migration to vg4 (BROKEN)
authorhgn <hgodden00@gmail.com>
Mon, 11 Aug 2025 20:38:38 +0000 (20:38 +0000)
committerhgn <hgodden00@gmail.com>
Mon, 11 Aug 2025 20:38:38 +0000 (20:38 +0000)
241 files changed:
.gitignore
build.c
build.sh
content_skaterift/boards/skaterift_fract/addon.inf [deleted file]
content_skaterift/boards/skaterift_fract/addon.kv [new file with mode: 0644]
content_skaterift/boards/skaterift_licco/addon.inf [deleted file]
content_skaterift/boards/skaterift_licco/addon.kv [new file with mode: 0644]
content_skaterift/boards/skaterift_long/addon.inf [deleted file]
content_skaterift/boards/skaterift_long/addon.kv [new file with mode: 0644]
content_skaterift/boards/skaterift_shark/addon.inf [deleted file]
content_skaterift/boards/skaterift_shark/addon.kv [new file with mode: 0644]
content_skaterift/boards/skaterift_spiral/addon.inf [deleted file]
content_skaterift/boards/skaterift_spiral/addon.kv [new file with mode: 0644]
content_skaterift/boards/skaterift_striped/addon.inf [deleted file]
content_skaterift/boards/skaterift_striped/addon.kv [new file with mode: 0644]
content_skaterift/maps/dev_flatworld/addon.inf [deleted file]
content_skaterift/maps/dev_flatworld/addon.kv [new file with mode: 0644]
content_skaterift/maps/dev_heaven/addon.inf [deleted file]
content_skaterift/maps/dev_heaven/addon.kv [new file with mode: 0644]
content_skaterift/maps/dev_hub/addon.inf [deleted file]
content_skaterift/maps/dev_hub/addon.kv [new file with mode: 0644]
content_skaterift/maps/dev_tutorial/addon.inf [deleted file]
content_skaterift/maps/dev_tutorial/addon.kv [new file with mode: 0644]
content_skaterift/maps/mp_line1/addon.inf [deleted file]
content_skaterift/maps/mp_line1/addon.kv [new file with mode: 0644]
content_skaterift/maps/mp_mtzero/addon.inf [deleted file]
content_skaterift/maps/mp_mtzero/addon.kv [new file with mode: 0644]
content_skaterift/maps/mp_spawn/addon.inf [deleted file]
content_skaterift/maps/mp_spawn/addon.kv [new file with mode: 0644]
content_skaterift/maps/vm/addon.inf [deleted file]
content_skaterift/maps/vm/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_aaron/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_aaron/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_amin/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_amin/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_chip/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_chip/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_ela/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_ela/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_fbi/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_fbi/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_fbi2/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_fbi2/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_j/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_jesus/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_jesus/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_john/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_john/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_jordan/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_jordan/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_new/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_new/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_outlaw/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_outlaw/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_president/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_president/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/skaterift_pro/addon.inf [deleted file]
content_skaterift/playermodels/skaterift_pro/addon.kv [new file with mode: 0644]
content_skaterift/playermodels/sr2t/addon.inf [deleted file]
content_skaterift/playermodels/sr2t/addon.kv [new file with mode: 0644]
control_overlay.h.c0 [deleted file]
shaders/common_scene.glsl
src/addon.c
src/addon.h
src/addon_types.c
src/addon_types.h
src/array_file.c
src/array_file.h
src/audio.c
src/audio.h
src/board_maker.c
src/board_maker.h
src/build_control_overlay.c [deleted file]
src/client.c
src/client.h
src/common.h [deleted file]
src/compass.c
src/compass.h
src/control_overlay.c
src/control_overlay.h
src/cutscene.c [new file with mode: 0644]
src/cutscene.h [new file with mode: 0644]
src/demo_check.c [new file with mode: 0644]
src/demo_check.h [new file with mode: 0644]
src/depth_compare.h
src/ent_atom.c
src/ent_atom.h
src/ent_camera.c
src/ent_camera.h
src/ent_challenge.c
src/ent_challenge.h
src/ent_cutscene.c
src/ent_cutscene.h
src/ent_glider.c
src/ent_glider.h
src/ent_list.c
src/ent_list.h
src/ent_npc.c
src/ent_npc.h
src/ent_objective.c
src/ent_objective.h
src/ent_prop.c
src/ent_prop.h
src/ent_region.c
src/ent_region.h
src/ent_relay.c
src/ent_relay.h
src/ent_route.c
src/ent_route.h
src/ent_script.c
src/ent_script.h
src/ent_skateshop.c
src/ent_skateshop.h
src/ent_tornado.c
src/ent_tornado.h
src/ent_traffic.c
src/ent_traffic.h
src/entity.c
src/entity.h
src/font.c [new file with mode: 0644]
src/font.h
src/freecam.c [deleted file]
src/freecam.h [deleted file]
src/gameserver.c
src/gameserver.h
src/gameserver_database.c
src/gameserver_monitor.c
src/gameserver_replay.c
src/gameserver_requests.c
src/gui.c [new file with mode: 0644]
src/gui.h
src/input.c [new file with mode: 0644]
src/input.h
src/menu.c
src/menu.h
src/metascene.c
src/metascene.h
src/model.c
src/model.h
src/network.c
src/network.h
src/network_common.h
src/network_compression.h
src/network_msg.h
src/network_requests.c
src/network_requests.h
src/particle.c
src/particle.h
src/physics_test.h [deleted file]
src/player.c
src/player.h
src/player_api.h
src/player_basic_info.c
src/player_basic_info.h
src/player_common.c
src/player_common.h
src/player_dead.c
src/player_dead.h
src/player_drive.c [deleted file]
src/player_drive.h [deleted file]
src/player_effects.c
src/player_effects.h
src/player_glide.c
src/player_glide.h
src/player_model.h [deleted file]
src/player_ragdoll.c
src/player_ragdoll.h
src/player_remote.c
src/player_remote.h
src/player_render.c
src/player_render.h
src/player_skate.c
src/player_skate.h
src/player_walk.c
src/player_walk.h
src/render.c
src/render.h
src/replay2.c
src/replay2.h
src/save.c
src/save.h
src/save2.c [new file with mode: 0644]
src/save2.h [new file with mode: 0644]
src/scene.c
src/scene.h
src/scene_rigidbody.c [new file with mode: 0644]
src/scene_rigidbody.h
src/scripts/board_maker.c
src/scripts/boost.c
src/scripts/explode.c
src/scripts/generic.c
src/scripts/l1_speed.c
src/scripts/tutorial_island.c
src/serialized_replay.h [deleted file]
src/shader_props.h
src/skaterift.c
src/skaterift.h [deleted file]
src/skaterift.hconf [new file with mode: 0644]
src/skaterift_script.c [deleted file]
src/skaterift_script.h [deleted file]
src/skeleton.h [deleted file]
src/traffic.h [deleted file]
src/trail.c
src/trail.h
src/unit_skaterift.c [new file with mode: 0644]
src/user_profile.c
src/user_profile.h
src/utest.c
src/vehicle.c
src/vehicle.h
src/workshop.c
src/workshop.h
src/world.c
src/world.h
src/world_audio.c
src/world_audio.h
src/world_entity.c
src/world_entity.h
src/world_gate.c
src/world_gate.h
src/world_gen.c
src/world_gen.h
src/world_info.h
src/world_load.c
src/world_load.h
src/world_map.c
src/world_map.h
src/world_physics.c
src/world_physics.h
src/world_render.c
src/world_render.h
src/world_routes.c
src/world_routes.h
src/world_routes_ui.c
src/world_routes_ui.h
src/world_sfd.c
src/world_sfd.h
src/world_volumes.c
src/world_volumes.h
src/world_water.c
src/world_water.h

index 7a84ac17d226e5a143ef669a67db9cce5b80e28e..a0eb0b89629108f844e1de653cbc16bf8cdb9e6f 100755 (executable)
@@ -17,6 +17,7 @@ dist/
 models_src/boards/workshop
 ccflags/png
 icons/png
+src.generated/
 
 # auto generated code
 shaders/*.h
diff --git a/build.c b/build.c
index bedb1e0739ea15ee5a99f1050c061d2bdb2a7022..a5150c3383bd5332e44da4233b8c71b082e05215 100644 (file)
--- a/build.c
+++ b/build.c
-#include "vg/vg_tool.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_log.h"
-#include "vg/vg_opt.h"
-#include "vg/vg_build.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_build_utils_shader.h"
-#include "vg/vg_msg.h"
-#include "src/addon_types.h"
+#define VG_BUILD_TOOLS
+#define VG_MATH
+#define VG_MSG_TO_KVS
+#include "vg/vg.hconf"
 
-#include "vg/vg_m.h"
-#include "src/model.h"
-#include "src/model.c"
-#include "src/array_file.c"
+#define VG_IMPLEMENTATION
+#include "vg/vg.hconf"
+#undef VG_IMPLEMENTATION
 
+#define VG_THIRDPARTY
+#include "vg/vg.hconf"
+#undef VG_THIRDPARTY
 
-/* 
- * Addon metadata utilities 
- * -------------------------------------------------------------------------- */
-
-void write_msg( vg_msg *msg, const char *path ){
-   FILE *fp = fopen( path, "wb" );
-   if( !fp ){
-      vg_error( "Cannot open %s for writing.\n", path );
-      exit(0);
-   }
+#define SR_MODEL
+#include "src/skaterift.hconf"
 
-   fwrite( msg->buf, msg->cur.co, 1, fp );
-   fclose( fp );
-   vg_success( "Written %s (%ub)\n", path, msg->cur );
-}
+#define SR_IMPLEMENTATION
+#include "src/skaterift.hconf"
+#undef SR_IMPLEMENTATION
 
-void write_generic_addon_inf( u32 type, const char *title,
-                              const char *content, const char *dest, u32 flags )
+void build_shaders(void)
 {
-   u8 descriptor_buf[ 512 ];
-   vg_msg descriptor = {0};
-   descriptor.buf = descriptor_buf;
-   descriptor.max = sizeof(descriptor_buf);
-   vg_msg_frame( &descriptor, "workshop" );
-      vg_msg_wkvstr( &descriptor, "title", title );
-      vg_msg_wkvstr( &descriptor, "author", "Skaterift" );
-      vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &type );
-   vg_msg_end_frame( &descriptor );
-   vg_msg_wkvstr( &descriptor, "content", content );
-   if( flags )
-      vg_msg_wkvnum( &descriptor, "flags", k_vg_msg_u32, 1, &flags );
-   write_msg( &descriptor, dest );
-}
-
-/*
- * Compilation specifications
- * -------------------------------------------------------------------------- */
+   vg_info( "Compiling shader headers\n" );
+   vg_shader_set_include_dir( "shaders" );
 
-/* operates in the local files, not in the bin folders */
-void build_game_metadata(void)
-{
-   vg_info( "Building game metadata\n" );
-   write_generic_addon_inf( k_addon_type_board, 
-                            "Longboard", "board.mdl", 
-                            "content_skaterift/boards/skaterift_long/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_board, 
-                            "Fractal", "board.mdl", 
-                            "content_skaterift/boards/skaterift_fract/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_board,
-                            "Striped", "board.mdl",
-                            "content_skaterift/boards/skaterift_striped/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_board,
-                            "Licco", "board.mdl",
-                            "content_skaterift/boards/skaterift_licco/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_board,
-                            "Hypno", "board.mdl",
-                            "content_skaterift/boards/skaterift_spiral/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_board,
-                            "Shark", "board.mdl",
-                            "content_skaterift/boards/skaterift_shark/addon.inf", 0 );
-
-   write_generic_addon_inf( k_addon_type_player,
-                            "De'folde", "ch_new.mdl",
-                            "content_skaterift/playermodels/skaterift_new/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Jordan", "ch_jordan.mdl",
-                            "content_skaterift/playermodels/skaterift_jordan/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Outlaw", "ch_outlaw.mdl",
-                            "content_skaterift/playermodels/skaterift_outlaw/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Chip", "ch_chip.mdl",
-                            "content_skaterift/playermodels/skaterift_chip/addon.inf", ADDON_REG_HIDDEN );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Aaron", "ch_aaron.mdl",
-                            "content_skaterift/playermodels/skaterift_aaron/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "JC", "ch_john.mdl",
-                            "content_skaterift/playermodels/skaterift_john/addon.inf", ADDON_REG_HIDDEN );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Ela", "ch_ela.mdl",
-                            "content_skaterift/playermodels/skaterift_ela/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Custom", "ch_sr2t.mdl",
-                            "content_skaterift/playermodels/sr2t/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Pro", "ch_pro.mdl",
-                            "content_skaterift/playermodels/skaterift_pro/addon.inf", 0 );
-   write_generic_addon_inf( k_addon_type_player,
-                            "Amin", "ch_amin.mdl",
-                            "content_skaterift/playermodels/skaterift_amin/addon.inf", 0 );
-
-   write_generic_addon_inf( k_addon_type_player,
-                            "Jesus", "ch_jesus.mdl",
-                            "content_skaterift/playermodels/skaterift_jesus/addon.inf", ADDON_REG_HIDDEN );
-   write_generic_addon_inf( k_addon_type_player,
-                            "FBI", "ch_fbi.mdl",
-                            "content_skaterift/playermodels/skaterift_fbi/addon.inf", ADDON_REG_HIDDEN );
-   write_generic_addon_inf( k_addon_type_player,
-                            "FBI2", "ch_fbi2.mdl",
-                            "content_skaterift/playermodels/skaterift_fbi2/addon.inf", ADDON_REG_HIDDEN );
-   write_generic_addon_inf( k_addon_type_player,
-                            "President", "ch_president.mdl",
-                            "content_skaterift/playermodels/skaterift_president/addon.inf", ADDON_REG_HIDDEN );
-
-   struct 
+   struct { c8 *name, *vs, *fs; } shaders[] = 
    {
-      const char *title, *location, *file;
-      u32 flags;
-   }
-   maps[] =
-   {
-      { "Mt.Zero Island", "Australia", "content_skaterift/maps/mp_mtzero/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_MTZERO | ADDON_REG_PREMIUM },
-      { "Flat World", "...", "content_skaterift/maps/dev_flatworld/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HIDDEN },
-      { "Heaven", "...", "content_skaterift/maps/dev_heaven/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HIDDEN },
-      { "Valley", "Cambodia", "content_skaterift/maps/mp_line1/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_VALLEY | ADDON_REG_PREMIUM },
-      { "Training Island", "Australia", "content_skaterift/maps/dev_tutorial/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_VOLC },
-      { "Center Island", "Australia", "content_skaterift/maps/dev_hub/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_HUB },
-      { "Downtown", "USA, Georgia", "content_skaterift/maps/mp_spawn/addon.inf", ADDON_REG_CAMPAIGN | ADDON_REG_CITY | ADDON_REG_PREMIUM },
-      { "Moon", "Venus", "content_skaterift/maps/vm/addon.inf", ADDON_REG_VENUS | ADDON_REG_PREMIUM },
+      /* TODO: We need to move this into a vg header */
+      { "debug_lines",              "vg/shaders/debug_lines.vs",        "vg/shaders/debug_lines.fs" },
+      { "debug_rigidbody",          "vg/shaders/rigidbody_view.vs",     "vg/shaders/rigidbody_view.fs" },
+      { "vgui",                     "vg/shaders/ui.vs",                 "vg/shaders/ui.fs" },
+      { "vgui_image",               "vg/shaders/ui_image.vs",           "vg/shaders/ui_image.fs" },
+      { "vgui_image_grad",          "vg/shaders/ui_image.vs",           "vg/shaders/ui_image_grad.fs" },
+      { "vgui_image_hsv",           "vg/shaders/ui_image.vs",           "vg/shaders/ui_image_hsv.fs" },
+      { "vgloader",                 "vg/shaders/blit.vs",               "vg/shaders/loader.fs" },
+
+      /* Scene */
+      { "scene_standard",           "shaders/scene.vs",           "shaders/scene_standard.fs" },
+      { "scene_standard_alphatest", "shaders/scene.vs",           "shaders/scene_standard_alphatest.fs" },
+      { "scene_foliage",            "shaders/scene_foliage.vs",   "shaders/scene_foliage.fs" },
+      { "scene_override",           "shaders/scene_override.vs",  "shaders/scene_override.fs" },
+      { "scene_preview",            "shaders/scene_override.vs",  "shaders/scene_preview.fs" },
+      { "scene_fxglow",             "shaders/scene_fxglow.vs",    "shaders/scene_fxglow.fs" },
+      { "scene_vertex_blend",       "shaders/scene.vs",           "shaders/scene_vertex_blend.fs" },
+      { "scene_terrain",            "shaders/scene.vs",           "shaders/scene_terrain.fs" },
+      { "scene_route",              "shaders/scene_override.vs",  "shaders/scene_route.fs" },
+      { "scene_depth",              "shaders/scene.vs",           "shaders/scene_depth.fs" },
+      { "scene_position",           "shaders/scene.vs",           "shaders/scene_position.fs" },
+      { "scene_cubemapped",         "shaders/scene.vs",           "shaders/scene_cubemapped.fs" },
+      { "scene_water",              "shaders/scene.vs",           "shaders/scene_water.fs" },
+      { "scene_water_fast",         "shaders/scene.vs",           "shaders/scene_water_fast.fs" },
+      { "scene_scoretext",          "shaders/scene_sfd.vs",       "shaders/scene_standard.fs" },
+      { "scene_font",               "shaders/model_font.vs",      "shaders/scene_font.fs" },
+
+      /* Models */
+      { "model_sky",                "shaders/model.vs",           "shaders/model_sky.fs" },
+      { "model_sky_space",          "shaders/model.vs",           "shaders/model_sky_space.fs" },
+      { "model_sky_cubemap",        "shaders/model_sky.vs",       "shaders/model_sky_cubemap.fs" },
+      { "model_menu",               "shaders/model.vs",           "shaders/model_menu.fs" },
+      { "model_character_view",     "shaders/model_skinned.vs",   "shaders/model_character_view.fs" },
+      { "model_board_view",         "shaders/model.vs",           "shaders/model_character_view.fs" },
+      { "model_entity",             "shaders/model.vs",           "shaders/model_entity.fs" },
+      { "model_gate",               "shaders/model.vs",           "shaders/model_gate_lq.fs" },
+      { "model_superworld",         "shaders/model.vs",           "shaders/model_superworld.fs" },
+      { "model_gate_unlinked",      "shaders/model.vs",           "shaders/model_gate_unlinked.fs" },
+      { "model_font",               "shaders/model_font.vs",      "shaders/model_font.fs" },
+
+      { "particle",                 "shaders/particle.vs",        "shaders/particle.fs" },
+      { "trail",                    "shaders/trail.vs",           "shaders/trail.fs" },
+
+      /* 2D */
+      { "workshop_compositor",      "shaders/workshop_compositor.vs",   "shaders/workshop_compositor.fs" },
+      { "blit",                     "vg/shaders/blit.vs",               "vg/shaders/blit_tex.fs" },
+      { "blitblur",                 "vg/shaders/blit.vs",               "vg/shaders/blit_blur.fs" },
+      { "blitcolour",               "vg/shaders/blit.vs",               "vg/shaders/blit_colour.fs" },
+      { "blit_transition",          "vg/shaders/blit.vs",               "shaders/blit_transition.fs" },
+      { "compass",                  "shaders/compass.vs",               "shaders/compass.fs" },
+      { "routeui",                  "shaders/routeui.vs",               "shaders/routeui.fs" },
    };
 
-   for( u32 i=0; i<VG_ARRAY_LEN(maps); i ++ )
-   {
-      u8 descriptor_buf[ 512 ];
-      vg_msg descriptor = {0};
-      descriptor.buf = descriptor_buf;
-      descriptor.max = sizeof(descriptor_buf);
-      vg_msg_frame( &descriptor, "workshop" );
-      {
-         vg_msg_wkvstr( &descriptor, "title", maps[i].title );
-         vg_msg_wkvstr( &descriptor, "author", "Skaterift" );
-         u32 type = k_addon_type_world;
-         vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &type );
-      }
-      vg_msg_end_frame( &descriptor );
-      vg_msg_wkvstr( &descriptor, "content", "main.mdl" );
-      if( maps[i].flags )
-         vg_msg_wkvnum( &descriptor, "flags", k_vg_msg_u32, 1, &maps[i].flags );
-      write_msg( &descriptor, maps[i].file );
-   }
-}
+   bool errors = 0;
 
-#define _S( NAME, VS, FS ) \
-   vg_build_shader( "shaders/" VS, "shaders/" FS, NULL, "shaders", NAME )
+   for( u32 i=0; i<VG_ARRAY_LEN(shaders); i ++ )
+      if( !vg_build_shader( shaders[i].vs, shaders[i].fs, NULL, shaders[i].name ) )
+         errors = 1;
 
-void build_shaders(void){
-   vg_info( "Compiling shader headers\n" );
-   vg_shader_set_include_dir( "shaders" );
+   if( errors )
+      exit(0);
 
-   /* Scene */
-   _S( "scene_standard",            "scene.vs", "scene_standard.fs" );
-   _S( "scene_standard_alphatest",  "scene.vs", "scene_standard_alphatest.fs" );
-   _S( "scene_foliage",             "scene_foliage.vs", "scene_foliage.fs" );
-   _S( "scene_override",            "scene_override.vs", "scene_override.fs" );
-   _S( "scene_preview",             "scene_override.vs", "scene_preview.fs" );
-   _S( "scene_fxglow",              "scene_fxglow.vs", "scene_fxglow.fs" );
-   _S( "scene_vertex_blend",        "scene.vs", "scene_vertex_blend.fs" );
-   _S( "scene_terrain",             "scene.vs", "scene_terrain.fs" );
-   _S( "scene_route",               "scene_override.vs", "scene_route.fs" );
-   _S( "scene_depth",               "scene.vs", "scene_depth.fs" );
-   _S( "scene_position",            "scene.vs", "scene_position.fs" );
-   _S( "scene_cubemapped",          "scene.vs", "scene_cubemapped.fs" );
-   _S( "scene_water",               "scene.vs", "scene_water.fs" );
-   _S( "scene_water_fast",          "scene.vs", "scene_water_fast.fs" );
-   _S( "scene_scoretext",           "scene_sfd.vs", "scene_standard.fs" );
-   _S( "scene_font",                "model_font.vs","scene_font.fs" );
-
-   /* Models */
-   _S( "model_sky",            "model.vs",         "model_sky.fs" );
-   _S( "model_sky_space",      "model.vs",         "model_sky_space.fs" );
-   _S( "model_sky_cubemap",    "model_sky.vs",     "model_sky_cubemap.fs" );
-   _S( "model_menu",           "model.vs",         "model_menu.fs" );
-   _S( "model_character_view", "model_skinned.vs", "model_character_view.fs" );
-   _S( "model_board_view",     "model.vs",         "model_character_view.fs" );
-   _S( "model_entity",         "model.vs",         "model_entity.fs" );
-   _S( "model_gate",           "model.vs",         "model_gate_lq.fs" );
-   _S( "model_superworld",     "model.vs",         "model_superworld.fs" );
-   _S( "model_gate_unlinked",  "model.vs",         "model_gate_unlinked.fs" );
-   _S( "model_font",           "model_font.vs",    "model_font.fs" );
-
-   _S( "particle", "particle.vs", "particle.fs" );
-   _S( "trail", "trail.vs", "trail.fs" );
-
-   /* 2D */
-   //_S( "blit",      "blit.vs",      "blit.fs" );
-   _S( "workshop_compositor", "workshop_compositor.vs", "workshop_compositor.fs" );
-   _S( "blitblur",  "blit.vs",      "blitblur.fs" );
-   _S( "blitcolour","blit.vs",      "colour.fs" );
-   _S( "compass","compass.vs",      "compass.fs" );
-   _S( "blit_transition", "blit.vs", "blit_transition.fs" );
-   _S( "routeui",   "routeui.vs",   "routeui.fs" );
-
-   vg_build_shader_impl( "shaders/impl.c" );
+   vg_build_shader_impl();
 }
 
-void build_game_content( struct vg_project *proj )
+void build_control_overlay(void)
 {
-   vg_symlink( proj, "content_skaterift/textures", "textures" );
-   vg_symlink( proj, "content_skaterift/models", "models" );
-   vg_symlink( proj, "content_skaterift/boards", "boards" );
-   vg_symlink( proj, "content_skaterift/maps", "maps" );
-   vg_symlink( proj, "content_skaterift/sound", "sound" );
-   vg_symlink( proj, "content_skaterift/playermodels", "playermodels" );
-   vg_symlink( proj, "content_skaterift/metascenes", "metascenes" );
-   vg_syscall( "mkdir -p bin/%s/cfg", proj->uid.buffer );
-   vg_syscall( "mkdir -p bin/%s/savedata", proj->uid.buffer );
-   vg_syscall( "mkdir -p bin/%s/tools", proj->uid.buffer );
-   vg_syscall( "cp bin/skaterift_blender.zip bin/%s/tools/", proj->uid.buffer );
+   FILE *hdr = fopen( "src.generated/control_overlay.h", "w" );
+   VG_ASSERT( hdr );
+
+   vg_stack_allocator stack;
+   vg_stack_init( &stack, NULL, VG_MB(8), "Model buffer" );
+
+   vg_model model;
+   VG_ASSERT( vg_model_load( &model, VG_MODEL_CPU_METADATA, "content_skaterift/models/rs_overlay.mdl", &stack ) );
+
+   for( u32 i=0; i<model.mesh_count; i ++ )
+   {
+      mdl_mesh *mesh = &model.meshes[ i ];
+      fprintf( hdr, "   %s = %u,\n", af_str( model.packed_strings, mesh->pstr_name ), mesh->submesh_start );
+   }
+   vg_stack_free( &stack );
+   fclose( hdr );
 }
-   
-#include "src/build_control_overlay.c"
 
 void build_game_bin( struct vg_project *proj, struct vg_compiler_env *env )
 {
@@ -234,12 +117,10 @@ void build_game_bin( struct vg_project *proj, struct vg_compiler_env *env )
    {
       meta = 1;
       build_shaders();
-      build_game_metadata();
+      build_control_overlay();
       vg_low( "\n\n" );
    }
 
-   build_control_overlay();
-
    struct vg_compiler_conf conf = {0};
 
    if( env->platform == k_platform_windows )
@@ -256,14 +137,63 @@ void build_game_bin( struct vg_project *proj, struct vg_compiler_env *env )
             .steam_api = 1,
             .use_3d = 1,
             .custom_game_settings = 0,
-            .custom_shaders = 1,
             .multiplayer = 1
          }, 
-         env, &conf, "src/client.c", "skaterift" );
+         env, &conf, "src/unit_skaterift.c", "skaterift" );
 
    vg_add_controller_database( proj );
+   vg_add_blob( proj, "steam_appid.txt", "" );
 }
 
+void build_game_content( struct vg_project *proj )
+{
+   vg_symlink( proj, "content_skaterift/textures", "textures" );
+   vg_symlink( proj, "content_skaterift/models", "models" );
+   vg_symlink( proj, "content_skaterift/boards", "boards" );
+   vg_symlink( proj, "content_skaterift/maps", "maps" );
+   vg_symlink( proj, "content_skaterift/sound", "sound" );
+   vg_symlink( proj, "content_skaterift/playermodels", "playermodels" );
+   vg_symlink( proj, "content_skaterift/metascenes", "metascenes" );
+   vg_syscall( "mkdir -p bin/%s/cfg", proj->uid.buffer );
+   vg_syscall( "mkdir -p bin/%s/savedata", proj->uid.buffer );
+   vg_syscall( "mkdir -p bin/%s/tools", proj->uid.buffer );
+   vg_syscall( "cp bin/skaterift_blender.zip bin/%s/tools/", proj->uid.buffer );
+}
+
+void vg_build_scripts(void)
+{
+   if( vg_long_opt( "skaterift", "Make skaterift" ) )
+   {
+      struct vg_project proj;
+      vg_project_init( &proj, "bin", "skaterift", NULL, 0 );
+
+      build_game_bin( &proj, &_vg_common_env );
+      build_game_content( &proj );
+      vg_add_blob( &proj, "steam_appid.txt", "" );
+   }
+}
+
+#if 0
+#include "vg/vg_tool.h"
+#include "vg/vg_platform.h"
+#include "vg/vg_log.h"
+#include "vg/vg_opt.h"
+#include "vg/vg_build.h"
+#include "vg/vg_mem_pool.h"
+#include "vg/vg_build_utils_shader.h"
+#include "vg/vg_msg.h"
+#include "src/addon_types.h"
+
+#include "vg/vg_m.h"
+#include "src/model.h"
+#include "src/model.c"
+#include "src/array_file.c"
+
+
+/* 
+ * Addon metadata utilities 
+ * -------------------------------------------------------------------------- */
+
 void build_crash_reporter( struct vg_project *proj, struct vg_compiler_env *env )
 {
    struct vg_compiler_conf conf = {0};
@@ -470,7 +400,6 @@ void s_utest_build(void)
             .log_source_info = 1,
             .use_3d = 0,
             .custom_game_settings = 0,
-            .custom_shaders = 0,
             .multiplayer = 0
          }, 
          env, &conf, "src/utest.c", "utest" );
@@ -511,10 +440,9 @@ void s_dbtest_build(void)
 
 int main( int argc, const char *argv[] )
 {
-   vg_log_init();
+   _vg_log_pre_init();
    _vg_opt_init( argc, argv );
 
-
    const char *arg;
 
    if( (arg = vg_long_opt_arg( "glsl-dir", "Specify output directory for preprocessed GLSL" )) )
@@ -566,3 +494,4 @@ int main( int argc, const char *argv[] )
 
    vg_success( "All scripts completed\n" );
 }
+#endif
index 4ad323cc9caea13a6106945dcb708258df0f7ef9..7f4e7b29233ae1ce3a5e75dfd1cddb31eebf8979 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -1 +1 @@
-clang -fsanitize=address -O0 -I. -I./vg build.c vg/vg_tool.c -o /tmp/tmpsr && /tmp/tmpsr $@
+zig cc -lasan -fsanitize=address -O0 -I. build.c -o /tmp/build_sr && /tmp/build_sr $@
diff --git a/content_skaterift/boards/skaterift_fract/addon.inf b/content_skaterift/boards/skaterift_fract/addon.inf
deleted file mode 100644 (file)
index 3c85c64..0000000
Binary files a/content_skaterift/boards/skaterift_fract/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_fract/addon.kv b/content_skaterift/boards/skaterift_fract/addon.kv
new file mode 100644 (file)
index 0000000..5c5b36a
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Fractal
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/boards/skaterift_licco/addon.inf b/content_skaterift/boards/skaterift_licco/addon.inf
deleted file mode 100644 (file)
index 0cb8f45..0000000
Binary files a/content_skaterift/boards/skaterift_licco/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_licco/addon.kv b/content_skaterift/boards/skaterift_licco/addon.kv
new file mode 100644 (file)
index 0000000..44c0a25
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Licco
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/boards/skaterift_long/addon.inf b/content_skaterift/boards/skaterift_long/addon.inf
deleted file mode 100644 (file)
index daf6b76..0000000
Binary files a/content_skaterift/boards/skaterift_long/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_long/addon.kv b/content_skaterift/boards/skaterift_long/addon.kv
new file mode 100644 (file)
index 0000000..f2e7248
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Longboard
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/boards/skaterift_shark/addon.inf b/content_skaterift/boards/skaterift_shark/addon.inf
deleted file mode 100644 (file)
index 7f8c3fc..0000000
Binary files a/content_skaterift/boards/skaterift_shark/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_shark/addon.kv b/content_skaterift/boards/skaterift_shark/addon.kv
new file mode 100644 (file)
index 0000000..bb06ef8
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Shark
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/boards/skaterift_spiral/addon.inf b/content_skaterift/boards/skaterift_spiral/addon.inf
deleted file mode 100644 (file)
index 6cc3ef5..0000000
Binary files a/content_skaterift/boards/skaterift_spiral/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_spiral/addon.kv b/content_skaterift/boards/skaterift_spiral/addon.kv
new file mode 100644 (file)
index 0000000..6f4da15
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Hypno
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/boards/skaterift_striped/addon.inf b/content_skaterift/boards/skaterift_striped/addon.inf
deleted file mode 100644 (file)
index 2c2ba4e..0000000
Binary files a/content_skaterift/boards/skaterift_striped/addon.inf and /dev/null differ
diff --git a/content_skaterift/boards/skaterift_striped/addon.kv b/content_skaterift/boards/skaterift_striped/addon.kv
new file mode 100644 (file)
index 0000000..94a5c96
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title Striped
+   author "Skate Rift"
+}
+
+content board.mdl
diff --git a/content_skaterift/maps/dev_flatworld/addon.inf b/content_skaterift/maps/dev_flatworld/addon.inf
deleted file mode 100644 (file)
index d4fef53..0000000
Binary files a/content_skaterift/maps/dev_flatworld/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/dev_flatworld/addon.kv b/content_skaterift/maps/dev_flatworld/addon.kv
new file mode 100644 (file)
index 0000000..16ba10e
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Flat World"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HIDDEN
+
+location Nowhere
diff --git a/content_skaterift/maps/dev_heaven/addon.inf b/content_skaterift/maps/dev_heaven/addon.inf
deleted file mode 100644 (file)
index 95f2519..0000000
Binary files a/content_skaterift/maps/dev_heaven/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/dev_heaven/addon.kv b/content_skaterift/maps/dev_heaven/addon.kv
new file mode 100644 (file)
index 0000000..c4aa0a8
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Heaven"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HIDDEN
+
+location Nowhere
diff --git a/content_skaterift/maps/dev_hub/addon.inf b/content_skaterift/maps/dev_hub/addon.inf
deleted file mode 100644 (file)
index 691e963..0000000
Binary files a/content_skaterift/maps/dev_hub/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/dev_hub/addon.kv b/content_skaterift/maps/dev_hub/addon.kv
new file mode 100644 (file)
index 0000000..de840d3
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Center Island"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|HUB
+
+location Australia
diff --git a/content_skaterift/maps/dev_tutorial/addon.inf b/content_skaterift/maps/dev_tutorial/addon.inf
deleted file mode 100644 (file)
index ae4c4b9..0000000
Binary files a/content_skaterift/maps/dev_tutorial/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/dev_tutorial/addon.kv b/content_skaterift/maps/dev_tutorial/addon.kv
new file mode 100644 (file)
index 0000000..410a9a5
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Training Island"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|VOLC
+
+location Australia
diff --git a/content_skaterift/maps/mp_line1/addon.inf b/content_skaterift/maps/mp_line1/addon.inf
deleted file mode 100644 (file)
index e7d0d6c..0000000
Binary files a/content_skaterift/maps/mp_line1/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/mp_line1/addon.kv b/content_skaterift/maps/mp_line1/addon.kv
new file mode 100644 (file)
index 0000000..e898856
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Valley"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|VALLEY|PREMIUM
+
+location Cambodia
diff --git a/content_skaterift/maps/mp_mtzero/addon.inf b/content_skaterift/maps/mp_mtzero/addon.inf
deleted file mode 100644 (file)
index 39fda55..0000000
Binary files a/content_skaterift/maps/mp_mtzero/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/mp_mtzero/addon.kv b/content_skaterift/maps/mp_mtzero/addon.kv
new file mode 100644 (file)
index 0000000..c0ab0c7
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Mt.Zero Island"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|MTZERO|PREMIUM
+
+location Australia
diff --git a/content_skaterift/maps/mp_spawn/addon.inf b/content_skaterift/maps/mp_spawn/addon.inf
deleted file mode 100644 (file)
index 79e6c26..0000000
Binary files a/content_skaterift/maps/mp_spawn/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/mp_spawn/addon.kv b/content_skaterift/maps/mp_spawn/addon.kv
new file mode 100644 (file)
index 0000000..1ff8634
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Downtown"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags CAMPAIGN|CITY|PREMIUM
+
+location USA
diff --git a/content_skaterift/maps/vm/addon.inf b/content_skaterift/maps/vm/addon.inf
deleted file mode 100644 (file)
index 0aa565c..0000000
Binary files a/content_skaterift/maps/vm/addon.inf and /dev/null differ
diff --git a/content_skaterift/maps/vm/addon.kv b/content_skaterift/maps/vm/addon.kv
new file mode 100644 (file)
index 0000000..000e56a
--- /dev/null
@@ -0,0 +1,10 @@
+workshop
+{
+   title "Moon"
+   author "Skate Rift"
+}
+
+content main.mdl
+flags VENUS|PREMIUM
+
+location Venus
diff --git a/content_skaterift/playermodels/skaterift_aaron/addon.inf b/content_skaterift/playermodels/skaterift_aaron/addon.inf
deleted file mode 100644 (file)
index f357ede..0000000
Binary files a/content_skaterift/playermodels/skaterift_aaron/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_aaron/addon.kv b/content_skaterift/playermodels/skaterift_aaron/addon.kv
new file mode 100644 (file)
index 0000000..a7a9feb
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Aaron"
+   author "Skate Rift"
+}
+
+content ch_aaron.mdl
diff --git a/content_skaterift/playermodels/skaterift_amin/addon.inf b/content_skaterift/playermodels/skaterift_amin/addon.inf
deleted file mode 100644 (file)
index 4cb227f..0000000
Binary files a/content_skaterift/playermodels/skaterift_amin/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_amin/addon.kv b/content_skaterift/playermodels/skaterift_amin/addon.kv
new file mode 100644 (file)
index 0000000..f329d81
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Amin"
+   author "Skate Rift"
+}
+
+content ch_amin.mdl
diff --git a/content_skaterift/playermodels/skaterift_chip/addon.inf b/content_skaterift/playermodels/skaterift_chip/addon.inf
deleted file mode 100644 (file)
index c8f4cbe..0000000
Binary files a/content_skaterift/playermodels/skaterift_chip/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_chip/addon.kv b/content_skaterift/playermodels/skaterift_chip/addon.kv
new file mode 100644 (file)
index 0000000..544607d
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "Chip"
+   author "Skate Rift"
+}
+
+content ch_chip.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_ela/addon.inf b/content_skaterift/playermodels/skaterift_ela/addon.inf
deleted file mode 100644 (file)
index 54f5411..0000000
Binary files a/content_skaterift/playermodels/skaterift_ela/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_ela/addon.kv b/content_skaterift/playermodels/skaterift_ela/addon.kv
new file mode 100644 (file)
index 0000000..da655f3
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Ela"
+   author "Skate Rift"
+}
+
+content ch_ela.mdl
diff --git a/content_skaterift/playermodels/skaterift_fbi/addon.inf b/content_skaterift/playermodels/skaterift_fbi/addon.inf
deleted file mode 100644 (file)
index 5961ecf..0000000
Binary files a/content_skaterift/playermodels/skaterift_fbi/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_fbi/addon.kv b/content_skaterift/playermodels/skaterift_fbi/addon.kv
new file mode 100644 (file)
index 0000000..6d8e89a
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "FBI"
+   author "Skate Rift"
+}
+
+content ch_fbi.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_fbi2/addon.inf b/content_skaterift/playermodels/skaterift_fbi2/addon.inf
deleted file mode 100644 (file)
index 0705e5d..0000000
Binary files a/content_skaterift/playermodels/skaterift_fbi2/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_fbi2/addon.kv b/content_skaterift/playermodels/skaterift_fbi2/addon.kv
new file mode 100644 (file)
index 0000000..c3c0288
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "FBI2"
+   author "Skate Rift"
+}
+
+content ch_fbi2.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_j/addon.inf b/content_skaterift/playermodels/skaterift_j/addon.inf
deleted file mode 100644 (file)
index 9e372d1..0000000
Binary files a/content_skaterift/playermodels/skaterift_j/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_jesus/addon.inf b/content_skaterift/playermodels/skaterift_jesus/addon.inf
deleted file mode 100644 (file)
index 18e258c..0000000
Binary files a/content_skaterift/playermodels/skaterift_jesus/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_jesus/addon.kv b/content_skaterift/playermodels/skaterift_jesus/addon.kv
new file mode 100644 (file)
index 0000000..b7fba83
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "Jesus"
+   author "Skate Rift"
+}
+
+content ch_jesus.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_john/addon.inf b/content_skaterift/playermodels/skaterift_john/addon.inf
deleted file mode 100644 (file)
index 1a03b82..0000000
Binary files a/content_skaterift/playermodels/skaterift_john/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_john/addon.kv b/content_skaterift/playermodels/skaterift_john/addon.kv
new file mode 100644 (file)
index 0000000..8646391
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "JC"
+   author "Skate Rift"
+}
+
+content ch_john.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_jordan/addon.inf b/content_skaterift/playermodels/skaterift_jordan/addon.inf
deleted file mode 100644 (file)
index 513da41..0000000
Binary files a/content_skaterift/playermodels/skaterift_jordan/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_jordan/addon.kv b/content_skaterift/playermodels/skaterift_jordan/addon.kv
new file mode 100644 (file)
index 0000000..be14a37
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Jordan"
+   author "Skate Rift"
+}
+
+content ch_jordan.mdl
diff --git a/content_skaterift/playermodels/skaterift_new/addon.inf b/content_skaterift/playermodels/skaterift_new/addon.inf
deleted file mode 100644 (file)
index 9a932a5..0000000
Binary files a/content_skaterift/playermodels/skaterift_new/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_new/addon.kv b/content_skaterift/playermodels/skaterift_new/addon.kv
new file mode 100644 (file)
index 0000000..097375a
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "De'folde"
+   author "Skate Rift"
+}
+
+content ch_new.mdl
diff --git a/content_skaterift/playermodels/skaterift_outlaw/addon.inf b/content_skaterift/playermodels/skaterift_outlaw/addon.inf
deleted file mode 100644 (file)
index 49e9bec..0000000
Binary files a/content_skaterift/playermodels/skaterift_outlaw/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_outlaw/addon.kv b/content_skaterift/playermodels/skaterift_outlaw/addon.kv
new file mode 100644 (file)
index 0000000..7a47e7f
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Outlaw"
+   author "Skate Rift"
+}
+
+content ch_outlaw.mdl
diff --git a/content_skaterift/playermodels/skaterift_president/addon.inf b/content_skaterift/playermodels/skaterift_president/addon.inf
deleted file mode 100644 (file)
index da72eec..0000000
Binary files a/content_skaterift/playermodels/skaterift_president/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_president/addon.kv b/content_skaterift/playermodels/skaterift_president/addon.kv
new file mode 100644 (file)
index 0000000..6ce9f36
--- /dev/null
@@ -0,0 +1,8 @@
+workshop
+{
+   title "President"
+   author "Skate Rift"
+}
+
+content ch_president.mdl
+flags HIDDEN
diff --git a/content_skaterift/playermodels/skaterift_pro/addon.inf b/content_skaterift/playermodels/skaterift_pro/addon.inf
deleted file mode 100644 (file)
index 22f2c6a..0000000
Binary files a/content_skaterift/playermodels/skaterift_pro/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/skaterift_pro/addon.kv b/content_skaterift/playermodels/skaterift_pro/addon.kv
new file mode 100644 (file)
index 0000000..46a5a86
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Pro"
+   author "Skate Rift"
+}
+
+content ch_pro.mdl
diff --git a/content_skaterift/playermodels/sr2t/addon.inf b/content_skaterift/playermodels/sr2t/addon.inf
deleted file mode 100644 (file)
index 6d79c74..0000000
Binary files a/content_skaterift/playermodels/sr2t/addon.inf and /dev/null differ
diff --git a/content_skaterift/playermodels/sr2t/addon.kv b/content_skaterift/playermodels/sr2t/addon.kv
new file mode 100644 (file)
index 0000000..f866bf2
--- /dev/null
@@ -0,0 +1,7 @@
+workshop
+{
+   title "Custom"
+   author "Skate Rift"
+}
+
+content ch_sr2t.mdl
diff --git a/control_overlay.h.c0 b/control_overlay.h.c0
deleted file mode 100644 (file)
index 115fbfc..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-   ov_carve_l = 0,
-   ov_y = 1,
-   ov_a = 2,
-   ov_b = 3,
-   ov_x = 4,
-   ov_ls = 5,
-   ov_key = 6,
-   ov_key_down = 7,
-   ov_shift = 8,
-   ov_shift_down = 9,
-   ov_space = 10,
-   ov_space_down = 11,
-   ov_text_jump = 12,
-   ov_jump_ind = 13,
-   ov_text_carve = 14,
-   ov_text_crouch = 15,
-   ov_stored_ind = 16,
-   ov_text_stored = 17,
-   ov_text_push = 18,
-   ov_text_left = 19,
-   ov_text_right = 20,
-   ov_text_manual = 21,
-   ov_text_front_flip = 22,
-   ov_text_back_flip = 23,
-   ov_text_w = 24,
-   ov_text_s = 25,
-   ov_text_shift = 26,
-   ov_text_grab = 27,
-   ov_key_fill = 28,
-   ov_shift_fill = 29,
-   ov_space_fill = 30,
-   ov_lmb = 31,
-   ov_rmb = 32,
-   ov_mouse = 33,
-   ov_text_shuvit = 34,
-   ov_text_kickflip = 35,
-   ov_text_treflip = 36,
-   ov_rmb_down = 37,
-   ov_lmb_down = 38,
-   ov_mouse_grabs = 39,
-   ov_text_walk = 40,
-   ov_text_back = 41,
-   ov_text_skate = 42,
-   ov_text_forward = 43,
-   ov_text_e = 44,
-   ov_text_glide = 45,
-   ov_text_walk_lwr = 46,
-   ov_text_camera = 47,
-   ov_text_run = 48,
-   ov_text_look = 49,
-   ov_text_rewind = 50,
-   ov_text_respawn = 51,
-   ov_ls_circ_walk = 52,
-   ov_rs_circ_look = 53,
-   ov_rs = 54,
-   ov_ls_circ_skate = 55,
-   ov_ls_circ_manual = 56,
-   ov_ls_circ_frontflip = 57,
-   ov_ls_circ_backflip = 58,
-   ov_rs_circ_grab = 59,
-   ov_lt = 60,
-   ov_lb = 61,
-   ov_carve_r = 62,
-   ov_lb_down = 63,
-   ov_rb = 64,
-   ov_rb_down = 65,
-   ov_lt_act = 66,
-   ov_rt = 67,
-   ov_rt_act = 68,
-   ov_lt_run = 69,
-   ov_rt_grab = 70,
-   ov_rt_crouch = 71,
-   ov_dpad = 72,
-   ov_text_dw_rewind = 73,
-   ov_text_a_shuvit = 74,
-   ov_text_b_kickflip = 75,
-   ov_text_x_treflip = 76,
-   ov_text_y_walk = 77,
-   ov_text_y_glide = 78,
-   ov_text_y_walk_lwr = 79,
-   ov_text_de_camera = 80,
-   ov_y_down = 81,
-   ov_a_down = 82,
-   ov_b_down = 83,
-   ov_x_down = 84,
-   ov_text_a_jump = 85,
-   ov_text_a_jump_mid = 86,
-   ov_text_b_push = 87,
-   ov_text_y_skate = 88,
-   ov_dpad_w = 89,
-   ov_dpad_n = 90,
-   ov_dpad_e = 91,
-   ov_dpad_s = 92,
-   ov_text_dn_respawn = 93,
-   ov_text_met_menu = 94,
-   ov_met_r = 95,
-   ov_met = 96,
-   ov_met_r_down = 97,
-   ov_met_l = 98,
-   ov_met_l_down = 99,
-   ov_text_menu = 100,
-   ov_key_menu = 101,
-   ov_key_menu_down = 102,
-   ov_y_ps = 103,
-   ov_a_ps = 104,
-   ov_b_ps = 105,
-   ov_x_ps = 106,
-   ov_y_down_ps = 107,
-   ov_a_down_ps = 108,
-   ov_b_down_ps = 109,
-   ov_x_down_ps = 110,
index 76658f2151aa1176439cea0d1489673131037d9d..3978a27686e53bb980b9173ff3057232e7f28514 100644 (file)
@@ -19,8 +19,7 @@ float sdLine( vec3 p, vec3 a, vec3 b )
 float compute_board_shadow()
 {
    // player shadow
-   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,
-                                                      g_board_1.xyz )-0.1 );
+   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz, g_board_1.xyz )-0.1 );
    float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );
    player_shadow *= player_shadow*player_shadow*player_shadow;
 
index c4180329803412ca736b2a3c3dc26113ffe0b7a4..0ed7edcf3c61f2183f144cc3fa5d887e4f6e10e1 100644 (file)
@@ -1,13 +1,3 @@
-#include "vg/vg_engine.h"
-#include "vg/vg_io.h"
-#include "vg/vg_loader.h"
-#include "addon.h"
-#include "addon_types.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-#include <string.h>
-
 struct _addon _addon;
 
 /* 
@@ -166,12 +156,29 @@ void addon_make_uid_cpart( addon_id id, char buf[ ADDON_UID_MAX ], char cpart[ A
       addon_reg *reg = addon_details(id);
       addon_alias *alias = &reg->alias;
 
-      if( alias->steam_workshop_id ) 
-         snprintf( buf, ADDON_UID_MAX, "sr%03d-steam-"PRINTF_U64"%s%s", alias->type, alias->steam_workshop_id, 
-                   cpart? ":": "", cpart? cpart: "" );
-      else                     
-         snprintf( buf, ADDON_UID_MAX, "sr%03d-local-%s%s%s", alias->type, alias->folder,
-                   cpart? ":": "", cpart? cpart: "" );
+      vg_str str_alias;
+      vg_strnull( &str_alias, buf, ADDON_UID_MAX );
+      vg_strcat( &str_alias, "sr" );
+      vg_strcati64r( &str_alias, alias->type, 10, 3, '0' );
+
+      if( alias->steam_workshop_id )
+      {
+         vg_strcat( &str_alias, "-steam-" );
+         vg_strcatu64( &str_alias, alias->steam_workshop_id, 10 );
+      }
+      else
+      {
+         vg_strcat( &str_alias, "-local-" );
+         vg_strcat( &str_alias, alias->folder );
+      }
+
+      if( cpart )
+      {
+         vg_strcat( &str_alias, ":" );
+         vg_strcat( &str_alias, cpart );
+      }
+
+      VG_ASSERT( vg_strgood( &str_alias ) );
    }
    else 
       buf[0] = '\0';
@@ -305,12 +312,10 @@ bool addon_parse_uid( const char *uid, addon_alias *alias )
    return 1;
 }
 
-void addon_system_init( void )
+VG_API void _addon_system_init(void)
 {
-   THREAD_1;
-
    u32 reg_size = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
-   _addon.registry = vg_stack_allocate( &vg.rtmem, reg_size, 8, "Addon Registry" );
+   _addon.registry = vg_stack_allocate( NULL, reg_size, 8, "Addon Registry" );
 
    for( u32 type=0; type<k_addon_type_max; type++ )
    {
@@ -321,15 +326,15 @@ void addon_system_init( void )
       {
          /* create the allocations pool */
          u32 alloc_size = sizeof(struct addon_cache_entry)*inf->cache_count;
-         cache->entries = vg_stack_allocate( &vg.rtmem, alloc_size, 8, "Cache entries" );
-         memset( cache->entries, 0, alloc_size );
-         vg_pool_init( &cache->pool, &cache->pool_unreferenced, inf->cache_count, &vg.rtmem );
+         cache->entries = vg_stack_allocate( NULL, alloc_size, 8, "Cache entries" );
+         vg_zero_mem( cache->entries, alloc_size );
+         vg_pool_init( &cache->pool, &cache->pool_unreferenced, inf->cache_count, NULL );
 
          /* create the real memory */
          u32 cache_size = inf->cache_stride*inf->cache_count;
-         cache->items = vg_stack_allocate( &vg.rtmem, cache_size, 8, "Cache data" );
+         cache->items = vg_stack_allocate( NULL, cache_size, 8, "Cache data" );
          cache->stride = inf->cache_stride;
-         memset( cache->items, 0, cache_size );
+         vg_zero_mem( cache->items, cache_size );
 
          for( i32 j=0; j<inf->cache_count; j++ )
          {
@@ -337,9 +342,7 @@ void addon_system_init( void )
             entry->addon_id = 0;
 
             if( inf->item_arena_size )
-               entry->item_arena = vg_stack_make_substack( &vg.rtmem, inf->item_arena_size, "Addon item arena" );
-            else
-               entry->item_arena = NULL;
+               vg_stack_init( &entry->item_arena, NULL, inf->item_arena_size, "Addon item arena" );
          }
       }
    }
@@ -347,38 +350,43 @@ void addon_system_init( void )
 
 static bool addon_try_load_metadata( addon_reg *reg, const char *folder_path )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    VG_ASSERT( reg );
 
    char path_buf[ 4096 ];
    vg_str meta_path;
    vg_strnull( &meta_path, path_buf, sizeof(path_buf) );
    vg_strcat( &meta_path, folder_path );
-   vg_strcat( &meta_path, "/addon.inf" );
-
+   vg_strcat( &meta_path, "/addon.kv" );
    if( !vg_strgood( &meta_path ) )
    {
       vg_error( "The metadata path is too long\n" );
       return 0;
    }
 
-   FILE *fp = fopen( meta_path.buffer, "rb" );
-   if( !fp )
-   {
-      vg_error( "Could not open the '%s'\n", meta_path.buffer );
-      return 0;
-   }
+   vg_kv_parser parser;
+   vg_kv_parser_init( &parser, &reg->metadata, 0 );
 
-   reg->metadata_len = fread( reg->metadata, 1, 512, fp );
-   if( !feof(fp) )
+   vg_stream file;
+   if( vg_file_stream_open( &file, path_buf, VG_STREAM_READ ) )
    {
-      fclose(fp);
-      vg_error( "Metadata too big\n" );
-      return 0;
+      vg_kv_parse_stream( &parser, &file );
+      vg_file_stream_close( &file );
+      return 1;
    }
-   fclose(fp);
+   else 
+   {
+      u32 size;
+      void *legacy_msg_buf = vg_file_read( NULL, path_buf, &size, 0 );
 
-   return 1;
+      if( legacy_msg_buf )
+      {
+         vg_kvs_append_from_legacy_msg2( &reg->metadata, 0, legacy_msg_buf, size );
+         vg_free( legacy_msg_buf );
+         return 1;
+      }
+      else return 0;
+   }
 }
 
 static addon_id addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_type type )
@@ -395,13 +403,15 @@ static addon_id addon_alloc_reg( PublishedFileId_t workshop_id, enum addon_type
 
    addon_reg *reg = &_addon.registry[ id-1 ];
    reg->flags = 0;
-   reg->metadata_len = 0;
    reg->cache_id = 0;
 
    memset( &reg->alias, 0, sizeof(addon_alias) );
    reg->alias.steam_workshop_id = workshop_id;
    reg->alias.type = type;
 
+   vg_stack_init( &reg->metadata_stack, NULL, VG_KB(8), "Addon metadata KV\n" );
+   vg_kvs_init( &reg->metadata, &reg->metadata_stack );
+
    if( workshop_id )
    {
 #if 0
@@ -437,7 +447,7 @@ static void addon_fail_allocation(void)
  */
 addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type type, const char *content_ext )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    u32 folder_name_length = 0;
    const char *folder_name = folder_path;
@@ -480,11 +490,8 @@ addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type
    bool loaded_metadata = addon_try_load_metadata( reg, folder_path );
    if( loaded_metadata )
    {
-      vg_msg msg;
-      vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
       u32 flags = 0x00;
-      vg_msg_getkvintg( &msg, "flags", k_vg_msg_u32, &flags, NULL );
+      vg_kv_read_vu32( &reg->metadata, 0, "flags", NULL, &flags, 1 );
       reg->flags |= ADDON_REG_MOUNTED | flags;
       addon_complete_allocation();
       return id;
@@ -506,14 +513,9 @@ addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type
       }
 
       /* create our own content commands */
-      vg_msg msg;
-      vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) );
-      vg_msg_frame( &msg, "workshop" );
-      {
-         vg_msg_wkvstr( &msg, "title", reg->alias.folder );
-         vg_msg_wkvstr( &msg, "author", "Custom Mod" );
-      }
-      vg_msg_end_frame( &msg );
+      u32 workshop_block = vg_kv_append( &reg->metadata, 0, "workshop", NULL );
+      vg_kv_append( &reg->metadata, workshop_block, "title", reg->alias.folder );
+      vg_kv_append( &reg->metadata, workshop_block, "author", "Custom Mod" );
 
       u32 content_count = 0;
       while( vg_dir_next_entry(&subdir) )
@@ -532,7 +534,8 @@ addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type
                continue;
             if( strcmp( ext, content_ext ) ) 
                continue;
-            vg_msg_wkvstr( &msg, "content", fname );
+
+            vg_kv_append( &reg->metadata, 0, "content", fname );
             content_count ++;
          }
       }
@@ -544,25 +547,15 @@ addon_id _addon_mount_from_folder_path( const char *folder_path, enum addon_type
          return 0;
       }
 
-      if( msg.error == k_vg_msg_error_OK )
-      {
-         reg->metadata_len = msg.cur.co;
-         reg->flags |= ADDON_REG_MOUNTED;
-         addon_complete_allocation();
-         return id;
-      }
-      else
-      {
-         vg_error( "Error creating metadata: %d\n", msg.error );
-         addon_fail_allocation();
-         return 0;
-      }
+      reg->flags |= ADDON_REG_MOUNTED;
+      addon_complete_allocation();
+      return id;
    }
 }
 
 void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    vg_info( "Mounting addons(type:%d) matching skaterift/%s/*/*%s\n", type, base_folder, content_ext );
 
@@ -609,19 +602,17 @@ void _addon_mount_content_folder( enum addon_type type, const char *base_folder,
 struct workshop_mount_info
 {
    u64 workshop_id;
-   char path[];
+   c8 path[4096];
 };
-static void workshop_mount_task( vg_async_task *task )
+static void workshop_mount_task( struct workshop_mount_info *in_args )
 {
-   THREAD_1;
-   struct workshop_mount_info *info = (void *)task->data;
-
-   addon_id id = addon_alloc_reg( info->workshop_id, k_addon_type_none );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   addon_id id = addon_alloc_reg( in_args->workshop_id, k_addon_type_none );
    if( !id )
       return;
 
    addon_reg *reg = &_addon.registry[ id-1 ];
-   bool loaded_metadata = addon_try_load_metadata( reg, info->path );
+   bool loaded_metadata = addon_try_load_metadata( reg, in_args->path );
 
    if( !loaded_metadata )
    {
@@ -629,12 +620,11 @@ static void workshop_mount_task( vg_async_task *task )
       return;
    }
 
-   enum addon_type type = k_addon_type_none;
-   vg_msg msg;
-   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
+   u32 type = k_addon_type_none;
 
-   if( vg_msg_seekframe( &msg, "workshop" ))
-      vg_msg_getkvintg( &msg, "type", k_vg_msg_u32, &type, NULL );
+   u32 workshop_block = vg_kv_find( &reg->metadata, 0, "workshop" );
+   if( workshop_block )
+      vg_kv_read_vu32( &reg->metadata, workshop_block, "type", NULL, &type, 1 );
 
    if( type == k_addon_type_none )
    {
@@ -648,52 +638,11 @@ static void workshop_mount_task( vg_async_task *task )
    addon_complete_allocation();
 }
 
-struct workshop_scan_info
-{
-   enum workshop_scan_state
-   {
-      k_workshop_scan_state_filter_mounted,
-      k_workshop_scan_state_mount
-   }
-   state;
-
-   u32 count;
-   PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
-};
-static void workshop_scan_t1( vg_async_task *co_task )
-{
-   THREAD_1;
-   struct workshop_scan_info *co_info = (void *)co_task->data;
-
-   if( co_info->state == k_workshop_scan_state_filter_mounted )
-   {
-      vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct workshop_scan_info), 1 );
-      struct workshop_scan_info *info = (void *)task->data;
-      info->state = k_workshop_scan_state_mount;
-
-      u32 send_count = 0;
-      for( u32 i=0; i<co_info->count; i ++ )
-      {
-         for( u32 j=0; j<_addon.registry_count; j ++ )
-         {
-            if( _addon.registry[j].alias.steam_workshop_id == co_info->workshop_ids[i] )
-               goto s1;
-         }
-         
-         info->workshop_ids[ send_count ++ ] = co_info->workshop_ids[i];
-s1:;
-      }
-
-      info->count = send_count;
-      vg_async_task_dispatch( task, _mount_workshop_addons );
-   }
-}
-
-void _mount_workshop_addons( vg_async_task *co_task )
+VG_API void _mount_workshop_addons(void)
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
-   if( g_client.demo_mode )
+   if( _is_running_demo() )
    {
       vg_info( "Won't load workshop items in demo mode\n" );
       return;
@@ -702,58 +651,48 @@ void _mount_workshop_addons( vg_async_task *co_task )
    if( _steam_api.disabled )
       return;
 
-   if( !co_task )
-   {
-      vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_scan_info), 1 );
-      struct workshop_scan_info *info = (void *)task->data;
-      info->state = k_workshop_scan_state_filter_mounted;
 
-      u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( _steam_api.pSteamUGC, info->workshop_ids, ADDON_MOUNTED_MAX, 0 );
-      vg_info( "Found %u subscribed items\n", count );
+   PublishedFileId_t workshop_ids[ ADDON_MOUNTED_MAX ];
+   u32 count = SteamAPI_ISteamUGC_GetSubscribedItems( _steam_api.pSteamUGC, workshop_ids, ADDON_MOUNTED_MAX, 0 );
+   vg_info( "Found %u subscribed items\n", count );
 
-      u32 send_count = 0;
+   for( u32 i=0; i<count; i++ )
+   {
+      u32 state = SteamAPI_ISteamUGC_GetItemState( _steam_api.pSteamUGC, workshop_ids[i] );
+      if( !(state & k_EItemStateInstalled) )
+         continue;
 
-      for( u32 i=0; i<count; i++ )
+      /* check if already installed, TODO: hash this?.. O(N^2) */
+      bool mounted = 0;
+      for( u32 j=0; j<_addon.registry_count; j ++ )
       {
-         u32 state = SteamAPI_ISteamUGC_GetItemState( _steam_api.pSteamUGC, info->workshop_ids[i] );
-         if( !(state & k_EItemStateInstalled) )
-            continue;
-
-         info->workshop_ids[ send_count ++ ] = info->workshop_ids[i];
+         if( _addon.registry[j].alias.steam_workshop_id == workshop_ids[i] )
+         {
+            mounted = 1;
+            break;
+         }
       }
-
-      info->count = send_count;
-      vg_async_task_dispatch( task, workshop_scan_t1 );
-   }
-   else
-   {
-      struct workshop_scan_info *co_info = (void *)co_task->data;
-      for( u32 i=0; i<co_info->count; i ++ )
+      
+      if( !mounted )
       {
-         char path[ 4096 ];
-
+         struct workshop_mount_info *out_args = _vg_async_alloc(VG_THREAD_ASYNC_ID, sizeof(struct workshop_mount_info));
+         out_args->workshop_id = workshop_ids[i];
          u64 _size;
          u32 _ts;
-         if( !SteamAPI_ISteamUGC_GetItemInstallInfo( _steam_api.pSteamUGC, co_info->workshop_ids[i], 
-                                                     &_size, path, sizeof(path), &_ts ))
+         if( !SteamAPI_ISteamUGC_GetItemInstallInfo( _steam_api.pSteamUGC, workshop_ids[i], 
+                                                     &_size, out_args->path, sizeof(out_args->path), &_ts ))
          {
-            vg_error( "GetItemInstallInfo failed for addon %lu\n", co_info->workshop_ids[i] );
+            vg_error( "GetItemInstallInfo failed for addon %lu\n", workshop_ids[i] );
             continue;
          }
-
-         u32 len = strlen( path );
-         vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct workshop_mount_info)+len+1, 1 );
-         struct workshop_mount_info *info = (void *)task->data;
-         strcpy( info->path, path );
-         info->workshop_id = co_info->workshop_ids[i];
-         vg_async_task_dispatch( task, workshop_mount_task );
+         _vg_async_send( out_args, (vg_async_fn)workshop_mount_task );
       }
    }
 }
 
 bool addon_get_content_folder( addon_id addon_id, vg_str *folder )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    VG_ASSERT( addon_id );
 
    addon_reg *reg = addon_details( addon_id );
@@ -768,7 +707,7 @@ bool addon_get_content_folder( addon_id addon_id, vg_str *folder )
          return 0;
       }
 
-      folder->i = strlen( folder->buffer );
+      folder->i = vg_strlen( folder->buffer );
       return 1;
    }
    else
@@ -789,41 +728,36 @@ struct cache_complete_info
    addon_cache_id cache_id;
    enum addon_cache_state result_state;
 };
-static void cache_load_complete( vg_async_task *task )
+static void cache_load_complete( struct cache_complete_info *in_args )
 {
-   THREAD_0;
-   struct cache_complete_info *info = (void *)task->data;
-   struct addon_cache *cache = &_addon.cache[info->type];
-   cache->entries[ vg_pool_index( &cache->pool, info->cache_id ) ].state = info->result_state;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   struct addon_cache *cache = &_addon.cache[in_args->type];
+   cache->entries[ vg_pool_index( &cache->pool, in_args->cache_id ) ].state = in_args->result_state;
 }
 
 struct cache_load_info
 {
    enum addon_type type;
    addon_cache_id cache_id;
-
-   char path[];
+   char path[4096];
 };
-static void cache_load_task( vg_async_task *task )
+static void cache_load_task( struct cache_load_info *in_args )
 {
-   THREAD_1;
-   struct cache_load_info *info = (void *)task->data;
-   addon_cache_entry *cache_entry = get_addon_cache_entry( info->type, info->cache_id );
-   vg_info( "process cache load request (%u#%u): %s\n", info->type, info->cache_id, info->path );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   addon_cache_entry *cache_entry = get_addon_cache_entry( in_args->type, in_args->cache_id );
+   vg_info( "process cache load request (%u#%u): %s\n", in_args->type, in_args->cache_id, in_args->path );
+   
+   enum addon_cache_state result_state = k_addon_cache_state_errored;
 
    /* load content files
     * --------------------------------- */
    char path_buf[4096];
    vg_str content_path;
    vg_strnull( &content_path, path_buf, sizeof(path_buf) );
-   vg_strcat( &content_path, info->path );
+   vg_strcat( &content_path, in_args->path );
 
    addon_reg *reg = addon_details( cache_entry->addon_id );
-   vg_msg msg;
-   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-   enum addon_cache_state result_state = k_addon_cache_state_errored;
-
-   const char *kv_content = vg_msg_getkvstr( &msg, "content" );
+   const c8 *kv_content = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, 0, "content" ), NULL );
    if( kv_content )
    {
       vg_strcat( &content_path, "/" );
@@ -840,30 +774,29 @@ static void cache_load_task( vg_async_task *task )
       vg_error( "   Metadata path too long\n" );
       goto e0;
    }
-   
-   vg_stack_allocator *arena = cache_entry->item_arena;
-   if( info->type == k_addon_type_board )
+
+   vg_stack_allocator *arena = &cache_entry->item_arena;
+   if( in_args->type == k_addon_type_board )
    {
-      struct player_board *board = addon_cache_item_data( info->type, info->cache_id, 0 );
+      struct player_board *board = addon_cache_item_data( in_args->type, in_args->cache_id, 0 );
       vg_stack_clear( arena );
       player_board_load( board, content_path.buffer, arena );
       result_state = k_addon_cache_state_loaded;
    }
-   else if( info->type == k_addon_type_player )
+   else if( in_args->type == k_addon_type_player )
    {
-      struct player_model *model = addon_cache_item_data( info->type, info->cache_id, 0 );
+      struct player_model *model = addon_cache_item_data( in_args->type, in_args->cache_id, 0 );
       vg_stack_clear( arena );
       player_model_load( model, content_path.buffer, arena );
       result_state = k_addon_cache_state_loaded;
    }
 
 e0:;
-   vg_async_task *res_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct cache_complete_info), 1 );
-   struct cache_complete_info *complete_info = (void *)res_task->data;
-   complete_info->type = info->type;
-   complete_info->cache_id = info->cache_id;
-   complete_info->result_state = result_state;
-   vg_async_task_dispatch( res_task, cache_load_complete );
+   struct cache_complete_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct cache_complete_info) );
+   out_args->type = in_args->type;
+   out_args->cache_id = in_args->cache_id;
+   out_args->result_state = result_state;
+   _vg_async_send( out_args, (vg_async_fn)cache_load_complete );
 }
 
 /*
@@ -882,25 +815,22 @@ void _addon_system_pre_update(void)
          addon_cache_entry *entry = &cache->entries[ vg_pool_index( &cache->pool, id ) ];
          if( entry->state == k_addon_cache_state_load_request )
          {
-            char path_buf[4096];
+            struct cache_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct cache_load_info) );
             vg_str folder;
-            vg_strnull( &folder, path_buf, 4096 );
+            vg_strnull( &folder, out_args->path, sizeof(out_args->path) );
+
             if( !addon_get_content_folder( entry->addon_id, &folder ) )
             {
+               _vg_async_send( out_args, NULL );
                entry->state = k_addon_cache_state_errored;
                continue;
             }
             
-            u32 len = strlen( path_buf ) + 1;
-            vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cache_load_info) + len, 1 );
-            struct cache_load_info *info = (void *)task->data;
-
-            info->type = type;
-            info->cache_id = id;
-            strcpy( info->path, path_buf );
-
+            out_args->type = type;
+            out_args->cache_id = id;
             entry->state = k_addon_cache_state_loading;
-            vg_async_task_dispatch( task, cache_load_task );
+            _vg_async_send( out_args, (vg_async_fn)cache_load_task );
+
          }
          id = vg_pool_next( &cache->pool, id, 0 );
       }
@@ -927,7 +857,7 @@ void *addon_cache_item_data( enum addon_type type, addon_cache_id cache_id, bool
 
 addon_cache_id addon_cache_create_viewer( enum addon_type type, addon_id addon_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( !addon_id )
       return 0;
@@ -993,7 +923,7 @@ addon_id addon_get_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX]
 
 addon_cache_id addon_cache_create_viewer_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    addon_id id = addon_get_from_uid( type, uid );
    if( id )
@@ -1007,7 +937,7 @@ addon_cache_id addon_cache_create_viewer_from_uid( enum addon_type type, const c
 
 void addon_cache_watch( enum addon_type type, addon_cache_id cache_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( !cache_id ) 
       return;
@@ -1019,7 +949,7 @@ void addon_cache_watch( enum addon_type type, addon_cache_id cache_id )
 
 void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( !cache_id ) 
       return;
index 901e667b9d13d7d51c364c11fa4274af29fd2488..f3da438b5fec890818404d05434c8261082378d6 100644 (file)
@@ -1,9 +1,6 @@
-#pragma once
-#include "vg/vg_steam2.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_string.h"
-#include "addon_types.h"
-#include "vg/vg_mutex.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/addon.c"
+#else
 
 typedef struct addon_reg addon_reg;
 typedef struct addon_cache_entry addon_cache_entry;
@@ -25,8 +22,9 @@ struct _addon
       addon_alias alias;
       u32 alias_hash;
 
-      u8 metadata[512];  /* vg_msg buffer */
-      u32 metadata_len;
+      vg_stack_allocator metadata_stack;
+      vg_kvs metadata;
+
       u32 flags;
       addon_cache_id cache_id;
    }
@@ -50,7 +48,7 @@ struct _addon
          state;
 
          char local_cpart[ ADDON_CPART_MAX ];
-         vg_stack_allocator *item_arena;
+         vg_stack_allocator item_arena;
       }
       *entries;
       vg_pool pool;
@@ -63,7 +61,7 @@ struct _addon
 }
 extern _addon;
 
-void addon_system_init( void );
+VG_API void _addon_system_init(void);
 
 addon_reg *addon_details( addon_id id );
 u32 _addon_filtered_count( enum addon_type type, u32 whitelist, u32 blacklist );
@@ -84,7 +82,7 @@ bool addon_get_content_folder( addon_id addon_id, vg_str *folder );
 addon_id _addon_mount_from_folder_path( const char *folder, enum addon_type type, const char *content_ext );
 
 void _addon_mount_content_folder( enum addon_type type, const char *base_folder, const char *content_ext );
-void _mount_workshop_addons( vg_async_task *co_task );
+VG_API void _mount_workshop_addons(void);
 
 void _addon_system_pre_update(void);
 addon_id addon_get_from_uid( enum addon_type type, const char uid[ADDON_UID_MAX] );
@@ -94,3 +92,5 @@ void addon_cache_watch( enum addon_type type, addon_cache_id cache_id );
 void addon_cache_unwatch( enum addon_type type, addon_cache_id cache_id );
 void *addon_cache_item_data( enum addon_type type, addon_cache_id cache_id, bool only_if_loaded );
 addon_cache_entry *get_addon_cache_entry( enum addon_type type, u16 cache_id );
+
+#endif
index 32186ade53175ef2953d1f3282f05aafa3cbf602..b392de50efed83717d1561bbfc80e70cb495c3ee 100644 (file)
@@ -1,7 +1,3 @@
-#include "player.h"
-#include "player_render.h"
-#include "player_api.h"
-
 struct addon_type_info addon_type_infos[] = 
 {
    [k_addon_type_board] = { 
index e54fc74cae6da370fb2fe4632b6d88250257f955..df05d09b7cf4e5d405dd23499dbb2087cfda59a5 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/addon_types.c"
+#else
 
 enum addon_type{
    k_addon_type_none   = 0,
@@ -44,3 +46,4 @@ struct addon_type_info
 extern addon_type_infos[];
 
 #endif
+#endif
index f97988e55123fa3f18113b31536919d478d48d3a..7b0a63a90a40e38859e5a2bc4f4e0a1d225d28d3 100644 (file)
@@ -1,90 +1,55 @@
-#include "array_file.h"
-#include <errno.h>
-
-u32 af_str_hash( array_file_context *af, u32 pstr )
+VG_TIER_0 u32 af_str_hash( const void *packed_strings, u32 pstr )
 {
    if( pstr & 0x3 )
       vg_fatal_error( "ALIGNMENT ERROR (%u)\n", pstr );
-
-   return *((u32 *)(af->strings + pstr));
+   return *((u32 *)(packed_strings + pstr));
 }
 
-const char *af_str( array_file_context *af, u32 pstr )
+VG_TIER_0 const c8 *af_str( const void *packed_strings, u32 pstr )
 {
-   return af->strings + pstr + 4;
+   return packed_strings + pstr + 4;
 }
 
-bool af_str_eq( array_file_context *af, u32 pstr, const char *str, u32 str_hash )
+VG_TIER_0 bool af_str_eq( const void *packed_strings, u32 pstr, const c8 *str, u32 str_hash )
 {
-   if( af_str_hash( af, pstr ) == str_hash )
-      if( !strcmp( str, af_str( af, pstr ))) 
+   if( af_str_hash( packed_strings, pstr ) == str_hash )
+      if( !strcmp( str, af_str( packed_strings, pstr ))) 
          return 1;
 
    return 0;
 }
 
-static void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride )
+VG_TIER_0 void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride )
 {
    if( arr->item_count )
    {
-      fseek( ctx->fp, arr->file_offset, SEEK_SET );
-
-      if( stride == arr->item_size )
-      {
-         u64 l = fread( buffer, arr->item_size*arr->item_count, 1, ctx->fp );
-         if( l != 1 ) 
-         {
-            vg_file_error_info( ctx->fp );
-            fclose( ctx->fp );
-            vg_fatal_error( "AF file buffer error\n" );
-         }
-      }
-      else 
+      vg_zero_mem( buffer, stride*arr->item_count );
+      u32 read_size = VG_MIN( stride, arr->item_size );
+      for( u32 i=0; i<arr->item_count; i++ )
       {
-         vg_warn( "Applying alignment fixup to array '%s' [%u -> %u] x %u\n", 
-                  arr->name, arr->item_size, stride, arr->item_count );
-
-         if( stride > arr->item_size )
-            memset( buffer, 0, stride*arr->item_count );
-
-         u32 read_size = VG_MIN( stride, arr->item_size );
-
-         for( u32 i=0; i<arr->item_count; i++ )
-         {
-            u64 l = fread( buffer+i*stride, read_size, 1, ctx->fp );
-            if( stride < arr->item_size )
-               fseek( ctx->fp, arr->item_size - stride, SEEK_CUR );
-
-            if( l != 1 ) 
-            {
-               vg_file_error_info( ctx->fp );
-               fclose( ctx->fp );
-               vg_fatal_error( "AF read arror\n" );
-            }
-         }
+         vg_stream_seek( ctx->stream, arr->file_offset + i*arr->item_size );
+         vg_stream_read( ctx->stream, buffer+i*stride, read_size );
       }
    }
 }
 
-void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr, 
-                         array_file_meta *arr, vg_stack_allocator *stack, u32 stride )
+VG_TIER_1 void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr, 
+                                   array_file_meta *arr, vg_stack_allocator *stack, u32 stride )
 {
    if( arr->item_count )
    {
       u32 size = stride*arr->item_count;
-      out_ptr->data = stack? vg_stack_allocate( stack, size, 8, NULL ): malloc( size );
+      out_ptr->data = vg_stack_allocate( stack, size, 8, NULL );
       af_load_array_file_buffer( ctx, arr, out_ptr->data, stride );
    }
    else
-   {
       out_ptr->data = NULL;
-   }
    
    out_ptr->stride = stride;
    out_ptr->count = arr->item_count;
 }
 
-void *af_arritm( array_file_ptr *arr, u32 index )
+VG_TIER_0 void *af_arritm( array_file_ptr *arr, u32 index )
 {
    if( index >= arr->count )
       vg_fatal_error( "Index out of range (%u >= %u)\n", index, arr->count );
@@ -92,12 +57,12 @@ void *af_arritm( array_file_ptr *arr, u32 index )
    return ((u8 *)arr->data) + index*arr->stride;
 }
 
-u32 af_arrcount( array_file_ptr *arr )
+VG_TIER_0 u32 af_arrcount( array_file_ptr *arr )
 {
    return arr->count;
 }
 
-array_file_meta *af_find_array( array_file_context *ctx, const char *name )
+VG_TIER_0 array_file_meta *af_find_array( array_file_context *ctx, const c8 *name )
 {
    for( u32 i=0; i<af_arrcount(&ctx->index); i++ )
    {
@@ -110,7 +75,8 @@ array_file_meta *af_find_array( array_file_context *ctx, const char *name )
    return NULL;
 }
 
-int af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride )
+VG_TIER_1 bool af_load_array( array_file_context *ctx, array_file_ptr *ptr, const c8 *name, 
+                              vg_stack_allocator *stack, u32 stride )
 {
    array_file_meta *arr = af_find_array( ctx, name );
 
@@ -128,45 +94,30 @@ int af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *nam
    }
 }
 
-void af_open( array_file_context *ctx, const char *path, u32 min_version, u32 max_version, vg_stack_allocator *stack )
+VG_TIER_1 bool af_open_stream( array_file_context *afc, vg_stream *stream, u32 min_version, u32 max_version, 
+                               vg_stack_allocator *stack )
 {
-   ctx->fp = fopen( path, "rb" );
-   if( !ctx->fp )
-      vg_fatal_error( "open('%s'): %s\n", path, strerror(errno) );
-
-   u64 l = fread( &ctx->header, sizeof(array_file_header), 1, ctx->fp );
-   if( l != 1 )
+   afc->stream = stream;
+   if( vg_stream_read( stream, &afc->header, sizeof(array_file_header)) != sizeof(array_file_header) )
    {
-      fclose( ctx->fp );
-      vg_fatal_error( "Array file corrupt\n" );
+      vg_error( "Array file not large enough to contain header.\n" );
+      return 0;
    }
 
-   if( ctx->header.version < min_version || ctx->header.version > max_version )
+   if( (afc->header.version < min_version) || (afc->header.version > max_version) )
    {
-      vg_info( "Legacy model version incompatable" );
-      vg_info( "For model: %s\n", path );
-      vg_info( "  version: %u (min: %u, max: %u)\n", 
-               ctx->header.version, min_version, max_version );
-      fclose( ctx->fp );
-      vg_fatal_error( "Legacy\n" );
+      vg_error( "Array file version out of range\n" );
+      vg_error( "  version: %u (min: %u, max: %u)\n", afc->header.version, min_version, max_version );
+      return 0;
    }
 
-   af_load_array_file( ctx, &ctx->index, &ctx->header.index, stack, sizeof(array_file_meta) );
-
-   array_file_ptr strings;
-   af_load_array( ctx, &strings, "strings", stack, 1 );
-   ctx->strings = strings.data;
-}
-
-void af_close( array_file_context *ctx )
-{
-   fclose( ctx->fp );
-   ctx->fp = NULL;
+   af_load_array_file( afc, &afc->index, &afc->header.index, stack, sizeof(array_file_meta) );
+   return 1;
 }
 
 /* compiler
  * ---------------------------------------------------------------------- */
-
+#if defined( VG_ENGINE )
 struct af_compiler_iter
 {
    u32 i, j;
@@ -210,7 +161,7 @@ static bool af_next( struct af_compiler_iter *iter )
 
 af_compiler_item *af_compiler_allocate_items( af_compiler *compiler, af_compiler_index *index, u32 count )
 {
-   af_compiler_item *entry = VG_STACK_ALLOCATE_STRUCT( compiler->stack, af_compiler_item );
+   af_compiler_item *entry = vg_stack_allocate( compiler->stack, sizeof(af_compiler_item), 1, "Compiler item" );
    entry->next = NULL;
 
    u32 data_size = count * index->element_size;
@@ -276,7 +227,7 @@ static void af_write_bin( af_compiler *compiler, void *data, u32 data_len, u32 p
 {
    if( data )
    {
-      fwrite( data, data_len, 1, compiler->fp );
+      vg_stream_write( &compiler->stream, data, data_len );
       compiler->file_offset += data_len;
    }
 
@@ -285,7 +236,7 @@ static void af_write_bin( af_compiler *compiler, void *data, u32 data_len, u32 p
       while( compiler->file_offset % padding )
       {
          const u8 pad_byte = 0xac;
-         fwrite( &pad_byte, 1, 1, compiler->fp );
+         vg_stream_write( &compiler->stream, &pad_byte, 1 );
          compiler->file_offset ++;
       }
    }
@@ -324,9 +275,8 @@ bool af_write( af_compiler *compiler, const char *path, u32 version )
 
    u32 header_size = vg_align8( sizeof( array_file_header ) );
    u32 index_size = vg_align8( sizeof( array_file_meta ) * indices_to_write );
-
-   compiler->fp = fopen( path, "wb" );
-   if( !compiler->fp )
+   
+   if( !vg_file_stream_open( &compiler->stream, path, VG_STREAM_WRITE ) )
       return 0;
    compiler->file_offset = 0;
 
@@ -377,6 +327,7 @@ bool af_write( af_compiler *compiler, const char *path, u32 version )
       }
    }
 
-   fclose( compiler->fp );
+   vg_file_stream_close( &compiler->stream );
    return 1;
 }
+#endif
index f67337fe856d736849490745d1f9895670ca6c92..7c6d1d2338bf41c1ea1a4baa6c03cc88193a3d76 100644 (file)
@@ -1,5 +1,6 @@
-#pragma once
-#include "vg_mem.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/array_file.c"
+#else
 
 typedef struct array_file_ptr array_file_ptr;
 typedef struct array_file_meta array_file_meta;
@@ -28,20 +29,19 @@ struct array_file_header
 
 struct array_file_context
 {
-   FILE *fp;
+   vg_stream *stream;
    array_file_header header;
    array_file_ptr index;
-   const void *strings;
 };
 
-void af_open( array_file_context *ctx, const char *path, u32 min_version, u32 max_version, vg_stack_allocator *stack );
-void af_close( array_file_context *ctx );
-
 /* array loading */
-array_file_meta *af_find_array( array_file_context *ctx, const char *name );
-void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr, 
-                         array_file_meta *arr, vg_stack_allocator *stack, u32 stride );
-int af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride );
+VG_TIER_0 array_file_meta *af_find_array( array_file_context *ctx, const c8 *name );
+
+
+VG_TIER_1 void af_load_array_file( array_file_context *ctx, array_file_ptr *out_ptr, 
+                                   array_file_meta *arr, vg_stack_allocator *stack, u32 stride );
+VG_TIER_1 bool af_load_array( array_file_context *ctx, array_file_ptr *ptr, const char *name, vg_stack_allocator *stack, u32 stride );
+VG_TIER_0 void af_load_array_file_buffer( array_file_context *ctx, array_file_meta *arr, void *buffer, u32 stride );
 
 #define AF_LOAD_ARRAY_STRUCT( CTX, PTR, STRUCT, STACK ) \
    af_load_array( CTX, PTR, #STRUCT, STACK, sizeof(STRUCT) )
@@ -51,9 +51,9 @@ void *af_arritm( array_file_ptr *arr, u32 index );
 u32 af_arrcount( array_file_ptr *arr );
 
 /* packed string buffer access (with djb2 hash prefix) */
-const char *af_str( array_file_context *af, u32 pstr );
-u32 af_str_hash( array_file_context *af, u32 pstr );
-bool af_str_eq( array_file_context *af, u32 pstr, const char *str, u32 str_hash );
+VG_TIER_0 const c8 *af_str( const void *packed_strings, u32 pstr );
+VG_TIER_0 u32 af_str_hash( const void *packed_strings, u32 pstr );
+VG_TIER_0 bool af_str_eq( const void *packed_strings, u32 pstr, const char *str, u32 str_hash );
 
 #define AF_STR_EQ( CTX, PSTR, CONSTR ) \
    af_str_eq( CTX, PSTR, CONSTR, vg_strdjb2( CONSTR ) )
@@ -61,7 +61,7 @@ bool af_str_eq( array_file_context *af, u32 pstr, const char *str, u32 str_hash
 
 /* COmpiler 
  * ------------------------------------ */
-
+#if defined( VG_ENGINE )
 typedef struct af_compiler af_compiler;
 typedef struct af_compiler_item af_compiler_item;
 typedef struct af_compiler_index af_compiler_index;
@@ -90,7 +90,7 @@ struct af_compiler
 
    af_compiler_item *most_recent_item;
 
-   FILE *fp;
+   vg_stream stream;
    u32 file_offset;
 };
 
@@ -100,3 +100,5 @@ af_compiler_index *af_compiler_create_index( af_compiler *compiler, const char *
 bool af_write( af_compiler *compiler, const char *path, u32 version );
 af_compiler_index *af_get_or_make_index( af_compiler *compiler, const char *alias, u32 element_size );
 u32 af_compile_string( af_compiler *compiler, const char *string );
+#endif
+#endif
index 8186c46d99fb326615dbf067a4ff53d0245ea88b..400df407a115ce420525a0a854a2e2be9a60745a 100644 (file)
@@ -1,7 +1,3 @@
-#include "world.h"
-#include "audio.h"
-#include "vg/vg_audio_dsp.h"
-
 audio_clip audio_board[] =
 {
    { .path="sound/skate_hpf.ogg" },
@@ -186,29 +182,36 @@ static audio_clip air_synth =
    .any_data = &air_audio_data
 };
 
-void audio_init(void)
+static void _audio_load_content_async( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+   vg_audio_clip_loadn( audio_board, VG_ARRAY_LEN(audio_board), NULL );
+   vg_audio_clip_loadn( audio_taps, VG_ARRAY_LEN(audio_taps), NULL );
+   vg_audio_clip_loadn( audio_flips, VG_ARRAY_LEN(audio_flips), NULL );
+   vg_audio_clip_loadn( audio_hits, VG_ARRAY_LEN(audio_hits), NULL );
+   vg_audio_clip_loadn( &audio_splash, 1, NULL );
+   vg_audio_clip_loadn( &audio_gate_pass, 1, NULL );
+   vg_audio_clip_loadn( &audio_gate_lap, 1, NULL );
+   vg_audio_clip_loadn( &audio_gate_ambient, 1, NULL );
+   vg_audio_clip_loadn( &audio_wood_break, 1, NULL );
+   vg_audio_clip_loadn( audio_jumps, VG_ARRAY_LEN(audio_jumps), NULL );
+   vg_audio_clip_loadn( audio_lands, VG_ARRAY_LEN(audio_lands), NULL );
+   vg_audio_clip_loadn( audio_water, VG_ARRAY_LEN(audio_water), NULL );
+   vg_audio_clip_loadn( audio_grass, VG_ARRAY_LEN(audio_grass), NULL );
+   vg_audio_clip_loadn( audio_footsteps, VG_ARRAY_LEN(audio_footsteps), NULL );
+   vg_audio_clip_loadn( audio_footsteps_grass, VG_ARRAY_LEN(audio_footsteps_grass), NULL );
+   vg_audio_clip_loadn( audio_footsteps_wood, VG_ARRAY_LEN(audio_footsteps_wood), NULL );
+   vg_audio_clip_loadn( audio_rewind, VG_ARRAY_LEN(audio_rewind), NULL );
+   vg_audio_clip_loadn( audio_ui, VG_ARRAY_LEN(audio_ui), NULL );
+   vg_audio_clip_loadn( audio_challenge, VG_ARRAY_LEN(audio_challenge), NULL );
+   vg_audio_clip_loadn( audio_gino, VG_ARRAY_LEN(audio_gino), NULL );
+}
+
+VG_API void _audio_init(void)
 {
-   audio_clip_loadn( audio_board, VG_ARRAY_LEN(audio_board), NULL );
-   audio_clip_loadn( audio_taps, VG_ARRAY_LEN(audio_taps), NULL );
-   audio_clip_loadn( audio_flips, VG_ARRAY_LEN(audio_flips), NULL );
-   audio_clip_loadn( audio_hits, VG_ARRAY_LEN(audio_hits), NULL );
-   audio_clip_loadn( &audio_splash, 1, NULL );
-   audio_clip_loadn( &audio_gate_pass, 1, NULL );
-   audio_clip_loadn( &audio_gate_lap, 1, NULL );
-   audio_clip_loadn( &audio_gate_ambient, 1, NULL );
-   audio_clip_loadn( &audio_wood_break, 1, NULL );
-
-   audio_clip_loadn( audio_jumps, VG_ARRAY_LEN(audio_jumps), NULL );
-   audio_clip_loadn( audio_lands, VG_ARRAY_LEN(audio_lands), NULL );
-   audio_clip_loadn( audio_water, VG_ARRAY_LEN(audio_water), NULL );
-   audio_clip_loadn( audio_grass, VG_ARRAY_LEN(audio_grass), NULL );
-   audio_clip_loadn( audio_footsteps, VG_ARRAY_LEN(audio_footsteps), NULL );
-   audio_clip_loadn( audio_footsteps_grass, VG_ARRAY_LEN(audio_footsteps_grass), NULL );
-   audio_clip_loadn( audio_footsteps_wood, VG_ARRAY_LEN(audio_footsteps_wood), NULL );
-   audio_clip_loadn( audio_rewind, VG_ARRAY_LEN(audio_rewind), NULL );
-   audio_clip_loadn( audio_ui, VG_ARRAY_LEN(audio_ui), NULL );
-   audio_clip_loadn( audio_challenge, VG_ARRAY_LEN(audio_challenge), NULL );
-   audio_clip_loadn( audio_gino, VG_ARRAY_LEN(audio_gino), NULL );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_audio_load_content_async );
 
    vg_audio_lock();
    air_audio_data.channel_id = vg_audio_get_first_idle_channel();
@@ -228,31 +231,3 @@ void audio_ambient_sprite_play( v3f co, audio_clip *clip )
    }
    vg_audio_unlock();
 }
-
-enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output);
-void audio_ambient_sprites_update( world_instance *world, v3f co )
-{
-   static float accum = 0.0f;
-   accum += vg.time_delta;
-
-   if( accum > 0.1f )
-      accum -= 0.1f;
-   else return;
-
-   v3f sprite_pos;
-   enum audio_sprite_type sprite_type = 
-      world_audio_sample_sprite_random( co, sprite_pos );
-   
-   if( sprite_type != k_audio_sprite_type_none ){
-      if( sprite_type == k_audio_sprite_type_grass ){
-         audio_ambient_sprite_play( sprite_pos, 
-                                    &audio_grass[vg_randu32(&vg.rand)%4] );
-      }
-      else if( sprite_type == k_audio_sprite_type_water ){
-         if( world->water.enabled ){
-            audio_ambient_sprite_play( sprite_pos, 
-                                       &audio_water[vg_randu32(&vg.rand)%6] );
-         }
-      }
-   }
-}
index 11eb136e785b0914c23b6f225b20b5a52eea2908..7489ee592cf53c35e9929acc5fd93b2b13da2f61 100644 (file)
@@ -1,13 +1,6 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-
-#include "vg/vg_engine.h"
-#include "vg/vg_audio.h"
-#include "vg/vg_audio_dsp.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/audio.c"
+#else
 
 struct air_synth_data {
    f32 speed;
@@ -22,12 +15,12 @@ struct air_synth_data {
 }
 extern air_audio_data;
 
-void audio_init(void);
+VG_API void _audio_init(void);
 void audio_ambient_sprite_play( v3f co, audio_clip *clip );
-void audio_ambient_sprites_update( world_instance *world, v3f co );
 
 /* TODO(ASSETS): 
  * Have these as asignable ID's and not a bunch of different arrays. 
+ * TODO: Just marking here again because this still isn't fucking fixed
  */
 extern audio_clip audio_board[];
 extern audio_clip audio_taps[];
@@ -55,3 +48,5 @@ enum audio_sprite_type
    k_audio_sprite_type_grass,
    k_audio_sprite_type_water
 };
+
+#endif
index d5a894e448a319a2f44d78a8f29925ed8d915164..af92dd8a98de721e1a2ce1d9e27adb9cd61297a6 100644 (file)
@@ -1,28 +1,5 @@
-#include "board_maker.h"
-#include "shaders/workshop_compositor.h"
-#include "vg/vg_ui/filebrowser.h"
-
 struct _board_maker _board_maker = 
 {
-   .compositor_fb =
-   {
-      .display_name = "Workshop Compositor texture",
-      .resolution_div = 0,
-      .fixed_w = 512, .fixed_h = 512,
-      .attachments = (vg_framebuffer_attachment[])
-      {
-         {
-            .display_name = "RGBA",
-            .purpose = k_framebuffer_attachment_type_texture,
-            .quality = k_framebuffer_quality_all,
-            .internalformat = GL_RGBA,
-            .format         = GL_RGBA,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         }
-      },
-      .attachment_count = 1
-   }
 };
 
 /* image loader thread 
@@ -34,9 +11,9 @@ struct board_maker_image_info
    i32 w, h;
 };
 
-static void _async_board_maker_image_finish( vg_async_task *task )
+static void _async_board_maker_image_finish( struct board_maker_image_info *in_args, vg_async_info *async )
 {
-   struct board_maker_image_info *inf = (void *)task->data;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_OPENGL ) );
    struct board_maker_decal *decal = &_board_maker.decals[ _board_maker.ui_target_part ];
 
    if( decal->loaded )
@@ -46,14 +23,13 @@ static void _async_board_maker_image_finish( vg_async_task *task )
 
    glGenTextures( 1, &decal->texture );
    glBindTexture( GL_TEXTURE_2D, decal->texture );
-   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, inf->w, inf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, inf->data );
+   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, in_args->w, in_args->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, in_args->data );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glGenerateMipmap( GL_TEXTURE_2D );
-
-   stbi_image_free( inf->data );
+   stbi_image_free( in_args->data );
 
    _board_maker.state = k_board_maker_state_none;
    _board_maker.compositor_state = k_board_maker_compositor_dirty;
@@ -61,19 +37,18 @@ static void _async_board_maker_image_finish( vg_async_task *task )
 
 static void _board_maker_image_t1( void *userdata )
 {
-   THREAD_1;
-   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct board_maker_image_info), 1 );
-   struct board_maker_image_info *info = (void *)task->data;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   struct board_maker_image_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct board_maker_image_info));
    i32 nc;
    stbi_set_flip_vertically_on_load(1);
-   info->data = stbi_load( _board_maker.browser->current_path, &info->w, &info->h, &nc, 4 );
-   vg_async_task_dispatch( task, _async_board_maker_image_finish );
+   out_args->data = stbi_load( _board_maker.browser->current_path, &out_args->w, &out_args->h, &nc, 4 );
+   _vg_async_send( out_args, (vg_async_fn)_async_board_maker_image_finish );
 }
 
 /* model loader thread 
  * ----------------------------------------- */
 
-static void _async_board_maker_load_finish( void *userdata )
+static void _async_board_maker_load_finish( void *nothing, vg_async_info *async )
 {
    _board_maker.state = k_board_maker_state_none;
    _board_maker.template_loaded = _board_maker.template_selection;
@@ -81,7 +56,7 @@ static void _async_board_maker_load_finish( void *userdata )
 
    _board_maker.base_shader = NULL;
 
-   mdl_context *mdl = &_board_maker.template_mdl;
+   vg_model *mdl = &_board_maker.template_mdl;
    if( mdl->version <= 105 ) 
       return;
 
@@ -92,7 +67,7 @@ static void _async_board_maker_load_finish( void *userdata )
    if( mat0->shader != k_shader_workshop )
       return;
 
-   _board_maker.base_shader = mat0->props.compiled;
+   _board_maker.base_shader = &mdl->shader_props[0];
 }
 
 struct ui_enum_opt _board_maker_template_opts[] = 
@@ -109,38 +84,51 @@ const char *_board_maker_template_paths[] =
    [2] = "models/workshop/longboard.mdl"
 };
 
-static void _board_maker_load_template( void *_ )
+static void _board_maker_load_template( void *_, vg_async_info *async )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    vg_stack_clear( &_board_maker.template_stack );
 
-   mdl_context *mdl = &_board_maker.template_mdl;
-   mdl_open( mdl, _board_maker_template_paths[_board_maker.template_selection], &_board_maker.template_stack );
-   mdl_load_metadata_block( mdl, &_board_maker.template_stack );
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &_board_maker.template_mdl, 
+                                    _board_maker_template_paths[_board_maker.template_selection] ) );
+   vg_model_stream_metadata( &ctx, &_board_maker.template_stack );
 
    /* we need this for compiling it back down */
-   mdl_load_mesh_block( mdl, &_board_maker.template_stack );
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &_board_maker.template_mdl_markers, ent_marker, &_board_maker.template_stack );
+   vg_model_stream_meshes_cpu( &ctx, &_board_maker.template_stack );
+   vg_model_stream_meshes_gpu( &ctx, NULL );
+   vg_model_stream_textures_gpu( &ctx );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &_board_maker.template_mdl_markers, ent_marker, &_board_maker.template_stack );
+   vg_model_stream_close( &ctx );
 
-   mdl_async_full_load_std( mdl, NULL );
-   mdl_close( mdl );
-   vg_async_call( &vg.main_tasks, _async_board_maker_load_finish, NULL );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_async_board_maker_load_finish );
 }
 
 /* system init thread 
  * ----------------------------------------------------- */
 
-static void _async_board_maker_init_finish( void *userdata )
+static void _board_maker_init_late(void)
 {
-   THREAD_0;
-   _board_maker.state = k_board_maker_state_none;
-}
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   
+   _board_maker.compositor_fb = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 0 );
+   _board_maker.compositor_fb->display_name = "Workshop Compositor texture";
+   _board_maker.compositor_fb->resolution_div = 0;
+   _board_maker.compositor_fb->fixed_w = 512;
+   _board_maker.compositor_fb->fixed_h = 512;
+   _board_maker.compositor_fb->attachments[0] = (vg_framebuffer_attachment)
+   {
+      .display_name = "RGBA",
+      .purpose = k_framebuffer_attachment_type_texture,
+      .quality = k_framebuffer_quality_all,
+      .internalformat = GL_RGBA,
+      .format         = GL_RGBA,
+      .type           = GL_UNSIGNED_BYTE,
+      .attachment     = GL_COLOR_ATTACHMENT0
+   };
+   vg_framebuffer_init( _board_maker.compositor_fb );
 
-static void _board_maker_init_t1( void *userdata )
-{
-   THREAD_1;
-   vg_framebuffer_create( &_board_maker.compositor_fb );
-   vg_async_call( &vg.main_tasks, _async_board_maker_init_finish, NULL );
+   _board_maker.state = k_board_maker_state_none;
 }
 
 static void _board_maker_export(void)
@@ -170,38 +158,43 @@ static void _board_maker_export(void)
       .channels = 3,
       .colorspace = QOI_SRGB 
    };
-
-   void *raw_data = malloc( 512*512*3 ),
-        *qoi_data = malloc( vg_query_qoi_storage_size( &desc ) );
-
-   vg_framebuffer_bind( &_board_maker.compositor_fb, 1.0f );
-   glReadBuffer( GL_COLOR_ATTACHMENT0 );
-   glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, raw_data );
-
-   i32 qoi_len;
-   if( !vg_encode_qoi2( raw_data, &desc, qoi_data, &qoi_len ) )
+   
+   u32 onetex;
+   u32 temp_frame = _vg_start_temp_frame();
    {
-      free( raw_data );
-      free( qoi_data );
-
-      _board_maker.export_success = 0;
-      _board_maker.export_message = "Texture failed to compress";
-      _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
-      return;
-   }
+      void *raw_data = vg_stack_allocate( _vg_temp_stack(), 512*512*3, 8, "Raw data" ),
+           *qoi_data = vg_stack_allocate( _vg_temp_stack(), vg_query_qoi_max_compressed_size( &desc ), 8, "QOI" );
 
-   u32 onetex = mdl_compiler_compile_texture_qoi( &compiler, "Maker Tex", qoi_data, qoi_len );
+      vg_framebuffer_bind( _board_maker.compositor_fb, 1.0f );
+      glReadBuffer( GL_COLOR_ATTACHMENT0 );
+      glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, raw_data );
 
-   free( raw_data );
-   free( qoi_data );
+      vg_stream qoi_stream;
+      vg_buffer_stream_open( &qoi_stream, qoi_data, vg_query_qoi_max_compressed_size( &desc ), VG_STREAM_WRITE );
 
-   u8 shader_buf[ 512 ];
-   vg_msg shader_kvs;
-   vg_msg_init( &shader_kvs, shader_buf, sizeof(shader_buf) );
-   vg_msg_wkvnum( &shader_kvs, "tex_diffuse", k_vg_msg_u32, 1, &onetex );
+      i32 qoi_len = vg_qoi_stream_encode( &desc, raw_data, &qoi_stream, 0 );
+      if( qoi_len == 0 )
+      {
+         _board_maker.export_success = 0;
+         _board_maker.export_message = "Texture failed to compress";
+         _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
+         _vg_end_temp_frame( temp_frame );
+         return;
+      }
+      onetex = mdl_compiler_compile_texture_qoi( &compiler, "Maker Tex", qoi_data, qoi_len );
+   }
+   _vg_end_temp_frame( temp_frame );
 
-   u32 onemat = mdl_compiler_start_material( &compiler, "Maker Mat" );
-   mdl_compiler_push_shaderdata( &compiler, k_shader_standard, &shader_kvs );
+   u32 onemat;
+   temp_frame = _vg_start_temp_frame();
+   {
+      vg_kvs shader_kvs;
+      vg_kvs_init( &shader_kvs, _vg_temp_stack() );
+      vg_kv_append_vu32( &shader_kvs, 0, "tex_diffuse", &onetex, 1 );
+      onemat = mdl_compiler_start_material( &compiler, "Maker Mat" );
+      mdl_compiler_push_shaderdata( &compiler, k_shader_standard, &shader_kvs );
+   }
+   _vg_end_temp_frame( temp_frame );
    
    for( u32 i=0; i<_board_maker.template_mdl.mesh_count; i ++ )
    {
@@ -213,7 +206,7 @@ static void _board_maker_export(void)
 
       u32 ref_marker_index = mdl_entity_id_id( ref_mesh->entity_id );
       ent_marker *ref_marker = af_arritm( &_board_maker.template_mdl_markers, ref_marker_index );
-      const char *ref_marker_alias = af_str( &_board_maker.template_mdl.af, ref_marker->pstr_alias );
+      const c8 *ref_marker_alias = af_str( _board_maker.template_mdl.packed_strings, ref_marker->pstr_alias );
 
       ent_marker copy_marker = *ref_marker;
       copy_marker.pstr_alias = af_compile_string( &compiler.af, ref_marker_alias );
@@ -228,7 +221,7 @@ static void _board_maker_export(void)
                                              ref_submesh->indice_count );
    }
 
-   af_write( &compiler.af, _board_maker.export_path, MDL_VERSION_NR );
+   af_write( &compiler.af, _board_maker.export_path, VG_MODEL_VERSION_NR );
    mdl_compiler_free( &compiler );
 
    _board_maker.export_success = 1;
@@ -248,7 +241,7 @@ void _board_maker_pre_update(void)
       {
          if( _board_maker.compositor_state == k_board_maker_compositor_dirty )
          {
-            vg_framebuffer_bind( &_board_maker.compositor_fb, 1.0f );
+            vg_framebuffer_bind( _board_maker.compositor_fb, 1.0f );
             glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
             glClear( GL_COLOR_BUFFER_BIT );
 
@@ -265,14 +258,13 @@ void _board_maker_pre_update(void)
             {
                for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
                {
-                  u32 tex_id = _board_maker.base_shader->tex_all[i];
+                  u32 tex_id = _board_maker.base_shader->workshop.tex_all[i];
 
                   if( tex_id )
                   {
-                     mdl_texture *tex = &_board_maker.template_mdl.textures[ tex_id-1 ];
+                     mdl_texture *mdl_tex = &_board_maker.template_mdl.textures[ tex_id-1 ];
 
-                     glActiveTexture( GL_TEXTURE0 );
-                     glBindTexture( GL_TEXTURE_2D, tex->glname );
+                     vg_tex_bind( GL_TEXTURE_2D, &mdl_tex->tex, 0 );
                      shader_workshop_compositor_uColour( _board_maker.colours[i] );
 
                      struct board_maker_decal *decal = &_board_maker.decals[ i ];
@@ -308,12 +300,12 @@ void _board_maker_pre_update(void)
       {
          if( _board_maker.template_loaded != -1 )
          {
-            mdl_sync_std_unload( &_board_maker.template_mdl );
+            vg_model_unload_gpu( &_board_maker.template_mdl );
             _board_maker.template_loaded = -1;
          }
 
          _board_maker.state = k_board_maker_state_loading_template;
-         vg_async_call( &vg.loader_tasks, _board_maker_load_template, NULL );
+         _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_board_maker_load_template );
       }
    }
    else
@@ -321,12 +313,12 @@ void _board_maker_pre_update(void)
       if( _board_maker.state == k_board_maker_state_not_ready )
       {
          _board_maker.state = k_board_maker_state_initializing;
-         vg_async_call( &vg.loader_tasks, _board_maker_init_t1, NULL );
+         _board_maker_init_late();
       }
       else if( _board_maker.state == k_board_maker_state_load_image )
       {
          _board_maker.state = k_board_maker_state_loading_image;
-         vg_async_call( &vg.loader_tasks, _board_maker_image_t1, NULL );
+         _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_board_maker_image_t1 );
       }
       else if( _board_maker.state == k_board_maker_state_export )
       {
@@ -372,22 +364,20 @@ void _board_maker_render( world_instance *world, vg_camera *cam )
 
    if( _board_maker.template_loaded >= 0 )
    {
-      vg_framebuffer_bind_texture( &_board_maker.compositor_fb, 0, 0 );
-
+      vg_framebuffer_bind_texture( _board_maker.compositor_fb, 0, 0 );
       shader_model_entity_use();
       shader_model_entity_uTexMain( 0 );
       shader_model_entity_uCamera( cam->transform[3] );
       shader_model_entity_uPv( cam->mtx.pv );
-      
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+      WORLD_LINK_LIGHTING( world, model_entity );
 
       m4x3f root_mmdl;
       m4x3_identity( root_mmdl );
       q_m3x3( _board_maker.q, root_mmdl );
       v3_copy( _board_maker.origin, root_mmdl[3] );
 
-      mdl_context *mdl = &_board_maker.template_mdl;
-      mesh_bind( &mdl->mesh );
+      vg_model *mdl = &_board_maker.template_mdl;
+      vg_model_bind_mesh( mdl );
 
       for( u32 i=0; i<mdl->mesh_count; i ++ )
       {
@@ -406,7 +396,7 @@ void _board_maker_render( world_instance *world, vg_camera *cam )
          for( u32 j=0; j<mesh->submesh_count; j ++ )
          {
             mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start + j ];
-            mdl_draw_submesh( sm );
+            vg_model_draw_submesh( sm );
          }
       }
    }
@@ -580,7 +570,7 @@ void _board_maker_ui( ui_context *ctx )
    if( _board_maker.ui_state == k_board_maker_ui_state_export )
    {
       ui_rect export_rect = { 0,0, 400, 300 };
-      ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, export_rect );
+      ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, export_rect );
       ui_panel( ctx, export_rect, export_rect );
 
       /* title */
@@ -881,8 +871,8 @@ void _board_maker_ui( ui_context *ctx )
       }
    }
 
-   ui_rect box = { vg.window_x-(400+8),8, 400,400 };
-   ui_image( ctx, box, &_board_maker.compositor_fb.attachments[0].id, 0 );
+   ui_rect box = { _vg_window.w-(400+8),8, 400,400 };
+   ui_image( ctx, box, &_board_maker.compositor_fb->attachments[0].tex, 0 );
    ui_outline( ctx, box, 1, ui_colour( ctx, k_ui_fg ), 0 );
 
    if( quit_me )
@@ -931,8 +921,8 @@ void _board_maker_open(void)
    _board_maker.template_loaded = -1;
    _board_maker.template_selection = 0;
 
-   vg_stack_init( &_board_maker.static_stack, NULL, VG_MB(8), "Board Maker: Static Stack" );
-   vg_stack_init( &_board_maker.template_stack, NULL, VG_MB(16), "Board Maker: Template Stack" );
+   vg_stack_init( &_board_maker.static_stack, VG_STACK_USE_HEAP, VG_MB(8), "Board Maker: Static Stack" );
+   vg_stack_init( &_board_maker.template_stack, VG_STACK_USE_HEAP, VG_MB(16), "Board Maker: Template Stack" );
 
    for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
    {
@@ -956,18 +946,20 @@ void _board_maker_open(void)
 
 void _board_maker_close(void)
 {
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
    for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
    {
       struct board_maker_decal *decal = &_board_maker.decals[i];
       clear_decal( decal );
    }
-   vg_framebuffer_free( &_board_maker.compositor_fb );
+   vg_framebuffer_free( _board_maker.compositor_fb );
 
    vg_filebrowser_free_entries( _board_maker.browser );
    free( _board_maker.browser );
    _board_maker.browser = NULL;
 
-   mdl_sync_std_unload( &_board_maker.template_mdl );
+   vg_model_unload_gpu( &_board_maker.template_mdl );
    _board_maker.template_loaded = -1;
 
    vg_stack_free( &_board_maker.static_stack );
index 7f12d2e97b2cd447d4967d518b98409b9e26b1d7..a88e44ebdf10e56115e56d280bda8e529e5c05f6 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "vg/vg_framebuffer.h"
-#include "shader_props.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/board_maker.c"
+#else
 
 v4f _board_maker_default_colours[] = 
 {
@@ -27,7 +27,7 @@ struct _board_maker
    i32 template_selection,
        template_loaded;
 
-   mdl_context template_mdl;
+   vg_model template_mdl;
    array_file_ptr template_mdl_markers;
 
    enum board_maker_state
@@ -51,10 +51,10 @@ struct _board_maker
    }
    compositor_state;
 
-   vg_framebuffer compositor_fb;
+   vg_framebuffer *compositor_fb;
 
    v4f colours[ k_workshop_shader_part_max ];
-   struct shader_props_workshop *base_shader;
+   union shader_props *base_shader;
 
    struct board_maker_decal
    {
@@ -101,3 +101,5 @@ void _board_maker_render( world_instance *world, vg_camera *cam );
 void _board_maker_ui( ui_context *ctx );
 void _board_maker_open(void);
 void _board_maker_close(void);
+
+#endif
diff --git a/src/build_control_overlay.c b/src/build_control_overlay.c
deleted file mode 100644 (file)
index 46dd837..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Script to load the overlay model and generate an enum referencing each 
- * submesh by its name.
- */
-void build_control_overlay(void)
-{
-   FILE *hdr = fopen( "src/control_overlay.h.generated", "w" );
-
-   vg_stack_allocator stack;
-   vg_stack_init( &stack, NULL, VG_MB(8), "Model buffer" );
-
-   mdl_context ctx;
-   mdl_open( &ctx, "content_skaterift/models/rs_overlay.mdl", &stack );
-   mdl_load_metadata_block( &ctx, &stack );
-   mdl_close( &ctx );
-
-   for( u32 i=0; i<ctx.mesh_count; i ++ )
-   {
-      mdl_mesh *mesh = &ctx.meshes[ i ];
-      fprintf( hdr, "   %s = %u,\n", af_str( &ctx.af, mesh->pstr_name ), mesh->submesh_start );
-   }
-
-   vg_stack_free( &stack );
-   fclose( hdr );
-}
index b8cbacc74c0dd7206de3fafa8bec39f3de701c3d..55486ca4440f6f301388f3b416d76f0f0c18ac1d 100644 (file)
-#include "vg/vg_opt.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include "vg/vg_audio.h"
-
-#include "client.h"
-#include "render.h"
-#include "network.h"
-#include "player_remote.h"
-#include "menu.h"
-
 const char* __asan_default_options() { return "detect_leaks=0"; }
 
-struct game_client g_client = 
+struct game_client _client = 
 {
-   .demo_mode = 1,
 };
 
-#include "skaterift.c"
+struct skaterift_globals skaterift = 
+{ 
+   .time_rate = 1.0f,
+};
+
+static void _skaterift_mount_addons_async( void *_, vg_async_info *async )
+{
+   _world.default_hub_addon = _addon_mount_from_folder_path( "maps/dev_hub", k_addon_type_world, ".mdl" );
+   VG_ASSERT( _world.default_hub_addon );
+   _addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
+   _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
+   _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
+}
+
+int skaterift_quit_command( int argc, const char *argv[] )
+{
+   if( argc >= 1 )
+      if( !strcmp( argv[0], "1" ) )
+         skaterift.no_save_location = 1;
+
+   _vg_terminate();
+   return 1;
+}
+
+/* 
+ * UPDATE LOOP
+ * ---------------------------------------------------------------------------*/
+
+static void draw_origin_axis(void)
+{
+   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
+   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
+   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
+}
+
+void client_event_handler( vg_event_info *info )
+{
+   if( info->type == k_vg_event_opts )
+   {
+      const char *arg;
+      if( vg_long_opt( "noauth", "Disable server authentication" ) )
+         network_client.auth_mode = eServerModeNoAuthentication;
+
+      if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
+         network_set_host( arg, NULL );
+
+      if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
+         skaterift.override_load_world = arg;
+
+      _demo_check_opts();
+   }
+   else if( info->type == k_vg_event_register )
+   {
+      vg_console_reg_cmd( "quit", skaterift_quit_command, NULL );
+      vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
+      vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
+      vg_console_reg_var( "allow_resume", &skaterift.allow_replay_resume, k_var_dtype_i32, VG_VAR_CHEAT );
+      vg_console_reg_var( "boost_scale", &skaterift.boost_scale, k_var_dtype_f32, VG_VAR_CHEAT );
+
+      _render_register();
+      _remote_players_register();
+      _network_register();
+      _menu_register();
+      _control_overlay_register();
+      _world_render_register();
+      _gui_register();
+      _compass_register();
+      _player_register();
+      _player_ragdoll_register();
+      _cutscene_register();
+      _workshop_register();
+      _ent_tornado_register();
+      _replay2_register();
+      _ent_atom_register();
+      _ent_challenge_register();
+
+      _steam_api.cb_connection_changed = cb_skaterift_connection_changed;
+      _steam_api.cb_persona_changed = cb_skaterift_persona_changed;
+
+      network_set_host( "skaterift.com", NULL );
+   }
+   else if( info->type == k_vg_event_init )
+   {
+      _vg_loader_set_user_information( "Initializing subsystems" );
+
+      _vg_async_context_push_groups( SKATERIFT_LOAD_GROUP );
+      _demo_check_init();
+      _render_init();
+      _remote_players_init();
+      _network_init();
+      _menu_init();
+      _user_profile_init();
+      _particles_init();
+      _addon_system_init();
+
+      _player_init();
+      _player_render_init();
+
+      _control_overlay_init();
+      _world_init();
+      _gui_init();
+      _compass_init();
+      _skateshop_init();
+      _world_map_init();
+      _replay2_init();
+      _ent_npc_init();
+      _audio_init();
+      _ent_atom_init();
+
+      _mount_workshop_addons();
+      _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_skaterift_mount_addons_async );
+
+      if( network_client.auto_connect )
+         network_client.user_intent = k_server_intent_online;
+      menu_at_begin();
+      _vg_async_context_pop_groups();
+   }
+   else if( info->type == k_vg_event_pre_update )
+   {
+
+#if 0
+         if( co_step( co, 1 ) )
+         {
+            /* initializing / loading world. */
+            vg_loader_set_user_information( "Loading savedata" );
+            skaterift_load_mainsave();
+
+            if( skaterift.override_load_world )
+               _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
+
+            _world.loader_instance = &_world.main;
+            _world.loader_preview_mode = 0;
+            _world.loader_stack = _world.stack;
+
+            if( !_world.load_addon )
+            {
+               vg_warn( "Falling back to default hub world...\n" );
+               _world.load_addon = _world.default_hub_addon;
+            }
+
+            _world_loader_set_addon( _world.load_addon );
+         }
+#endif
+
+
+      skaterift_preupdate_inputs();
+      world_switcher_update();
+
+      if( !skaterift.ready_to_show_game )
+         return;
+
+      //draw_origin_axis();
+      //_skaterift_script_update();
+      _addon_system_pre_update();
+      _network_update();
+
+      /* time rate */
+      f32 target = 1;
+      if( skaterift.activity & k_skaterift_replay )
+         target = 0;
+
+      if( skaterift.activity == k_skaterift_spectate )
+      {
+         if( button_down( k_srbind_mback ) )
+         {
+            vg_audio_lock();
+            vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
+            vg_audio_unlock();
+            menu_close(); /* sets tate to default*/
+            menu_open( k_menu_page_quick );
+            _gui_helper_reset( k_gui_helper_mode_clear );
+            localplayer.immobile = 0;
+         }
+      }
+
+      world_update( &_world.main, localplayer.rb.co );
+      _board_maker_pre_update();
+
+      cutscene_update( vg.time_rate * vg.time_frame_delta );
+
+      if( !((skaterift.activity == k_skaterift_menu) && (menu.page != k_menu_page_quick)) )
+         player__pre_update();
+
+      _replay2_pre_update();
+      remote_sfx_pre_update();
+
+      v3f listen_co;
+      v3_copy( localplayer.rb.co, listen_co );
+      if( skaterift.activity & k_skaterift_menu )
+      {
+         if( menu.page != k_menu_page_quick )
+         {
+            if( menu.bg_cam )
+               v3_copy( menu.bg_cam->co, listen_co );
+            else target = 0;
+         }
+      }
+
+      vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) );
+      vg.time_rate = vg_smoothstepf( skaterift.time_rate );
+   }
+   else if( info->type == k_vg_event_fixed_update )
+   {
+      if( !skaterift.ready_to_show_game )
+         return;
+
+      world_routes_fixedupdate( &_world.main );
+      player__update();
+   }
+   else if( info->type == k_vg_event_post_update )
+   {
+      if( !skaterift.ready_to_show_game )
+         return;
+
+      player__post_update();
+
+      float dist;
+      int sample_index;
+      world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist );
+
+      vg_audio_lock();
+      vg_dsp.echo_distances[sample_index] = dist;
+
+      v3f ears = { 1.0f,0.0f,0.0f };
+      m3x3_mulv( g_render.cam.transform, ears, ears );
+      v3_copy( ears, _vg_audio.controls.listener_right_ear_direction );
+      v3_copy( g_render.cam.transform[3], _vg_audio.controls.listener_position );
+
+      if( localplayer.gate_waiting )
+      {
+         m4x3_mulv( localplayer.gate_waiting->transport, _vg_audio.controls.listener_position, 
+                    _vg_audio.controls.listener_position );
+      }
+
+      v3_copy( localplayer.rb.v, _vg_audio.controls.listener_velocity );
+      vg_audio_unlock();
+
+      _skaterift_autosave_post_update();
+      localplayer.immunity = 0;
+   }
+   else if( info->type == k_vg_event_render )
+   {
+      if( !skaterift.ready_to_show_game )
+         return;
+
+      glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+      glViewport( 0,0, _vg_window.w, _vg_window.h );
+      glDisable( GL_DEPTH_TEST );
+      glDisable( GL_BLEND );
+
+      glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
+      glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+      /* RENDER main game 
+       * ------------------------------------------------------------------------------------------------------------ */
+      {
+         if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
+         {
+            struct cs_instance *inst = _cutscene.player_binding;
+            ms_skeleton *sk = &localplayer.skeleton;
+            for( u32 i=0; i<sk->bone_count; i ++ )
+               m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
+         }
+         else if( skaterift.activity == k_skaterift_replay ){}
+         else
+         {
+            player__animate();
+            _replay2_record_local_frame();
+         }
+
+         animate_remote_players();
+         player__pre_render();
+
+
+         /* world entity driven camera 
+          * ------------------------------------------------------------------------------ */
+         if( _world.entity_set_camera )
+         {
+            _world.entity_set_camera = 0;
+            _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
+         }
+         else
+         {
+            _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
+         }
+         
+         vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
+                         vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
+
+         /* replay camera 
+          * ------------------------------------------------------------------ */
+         if( skaterift.activity == k_skaterift_replay )
+         {
+            _replay2_get_camera( &g_render.cam );
+         }
+
+         if( skaterift.activity == k_skaterift_spectate )
+         {
+            _network_get_spectate_cam( &g_render.cam );
+         }
+
+         g_render.cam.nearz = 0.1f;
+         g_render.cam.farz  = 2100.0f;
+
+         /* menu override camera 
+          * -------------------------------------------------------------------- */
+         if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
+         {
+            ent_camera_unpack( menu.bg_cam, &g_render.cam );
+         }
+
+         /* cutscene camera TODO: Fix the action camera 
+          * ---------------------------------------------------------------- */
+         ent_camera *cs_cam = _cutscene_active_camera();
+         if( cs_cam )
+            ent_camera_unpack( cs_cam, &g_render.cam );
+
+         world_map_get_transition_cam( &g_render.cam );
+
+         vg_camera_update_transform( &g_render.cam );
+
+         vg_camera_update_view( &g_render.cam );
+         vg_camera_update_projection( &g_render.cam, _vg_window.w, _vg_window.h );
+         vg_camera_finalize( &g_render.cam );
+
+
+
+
+
+
+
+         bool render_actual_game = !menu_viewing_map();
+         bool render_stenciled = 0;
+
+         if( render_actual_game )
+         {
+            world_instance *world = &_world.main;
+            render_world_cubemaps( world );
+         }
+
+         /* variable res target */
+         vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+         glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
+
+         if( !render_actual_game )
+         {
+            render_world_map();
+
+            if( world_map_get_transition_cam(NULL) )
+            {
+               glEnable( GL_STENCIL_TEST );
+               glDisable( GL_DEPTH_TEST );
+               glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
+               glStencilFunc( GL_ALWAYS, 1, 0xFF );
+               glStencilMask( 0xFF );
+               
+               shader_blit_transition_use();
+               shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
+               shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
+               render_fsquad();
+               render_stenciled = 1;
+               render_actual_game = 1;
+            }
+         }
+
+         if( render_actual_game )
+         {
+            /* Draw world */
+            glEnable( GL_DEPTH_TEST );
+            world_prerender( &_world.main );
+
+            render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
+
+            particle_system_update( &particles_grind, vg.time_delta );
+            //particle_system_debug( &particles_grind );
+            particle_system_prerender( &particles_grind );
+            particle_system_render( &particles_grind, &g_render.cam );
+            
+            ent_tornado_pre_update();
+            particle_system_update( &particles_env, vg.time_delta );
+            particle_system_prerender( &particles_env );
+            particle_system_render( &particles_env, &g_render.cam );
+
+            player_glide_render_effects( &g_render.cam );
+         }
+
+         glEnable( GL_DEPTH_TEST );
+
+         /* full res target */
+         glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+         glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+         if( render_actual_game && !render_stenciled )
+         {
+            bool render_player_transparent = 1;
+
+            if( (skaterift.activity == k_skaterift_menu) &&
+                (menu.page == k_menu_page_main) && 
+                (menu.main_index == k_menu_main_guide) )
+            {
+               render_player_transparent = 0;
+            }
+
+            if( skaterift.activity == k_skaterift_replay )
+               render_player_transparent = 0;
+
+            if( render_player_transparent )
+            {
+               static vg_camera small_cam;      /* DOES NOT NEED TO BE STATIC BUT MINGW 
+                                                SAIS OTHERWISE */
+
+               m4x3_copy( g_render.cam.transform, small_cam.transform );
+
+               small_cam.fov = g_render.cam.fov;
+               small_cam.nearz = 0.05f;
+               small_cam.farz  = 60.0f;
+
+               vg_camera_update_view( &small_cam );
+               vg_camera_update_projection( &small_cam, _vg_window.w, _vg_window.h );
+               vg_camera_finalize( &small_cam );
+
+               /* Draw player to window buffer and blend background ontop */
+               player__render( &small_cam );
+            }
+
+            /* continue with variable rate */
+            vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
+            render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
+         }
+
+         /* composite */
+         if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
+            v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
+         else 
+            v2_zero( g_render.blur_override );
+
+         vg_postprocess_to_screen( _vg_render.fb_main );
+         _cutscene_render_fadeout();
+
+         if( !_gui_helpers_active() )
+            control_overlay_render();
+      }
+
+
+      m4x4_copy( g_render.cam.mtx.pv, vg.pv );
+      
+      glDisable(GL_BLEND);
+      glDisable(GL_DEPTH_TEST);
+      glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+      _gui_render_icons();
+      compass_render_texture();
+   }
+   else if( info->type == k_vg_event_gui )
+   {
+      if( !skaterift.ready_to_show_game )
+         return;
+
+      glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+      glViewport( 0,0, _vg_window.w, _vg_window.h );
+
+      _gui_draw( info->gui.ctx );
+      _compass_render_imgui( info->gui.ctx );
+
+      if( k_light_editor )
+         imgui_world_light_edit( info->gui.ctx, &_world.main );
+      
+      vg_ui.tex_bg = &_vg_render.fb_main->attachments[0].tex;
+      vg_framebuffer_inverse_ratio( _vg_render.fb_main, vg_ui.bg_inverse_ratio );
+
+      _cutscene_gui( info->gui.ctx );
+      _board_maker_ui( info->gui.ctx );
+      menu_gui( info->gui.ctx );
+      player__im_gui( info->gui.ctx );
+      world_instance *world = &_world.main;
+
+      if( skaterift.activity != k_skaterift_replay )
+      {
+         world_routes_imgui( info->gui.ctx, world );
+         _ent_route_imgui( info->gui.ctx );
+      }
+      _replay2_imgui( info->gui.ctx );
+      workshop_form_gui( info->gui.ctx );
+      world_gui( info->gui.ctx, world );
+
+      if( menu_viewing_map() )
+      {
+         remote_players_imgui_world( info->gui.ctx, &_world.main, vg.pv, 2000.0f, 0 );
+         //remote_players_imgui_lobby( ctx );
+      }
+      else 
+      {
+         remote_players_chat_imgui( info->gui.ctx ); /* TODO: conditional */
+         remote_players_imgui_world( info->gui.ctx, &_world.main, vg.pv, 100.0f, 1 );
+      }
+   }
+}
+
+int main( int argc, const char *argv[] )
+{
+   vg_run( argc, argv, client_event_handler );
+   return 0;
+}
index d11add9ff16dbe1263b999730371ebee25001331..36d1865e7c11838174080c125b10e8ba747e6b49 100644 (file)
@@ -1,17 +1,52 @@
-#pragma once
-#include "vg/vg_platform.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/client.c"
+#else
 
-/*
- *   client     - entry point. window, common things like render init.. etc
- *      vg      - backend code
- *         game - top layer: game content, state
- */
+#define SKATERIFT_APPID 2103940
+#define SKATERIFT_WORLD_READY 0x10000
+#define SKATERIFT_LOAD_GROUP VG_ASYNC_GROUP_CLIENT3
 
 struct game_client
 {
-   bool demo_mode;
+   u32 async_init_count;
 }
-extern g_client;
+extern _client;
 
 /* game defined */
 void game_launch_opt( void );
+
+enum skaterift_rt 
+{
+   k_skaterift_rt_workshop_preview,
+   k_skaterift_rt_server_status,
+   k_skaterift_rt_max
+};
+
+struct skaterift_globals
+{
+   f32 time_rate;
+   
+   enum skaterift_activity {
+      k_skaterift_default    = 0x00,  /* regular playing */
+      k_skaterift_replay     = 0x01,
+      k_skaterift_spectate   = 0x02,
+      k_skaterift_menu       = 0x04,
+      k_skaterift_activity_max = 0x8
+   }
+   activity;
+
+   vg_tex *rt_textures[k_skaterift_rt_max];
+
+   u32 achievements;
+   i32 allow_replay_resume;
+
+   const char *override_load_world;
+
+   f32 boost_scale;
+   bool no_save_location;
+
+   bool ready_to_show_game;
+}
+extern skaterift;
+
+#endif
diff --git a/src/common.h b/src/common.h
deleted file mode 100644 (file)
index 6f0c2f9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#endif /* COMMON_H */
index 019241b80d52f1a7182ac3d3d095498a3f9e3562..197d424b0ab93f8a480a1ce9e1864257f95d01d4 100644 (file)
@@ -1,35 +1,33 @@
-#include "compass.h"
-#include "shaders/compass.h"
-#include "world.h"
-
 struct _compass _compass = { .alpha = 1 };
 
-void compass_register(void)
+VG_API void _compass_register(void)
 {
    vg_console_reg_var( "compass_alpha", &_compass.alpha, k_var_dtype_f32, VG_VAR_PERSISTENT );
 }
 
-void compass_init(void)
+static void _compass_load_content_async( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   vg_model_load( &_compass.model, VG_MODEL_ENGINE_STANDARD, "models/rs_compass.mdl", NULL );
+   _compass.sm_comp = vg_model_get_submesh_index( &_compass.model, "comp" );
+   _compass.sm_comp_bar = vg_model_get_submesh_index( &_compass.model, "comp_bar" );
+   _compass.sm_comp_dot = vg_model_get_submesh_index( &_compass.model, "comp_dot" );
+   _compass.sm_comp_e = vg_model_get_submesh_index( &_compass.model, "comp_e" );
+   _compass.sm_comp_fade = vg_model_get_submesh_index( &_compass.model, "comp_fade" );
+   _compass.sm_comp_friend = vg_model_get_submesh_index( &_compass.model, "comp_friend" );
+   _compass.sm_comp_gate = vg_model_get_submesh_index( &_compass.model, "comp_gate" );
+   _compass.sm_comp_n = vg_model_get_submesh_index( &_compass.model, "comp_n" );
+   _compass.sm_comp_notify = vg_model_get_submesh_index( &_compass.model, "comp_notify" );
+   _compass.sm_comp_person = vg_model_get_submesh_index( &_compass.model, "comp_person" );
+   _compass.sm_comp_s = vg_model_get_submesh_index( &_compass.model, "comp_s" );
+   _compass.sm_comp_w = vg_model_get_submesh_index( &_compass.model, "comp_w" );
+   _compass.sm_comp_objective = vg_model_get_submesh_index( &_compass.model, "comp_objective" );
+}
+
+VG_API void _compass_init(void)
 {
-   mdl_context *mdl = &_compass.mdl;
-
-   mdl_open( mdl, "models/rs_compass.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
-   mdl_async_full_load_std( mdl, NULL );
-   _compass.sm_comp = mdl_get_submesh_index( mdl, "comp" );
-   _compass.sm_comp_bar = mdl_get_submesh_index( mdl, "comp_bar" );
-   _compass.sm_comp_dot = mdl_get_submesh_index( mdl, "comp_dot" );
-   _compass.sm_comp_e = mdl_get_submesh_index( mdl, "comp_e" );
-   _compass.sm_comp_fade = mdl_get_submesh_index( mdl, "comp_fade" );
-   _compass.sm_comp_friend = mdl_get_submesh_index( mdl, "comp_friend" );
-   _compass.sm_comp_gate = mdl_get_submesh_index( mdl, "comp_gate" );
-   _compass.sm_comp_n = mdl_get_submesh_index( mdl, "comp_n" );
-   _compass.sm_comp_notify = mdl_get_submesh_index( mdl, "comp_notify" );
-   _compass.sm_comp_person = mdl_get_submesh_index( mdl, "comp_person" );
-   _compass.sm_comp_s = mdl_get_submesh_index( mdl, "comp_s" );
-   _compass.sm_comp_w = mdl_get_submesh_index( mdl, "comp_w" );
-   _compass.sm_comp_objective = mdl_get_submesh_index( mdl, "comp_objective" );
-   mdl_close( mdl );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_compass_load_content_async );
 }
 
 static void compass_project( m3x3f base_projection, f32 x, f32 height )
@@ -76,37 +74,36 @@ void compass_render_texture(void)
    projection[0][0] = 512.0f/400.0f;
    projection[1][1] = 512.0f/50.0f;
 
-   mdl_context *mdl = &_compass.mdl;
-   mesh_bind( &mdl->mesh );
+   vg_model *mdl = &_compass.model;
+   vg_model_bind_mesh( mdl );
 
    shader_compass_use();
    shader_compass_uTexMain( 0 );
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, mdl->textures[0].glname );
+   vg_tex_bind( GL_TEXTURE_2D, &mdl->textures[0].tex, 0 );
 
    /* base */
    shader_compass_uColour( (v4f){ 1,1,1,0.4 } );
    compass_project( projection, 0,0 );
-   mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_bar ] );
+   vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_bar ] );
 
    if( compass_a( projection, 0.0f, 0 ) )
-      mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_n ] );
+      vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_n ] );
 
    if( compass_a( projection, VG_PIf/2.0f, 0 ) )
-      mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_e ] );
+      vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_e ] );
 
    if( compass_a( projection, VG_PIf, 0 ) )
-      mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_s ] );
+      vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_s ] );
 
    if( compass_a( projection, -VG_PIf/2.0f, 0 ) )
-      mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_w ] );
+      vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_w ] );
 
    for( u32 i=0; i<4; i ++ )
    {
       f32 a = VG_PIf/4.0f + (f32)i * (VG_PIf/2.0f);
       if( compass_a( projection, a, 0 ) )
       {
-         mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_dot ] );
+         vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_dot ] );
       }
    }
 
@@ -120,11 +117,11 @@ void compass_render_texture(void)
          struct network_player *player = &netplayers.list[i];
          if( player->active && player->same_world )
          {
-            struct skeleton *sk = &localplayer.skeleton;
+            ms_skeleton *sk = &localplayer.skeleton;
             m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*i ];
 
             if( compass_co( projection, final_mtx[0][3], 0.0f ) )
-               mdl_draw_submesh( &mdl->submeshes[ player->isfriend? _compass.sm_comp_friend: _compass.sm_comp_person ] );
+               vg_model_draw_submesh( &mdl->submeshes[ player->isfriend? _compass.sm_comp_friend: _compass.sm_comp_person ] );
          }
       }
    }
@@ -141,7 +138,7 @@ void compass_render_texture(void)
       if( marker->flags & k_ent_marker_flag_gui_icon )
       {
          if( compass_co( projection, marker->transform.co, 0.0f ) )
-            mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_notify ] );
+            vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_notify ] );
       }
    }
    for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
@@ -152,7 +149,7 @@ void compass_render_texture(void)
       if( !challenge->status )
       {
          if( compass_co( projection, challenge->transform.co, 0.0f ) )
-            mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+            vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
       }
    }
 
@@ -181,7 +178,7 @@ void compass_render_texture(void)
             ent_gate *gate = af_arritm( &world->ent_gate, cp->gate_index );
 
             if( compass_co( projection, gate->co[0], 0.0f ) )
-               mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_gate ] );
+               vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_gate ] );
          }
       }
    }
@@ -194,21 +191,21 @@ void compass_render_texture(void)
          if( !(route->flags & (k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver)) )
          {
             if( compass_co( projection, route->board_transform[3], 0.0f ) )
-               mdl_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
+               vg_model_draw_submesh( &mdl->submeshes[ _compass.sm_comp_objective ] );
          }
       }
    }
 }
 
-void compass_render_imgui( ui_context *ctx )
+VG_API void _compass_render_imgui( ui_context *ctx )
 {
    if( skaterift.activity == k_skaterift_replay )
       return;
 
    ui_rect rect = { 0,0, 800, 100 };
-   ui_rect_center( (ui_rect){0,0,vg.window_x,100}, rect );
+   ui_rect_center( (ui_rect){0,0,_vg_window.w,100}, rect );
    ui_flush( ctx, k_ui_shader_colour, NULL );
    vg_ui.colour[3] = _compass.alpha;
-   ui_image( ctx, rect, &g_render.fb_compass->attachments[0].id, 0 );
+   ui_image( ctx, rect, &g_render.fb_compass->attachments[0].tex, 0 );
    vg_ui.colour[3] = 1.0f;
 }
index 8337610812fbf5202ed44ac6fc57d93db8247645..ec4855184bea350f7f0d637c9b183c7e240c5302 100644 (file)
@@ -1,9 +1,10 @@
-#pragma once
-#include "vg/vg_framebuffer.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/compass.c"
+#else
 
 struct _compass
 {
-   mdl_context mdl;
+   vg_model model;
 
    i32 sm_comp,
        sm_comp_bar,
@@ -23,7 +24,9 @@ struct _compass
 }
 extern _compass;
 
-void compass_init(void);
-void compass_register(void);
+VG_API void _compass_register(void);
+VG_API void _compass_init(void);
 void compass_render_texture(void);
-void compass_render_imgui( ui_context *ctx );
+VG_API void _compass_render_imgui( ui_context *ctx );
+
+#endif
index 9c4293800836161dc5cd64ce4f610a49e68d8666..a55f5e0b5d3cf244665cbecd30c91343c5d5543e 100644 (file)
@@ -1,50 +1,26 @@
-#include "control_overlay.h"
-#include "model.h"
-#include "input.h"
-#include "player.h"
-#include "player_skate.h"
-#include "player_walk.h"
-#include "shaders/model_menu.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_mem.h"
-#include "vg/vg_m.h"
-
-struct control_overlay control_overlay = { .enabled = 1 };
+struct control_overlay _control_overlay = { .enabled = 1 };
 
 static void render_overlay_mesh( enum control_overlay_mesh index )
 {
-   mdl_draw_submesh( &control_overlay.mdl.submeshes[ index ] );
+   vg_model_draw_submesh( &_control_overlay.model.submeshes[ index ] );
 }
 
-static void control_overlay_init_finish( void *userdata )
+VG_API void _control_overlay_register(void)
 {
-   mdl_context *mdl = &control_overlay.mdl;
-   if( mdl->texture_count )
-   {
-      mdl_texture *tex = &mdl->textures[ 0 ];
-      control_overlay.tex = tex->glname;
-   }
-   else
-   {
-      control_overlay.tex = vg.tex_missing;
-      vg_error( "No texture in control overlay\n" );
-   }
+   vg_console_reg_var( "control_overlay", &_control_overlay.enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
 }
 
-void control_overlay_register(void)
+static void _control_overlay_load_content_async( void *_, vg_async_info *async )
 {
-   vg_console_reg_var( "control_overlay", &control_overlay.enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   vg_model_load( &_control_overlay.model, VG_MODEL_ENGINE_STANDARD, "models/rs_overlay.mdl", NULL );
+   VG_ASSERT( _control_overlay.model.texture_count );
 }
 
-void control_overlay_init(void)
+VG_API void _control_overlay_init(void)
 {
-   mdl_context *mdl = &control_overlay.mdl;
-
-   mdl_open( mdl, "models/rs_overlay.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
-   mdl_async_full_load_std( mdl, NULL );
-   mdl_close( mdl );
-   vg_async_call( &vg.main_tasks, control_overlay_init_finish, NULL );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_control_overlay_load_content_async );
 }
 
 static void draw_key( bool press, bool wide )
@@ -72,7 +48,7 @@ static void colorize( bool press, bool condition )
 
 void control_overlay_render(void)
 {
-   if( !control_overlay.enabled ) return;
+   if( !_control_overlay.enabled ) return;
    if( skaterift.activity != k_skaterift_default ) return;
    if( _cutscene.state != k_cutscene_state_none ) return;
    if( localplayer.subsystem == k_player_subsystem_dead ) return;
@@ -93,7 +69,7 @@ void control_overlay_render(void)
    glBlendEquation(GL_FUNC_ADD);
 
    m4x4f ortho;
-   f32  r = (f32)vg.window_x / (f32)vg.window_y,
+   f32  r = (f32)_vg_window.w / (f32)_vg_window.h,
        fl = -r,
        fr =  r,
        fb =  1.0f,
@@ -117,10 +93,8 @@ void control_overlay_render(void)
    shader_model_menu_uPv( ortho );
    shader_model_menu_uColour( cnorm );
 
-   mdl_context *mdl = &control_overlay.mdl;
-   mesh_bind( &mdl->mesh );
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, control_overlay.tex );
+   vg_model_bind_mesh( &_control_overlay.model );
+   vg_tex_bind( GL_TEXTURE_2D, &_control_overlay.model.textures[0].tex, 1 );
 
    enum player_subsystem subsytem = localplayer.subsystem;
 
index a8f734abc8bf45fa9f787e9eacedb2e010cb8065..bda9485b87b918230ce438ac9fc7f5d068805458 100644 (file)
@@ -1,18 +1,22 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/control_overlay.c"
+#else
 
 enum control_overlay_mesh
 {
-   #include "control_overlay.h.generated"
+   #include "src.generated/control_overlay.h"
 };
 
 struct control_overlay
 {
-   mdl_context mdl;
-   GLuint tex;
+   vg_model model;
    i32 enabled;
 }
-extern control_overlay;
+extern _control_overlay;
+
+VG_API void _control_overlay_register(void);
+VG_API void _control_overlay_init(void);
 
 void control_overlay_render(void);
-void control_overlay_init(void);
-void control_overlay_register(void);
+
+#endif
diff --git a/src/cutscene.c b/src/cutscene.c
new file mode 100644 (file)
index 0000000..b5c65d6
--- /dev/null
@@ -0,0 +1,978 @@
+struct _cutscene _cutscene;
+
+struct cs_instance *_cutscene_get_first_model_instance( const c8 *mdl_name )
+{
+   for( u32 i=0; i<_cutscene.instance_count; i ++ )
+   {
+      struct cs_instance *inst = &_cutscene.instances[i];
+      struct model_ref *mref = &_cutscene.refs[ inst->ref_id ];
+      
+      if( vg_str_eq( mdl_name, mref->name ) )
+         return inst;
+   }
+
+   return NULL;
+}
+
+void _cutscene_unload(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   vg_info( "Unloading cutscene\n" );
+   vg_audio_lock();
+   vg_audio_set_flagged_pause( AUDIO_FLAG_CUTSCENE, 0 );
+   vg_audio_fadeout_flagged_audio( AUDIO_FLAG_CUTSCENE, 1.0f );
+   vg_audio_unlock();
+
+   for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+      vg_model_unload_gpu( &_cutscene.refs[i].model );
+
+   _cutscene.unique_refs = 0;
+   _cutscene.active_camera = NULL;
+   _cutscene.strip = 0;
+   _cutscene.time = 0.0f;
+   _cutscene.active_samplers = 0;
+   _cutscene.state = k_cutscene_state_unloading;
+   _cutscene.player_binding = NULL;
+   _cutscene.subtitle = NULL;
+   _cutscene.raiser_entity = 0;
+   _cutscene.fadeout = 0;
+   _cutscene.skipped = 0;
+   _cutscene.fadeout_start = 0.0f;
+}
+
+/*
+ * Find associated entity data. We should also probably do this on the world
+ * thingy
+ */
+struct cs_asoc
+{
+   vg_model *orig_data;
+   u16 entity_type,
+       entity_index;
+   ms_override *override;
+};
+
+static void _cutscene_override_asoc( u32 instance_id, u32 override_index, struct cs_asoc *out_asoc )
+{
+   struct cs_instance *instance = &_cutscene.instances[ instance_id ];
+   vg_model *model = &_cutscene.refs[ instance->ref_id ].model;
+
+   ms_instance *oins = af_arritm( &_cutscene.meta.instances, instance_id );
+   ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + override_index );
+
+   out_asoc->orig_data = model;
+   out_asoc->entity_type = override->entity_type;
+   out_asoc->override = override;
+   const char *name = af_str( _cutscene.meta.packed_strings, override->pstr_name );
+   u32 name_hash = af_str_hash( _cutscene.meta.packed_strings, override->pstr_name );
+
+   if( out_asoc->entity_type != 28 ) 
+      goto NOT_IMPLEMENTED;
+
+   for( u32 j=0; j<model->armature_count; j ++ )
+   {
+      mdl_armature *armature = &model->armatures[ j ];
+      if( af_str_eq( model->packed_strings, armature->pstr_name, name, name_hash ) )
+      {
+         out_asoc->entity_index = j;
+         return;
+      }
+   }
+
+NOT_IMPLEMENTED:
+
+   vg_fatal_error( "The data association was not found.\n"
+                   "  Entity Type: %u\n"
+                   "  Entity name: %s\n", override->entity_type, name );
+}
+
+static void _cutscene_get_strip_asoc( ms_strip *strip, struct cs_asoc *out_asoc )
+{
+   VG_ASSERT( strip->mode & k_ms_strip_mode_animation );
+   if( strip->strip.instance_id == 0xffffffff )
+   {
+      out_asoc->orig_data = NULL;// &_cutscene.meta;
+      out_asoc->entity_type = mdl_entity_id_type( strip->strip.object_id );
+      out_asoc->entity_index = mdl_entity_id_id( strip->strip.object_id );
+      out_asoc->override = NULL;
+   }
+   else
+      _cutscene_override_asoc( strip->strip.instance_id, strip->strip.object_id, out_asoc );
+}
+
+static void sync_cutscene_loaded( void *nothing, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   vg_info( "Cutscene loaded\n" );
+   _cutscene.state = k_cutscene_state_ready;
+}
+
+struct cutscene_load_info 
+{
+   u32 nothing;
+   char path[];
+};
+static void cutscene_load_thread( struct cutscene_load_info *in_args, vg_async_info *info )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+   vg_info( "Loading cutscene: %s\n", in_args->path );
+   vg_stack_init( &_cutscene.stack, NULL, VG_MB(20), "Cutscene Stack" );
+   metascene_load( &_cutscene.meta, in_args->path, &_cutscene.stack );
+   _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances );
+   _cutscene.instances = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_instance) * _cutscene.instance_count, 
+                                             8, "Instances" );
+
+   _cutscene.refs = vg_stack_allocate( &_cutscene.stack, 0, 8, "References" );
+   _cutscene.unique_refs = 0;
+   for( u32 i=0; i < _cutscene.instance_count; i ++ )
+   {
+      ms_instance *instance = af_arritm( &_cutscene.meta.instances, i );
+      const char *name = af_str( _cutscene.meta.packed_strings, instance->pstr_name );
+      u32 name_hash = af_str_hash( _cutscene.meta.packed_strings, instance->pstr_name );
+
+      struct model_ref *ref = NULL;
+      u32 ref_id = 0;
+
+      for( u32 j=0; j<_cutscene.unique_refs; j ++ )
+      {
+         struct model_ref *ref_j = &_cutscene.refs[ j ];
+
+         if( af_str_eq( _cutscene.meta.packed_strings, instance->pstr_name, ref_j->name, ref_j->name_hash ) )
+         {
+            ref = ref_j;
+            ref_id = j;
+            break;
+         }
+      }
+
+      if( !ref )
+      {
+         vg_stack_extend_last( &_cutscene.stack, sizeof(struct model_ref) );
+         ref_id = _cutscene.unique_refs;
+         ref = &_cutscene.refs[ ref_id ];
+         ref->name = name;
+         ref->name_hash = name_hash;
+         ref->reference_count = 0;
+         vg_info( "Indexed reference '%s'\n", name );
+         _cutscene.unique_refs ++;
+      }
+
+      ref->reference_count ++;
+      _cutscene.instances[ i ].ref_id = ref_id;
+      _cutscene.instances[ i ].skinning_data = NULL;
+      _cutscene.instances[ i ].disable_render = 0;
+   }
+
+   /* load model data */
+   for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+   {
+      struct model_ref *ref = &_cutscene.refs[ i ];
+      char mdl_path_buf[ 512 ];
+      vg_str mdl_path;
+      vg_strnull( &mdl_path, mdl_path_buf, sizeof(mdl_path_buf) );
+      vg_strcat( &mdl_path, ref->name );
+      vg_strcat( &mdl_path, ".mdl" );
+
+      vg_info( "Loading instance model: %s\n", mdl_path.buffer );
+      vg_model_load( &ref->model, VG_MODEL_ENGINE_STANDARD, mdl_path.buffer, &_cutscene.stack );
+
+      u32 skeleton_count = ref->model.armature_count;
+      if( skeleton_count )
+      {
+         ref->skeletons = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_skeleton) * skeleton_count, 8, "Skeletons" );
+         ref->total_skinning_bones = 0;
+         for( u32 j=0; j<skeleton_count; j ++ )
+         {
+            struct cs_skeleton *skele = &ref->skeletons[ j ];
+            skeleton_setup( &skele->sk, &ref->model, j, &_cutscene.stack );
+            skele->skinning_offset = ref->total_skinning_bones;
+            ref->total_skinning_bones += skele->sk.bone_count;
+         }
+      }
+      else 
+      {
+         ref->skeletons = NULL;
+         ref->total_skinning_bones = 0;
+      }
+   }
+
+   /* allocate skinning memory per-instance */
+   for( u32 i=0; i<_cutscene.instance_count; i ++ )
+   {
+      struct cs_instance *ins = &_cutscene.instances[ i ];
+      struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+
+      ins->skinning_data = vg_stack_allocate( &_cutscene.stack, sizeof(m4x3f) * ref->total_skinning_bones,
+                                              8, "Skinning Data" );
+      for( u32 j=0; j<ref->total_skinning_bones; j ++ )
+         m4x3_identity( ins->skinning_data[ j ] );
+
+      /* load overrides */
+      ms_instance *oins = af_arritm( &_cutscene.meta.instances, i );
+      for( u32 j=0; j<oins->override_count; j ++ )
+      {
+         ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + j );
+
+         struct cs_asoc asoc;
+         _cutscene_override_asoc( i, j, &asoc );
+
+         VG_ASSERT( asoc.entity_type == 28 );
+
+         struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
+         m4x3f mmdl;
+         mdl_transform_m4x3( &override->transform, mmdl );
+
+         for( u32 l=0; l<skele->sk.bone_count; l ++ )
+            m4x3_copy( mmdl, ins->skinning_data[skele->skinning_offset+l] );
+      }
+   }
+
+   /* audio packs */
+   for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+   {
+      ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
+
+      for( u32 k=0; k<audio->clip_count; k++ )
+      {
+         ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start+k );
+         if( clip->_.file.pack_size )
+            vg_error( "Currently not support packed audio in metascene..." );
+         else
+         {
+            clip->_.clip.path = af_str( _cutscene.meta.packed_strings, clip->_.file.pstr_path );
+            clip->_.clip.flags = audio->flags;
+            clip->_.clip.any_data = NULL;
+            clip->_.clip.size = 0;
+         }
+         vg_audio_clip_load( &clip->_.clip, &_cutscene.stack );
+      }
+   }
+
+   _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)sync_cutscene_loaded );
+}
+
+bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity )
+{
+   if( _cutscene.state != k_cutscene_state_none )
+   {
+      vg_error( "Tried to play cutscene '%s' while already playing one.\n", path );
+      return 0;
+   }
+
+   _cutscene.raiser_entity = raiser_entity;
+
+   for( u32 i=0; i<k_npc_max; i ++ )
+      _ent_npc_set_in_cutscene( i, 0 );
+
+   _cutscene.state = k_cutscene_state_loading;
+   _cutscene.time = 0.0f;
+   _cutscene.strip = 0;
+   _cutscene.active_samplers = 0;
+   _cutscene.freeze_player = freeze_player;
+
+   u32 len = strlen( path ) +1;
+   struct cutscene_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct cutscene_load_info) + len );
+   strcpy( out_args->path, path );
+   _vg_async_send( out_args, (vg_async_fn)cutscene_load_thread );
+   return 1;
+}
+
+/*
+ * Currently draws everything as skinned meshes.
+ */
+static void cutscene_render_instance( struct cs_instance *ins, vg_camera *cam )
+{
+   if( ins->disable_render )
+      return;
+
+   struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+   vg_model *mdl = &ref->model;
+   vg_model_bind_mesh( mdl );
+
+   shader_model_character_view_use();
+   shader_model_character_view_uCamera( cam->transform[3] );
+   shader_model_character_view_uPv( cam->mtx.pv );
+   shader_model_character_view_uDepthMode( 0 );
+   shader_model_character_view_uShadeless( 0 );
+   shader_model_character_view_uUvOffset( (v2f){0,0} );
+
+   WORLD_LINK_LIGHTING( &_world.main, model_character_view );
+   shader_model_character_view_uTexMain( 0 );
+
+   u32 armature_id = 0x00;
+   u32 material_id = 0x00;
+   bool using_additive = 0;
+
+   for( u32 i=0; i<mdl->mesh_count; i ++ )
+   {
+      mdl_mesh *mesh = &mdl->meshes[ i ];
+      VG_ASSERT( mesh->armature_id );
+
+      if( mesh->armature_id != armature_id )
+      {
+         armature_id = mesh->armature_id;
+         u32 sk_index = mdl_entity_id_id( armature_id );
+
+         struct cs_skeleton *skele = &ref->skeletons[ sk_index ];
+         m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset;
+         shader_model_character_view_uTransforms( skinning_data, skele->sk.bone_count );
+      }
+
+      for( u32 j=0; j<mesh->submesh_count; j ++ )
+      {
+         mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
+         VG_ASSERT( sm->material_id );
+
+         if( sm->material_id != material_id )
+         {
+            mdl_material *m = &mdl->materials[ sm->material_id-1 ];
+            VG_ASSERT( m->shader == k_shader_standard );
+
+            union shader_props *props = &mdl->shader_props[ sm->material_id-1 ];
+            VG_ASSERT( props->standard.tex_diffuse );
+            vg_tex_bind( GL_TEXTURE_2D, &mdl->textures[ props->standard.tex_diffuse-1 ].tex, 0 );
+
+            if( props->standard.render_flags & k_material_render_additive )
+            {
+               using_additive = 1;
+               glDepthMask(GL_FALSE);
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_ONE, GL_ONE);
+               glBlendEquation(GL_FUNC_ADD);
+               glDisable( GL_CULL_FACE );
+               shader_model_character_view_uShadeless( 1 );
+            }
+            else
+            {
+               if( using_additive )
+               {
+                  using_additive = 0;
+                  glDepthMask(GL_TRUE);
+                  glDisable(GL_BLEND);
+                  glEnable( GL_CULL_FACE );
+                  shader_model_character_view_uShadeless( 0 );
+               }
+            }
+         }
+
+         vg_model_draw_submesh( sm );
+      }
+   }
+
+   if( using_additive )
+   {
+      shader_model_character_view_uShadeless( 0 );
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+   }
+}
+
+#define CS_LOCATION 0
+#define CS_ANGLES 4
+#define CS_FOV 8
+
+struct cs_link_info
+{
+   f32 *target;
+   u32 semantic_type;
+};
+
+static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath, struct cs_link_info *out_link )
+{
+   if( asoc->entity_type != k_ent_camera )
+   {
+      vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+      VG_ASSERT( 0 );
+   }
+   ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc->entity_index );
+
+   struct
+   {
+      const char *prefix;
+      f32 *arr;
+      u32 semantic;
+   }
+   reference[] =
+   {
+      { "location:", cam->co, CS_LOCATION },
+      { "rotation_euler:", cam->r, CS_ANGLES },
+      { "lens:", &cam->fov, CS_FOV }
+   };
+
+   for( u32 i=0; i<VG_ARRAY_LEN(reference); i ++ )
+   {
+      u32 len = strlen( reference[i].prefix );
+      if( !strncmp( reference[i].prefix, datapath, len ) )
+      {
+         i32 offset = atoi( datapath + len );
+         out_link->target = reference[i].arr + offset;
+         out_link->semantic_type = reference[i].semantic + offset;
+
+         vg_info( "Linked %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+         return 1;
+      }
+   }
+
+   vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+   return 0;
+}
+
+ent_camera *_cutscene_active_camera(void)
+{
+   return _cutscene.active_camera;
+}
+
+void cutscene_update( f32 delta )
+{
+   if( _cutscene.state == k_cutscene_state_unloading )
+   {
+      // NOTE: This somestimes still fails!
+      if( !vg_audio_flagged_stopped( AUDIO_FLAG_CUTSCENE ) )
+      {
+         static u32 ticker = 0;
+         ticker ++;
+         if( ticker > 50 )
+         {
+            vg_low( "waiting for audio to stop...\n" );
+            ticker = 0;
+         }
+         return;
+      }
+
+      vg_stack_free( &_cutscene.stack );
+      _cutscene.state = k_cutscene_state_none;
+      _cutscene.marker_this_frame = NULL;
+      _cutscene.subtitle = NULL;
+      _cutscene.raiser_entity = 0;
+      vg_info( "Finished unloading cutscene\n" );
+      return;
+   }
+
+   if( _cutscene.state == k_cutscene_state_ready )
+   {
+      _cutscene.player_binding = _cutscene_get_first_model_instance( "models/ch_none" );
+      if( _cutscene.player_binding )
+         _cutscene.player_binding->disable_render = 1;
+
+      /* start playing */
+      if( _cutscene.freeze_player )
+         localplayer.immobile = 1;
+
+      vg_audio_lock();
+      for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+      {
+         ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
+         ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start );
+
+         if( audio->flags & AUDIO_FLAG_AUTO_START )
+         {
+            const u16 group = 0xfff1;
+            const u32 flags = AUDIO_FLAG_CUTSCENE;
+
+            if( audio->flags & AUDIO_FLAG_SPACIAL_3D )
+               vg_audio_oneshot_3d( &clip->_.clip, audio->transform.co, audio->transform.s[0], audio->volume, group,flags);
+            else
+               vg_audio_oneshot( &clip->_.clip, 1.0f, 0.0f, group, flags );
+         }
+      }
+      vg_audio_unlock();
+
+      _cutscene.state = k_cutscene_state_playing;
+      _world_raise_event( _cutscene.raiser_entity, "start" );
+   }
+
+   if( _cutscene.state != k_cutscene_state_playing )
+      return; 
+
+   _cutscene.marker_this_frame = NULL;
+   _cutscene.time += delta;
+   i32 frame = _cutscene.time * _cutscene.meta.info.framerate;
+
+   /* clear out finished samplers */
+   bool move = 0;
+   u32 j = 0;
+   for( u32 i=0; i<_cutscene.active_samplers; i ++ )
+   {
+      struct cs_sampler *si = &_cutscene.samplers[i];
+
+      if( frame > (si->strip->offset + (i32)si->strip->strip.length) )
+         move = 1;
+      else
+      {
+         if( move )
+         {
+            struct cs_sampler *sj = &_cutscene.samplers[j];
+            *sj = *si;
+         }
+
+         j ++;
+      }
+   }
+   _cutscene.active_samplers = j;
+
+   /* add new samplers as we get to them */
+   for( u32 i=_cutscene.strip; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+   {
+      ms_strip *strip = af_arritm(&_cutscene.meta.strips, i);
+
+      if( frame < strip->offset )
+         break;
+
+      if( strip->mode & k_ms_strip_mode_animation )
+      {
+         if( frame > strip->offset + (i32)strip->strip.length )
+         {
+            vg_warn( "Skipping?\n" );
+            _cutscene.strip ++;
+            continue;
+         }
+
+         if( _cutscene.skipped == 2 )
+         {
+            _cutscene.strip ++;
+            continue;
+         }
+
+         if( strip->strip.instance_id == 0xffffffff )
+         {
+            const char *strip_name = af_str( _cutscene.meta.packed_strings, strip->strip.pstr_name );
+            vg_info( "+ Strip: '%s' entity: %u\n", strip_name, strip->strip.object_id );
+
+            /* internal link */
+            struct cs_asoc asoc;
+            _cutscene_get_strip_asoc( strip, &asoc );
+
+            if( strip->mode == k_ms_strip_mode_curves )
+            {
+               for( u32 j=0; j<strip->strip.count; j ++ )
+               {
+                  ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->strip.start + j );
+                  const char *datapath = af_str( _cutscene.meta.packed_strings, track->pstr_datapath );
+                  
+                  struct cs_link_info link;
+                  if( !link_internal_datapath( &asoc, datapath, &link ) )
+                     continue;
+                  
+                  VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
+                  struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
+                  samp->strip = strip;
+                  samp->curves.track = track;
+
+                  samp->curves.target = link.target;
+                  samp->curves.semantic = link.semantic_type;
+                  samp->curves.keyframe = 0;
+                  samp->override = asoc.override;
+                  VG_ASSERT( samp->curves.target );
+               }
+            }
+            else VG_ASSERT(0);
+         }
+         else
+         {
+            /* external link */
+            struct cs_instance *ins = &_cutscene.instances[ strip->strip.instance_id ];
+            struct cs_asoc asoc;
+            _cutscene_get_strip_asoc( strip, &asoc );
+            VG_ASSERT( asoc.entity_type == 28 );
+
+            if( strip->mode == k_ms_strip_mode_keyframes )
+            {
+               VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
+
+               struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
+               struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
+               struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
+
+               samp->strip = strip;
+               samp->skeleton.skinning_data = &ins->skinning_data[ skele->skinning_offset ];
+               samp->skeleton.ref_sk = &skele->sk;
+               samp->override = asoc.override;
+            }
+            else
+            {
+               VG_ASSERT(0);
+            }
+         }
+      }
+      else
+      {
+         if( strip->mode == k_ms_strip_mode_camera )
+         {
+            u32 type = mdl_entity_id_type( strip->camera.entity_id ),
+                index = mdl_entity_id_id( strip->camera.entity_id );
+            VG_ASSERT( type == k_ent_camera );
+            ent_camera *cam = af_arritm( &_cutscene.meta.cameras, index );
+            _cutscene.active_camera = cam;
+         }
+
+         if( strip->mode == k_ms_strip_mode_fadeout )
+         {
+            _cutscene.fadeout = 1;
+            _cutscene.fadeout_start = _cutscene.time;
+         }
+
+         if( strip->mode == k_ms_strip_mode_subtitle )
+         {
+            // FIXME: COLOURS
+            _cutscene.subtitle = af_str( _cutscene.meta.packed_strings, strip->subtitle.pstr_en );
+         }
+
+         if( strip->mode == k_ms_strip_mode_event )
+         {
+            const char *str = af_str( _cutscene.meta.packed_strings, strip->event.pstr_string );
+            vg_info( "cutscene event: %s\n", str );
+            _world_raise_event( _cutscene.raiser_entity, str );
+         }
+      }
+
+      _cutscene.strip ++;
+   }
+
+   /* sample da samplers */
+   for( u32 i=0; i<_cutscene.active_samplers && (_cutscene.skipped != 2); i ++ )
+   {
+      struct cs_sampler *samp = &_cutscene.samplers[ i ];
+
+      if( samp->strip->mode == k_ms_strip_mode_keyframes )
+      {
+         ms_skeletal_animation temp_anim = 
+         {
+            .strip = samp->strip,
+            .framerate = _cutscene.meta.info.framerate,
+            .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->strip.start )
+         };
+
+         f32 t  = _cutscene.time;
+             t -= (f32)samp->strip->offset / _cutscene.meta.info.framerate;
+
+         ms_skeleton *ref_sk = samp->skeleton.ref_sk;
+         m4x3f *final_mtx = samp->skeleton.skinning_data;
+
+         ms_keyframe pose[32];
+         skeleton_sample_anim_clamped( ref_sk, &temp_anim, t, pose );
+
+         skeleton_apply_pose( ref_sk, pose, k_anim_apply_defer_ik, final_mtx );
+         skeleton_apply_ik_pass( ref_sk, final_mtx );
+         skeleton_apply_pose( ref_sk, pose, k_anim_apply_deffered_only, final_mtx );
+         skeleton_apply_inverses( ref_sk, final_mtx );
+
+         if( samp->override )
+         {
+            m4x3f mmdl;
+            mdl_transform_m4x3( &samp->override->transform, mmdl );
+            skeleton_apply_transform( ref_sk, mmdl, final_mtx );
+         }
+
+         skeleton_debug( ref_sk, final_mtx );
+      }
+      else
+      {
+         f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
+             t = (f32)(scene_t - samp->strip->offset) + samp->strip->strip.timing_offset;
+
+         ms_curve_keyframe *kl = af_arritm( &_cutscene.meta.curves, 
+                  samp->curves.track->keyframe_start + samp->curves.keyframe ),
+                           *kr = NULL;
+
+         if( t > kl->co[0] )
+         {
+            if( samp->curves.track->keyframe_count > 1 )
+            {
+               for( u32 j=samp->curves.keyframe+1; j<samp->curves.track->keyframe_count; j ++ )
+               {
+                  kr = af_arritm( &_cutscene.meta.curves, samp->curves.track->keyframe_start + j );
+                  if( kr->co[0] <= t )
+                  {
+                     kl = kr;
+                     kr = NULL;
+                     samp->curves.keyframe = j;
+                  }
+                  else break;
+               }
+            }
+         }
+
+         if( kl && kr )
+            *samp->curves.target = explicit_bezier( kl->co, kl->r, kr->l, kr->co, t );
+         else
+            *samp->curves.target = kl->co[1];
+
+         if( samp->curves.semantic == CS_FOV )
+         {
+            f32 mm  = *samp->curves.target,
+                fov = 2.0f * 57.2957795f * atanf( (36.0f*0.5f) / mm );
+            *samp->curves.target = fov;
+         }
+      }
+   }
+
+   for( u32 i=0; i<af_arrcount( &_cutscene.meta.cameras ); i ++ )
+   {
+      ent_camera *cam = af_arritm( &_cutscene.meta.cameras, i );
+      vg_line_cross( cam->co, VG__RED, 0.2f );
+   }
+
+   f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
+       end_t   = _cutscene.meta.info.end_frame;
+
+   if( scene_t >= end_t )
+   {
+      if( _cutscene.strip != af_arrcount(&_cutscene.meta.strips) )
+      {
+         _cutscene.time = 9999999.9f;
+         _cutscene.skipped = 2; /* signal we can ignore animation strips, just want events for correctness */
+         return;
+      }
+      _world_raise_event( _cutscene.raiser_entity, "end" );
+
+      if( _cutscene.freeze_player )
+         localplayer.immobile = 0;
+
+      _cutscene_unload();
+   }
+}
+
+void _cutscene_render_fadeout(void)
+{
+   bool render = 0;
+   f32 render_alpha = 0.0f;
+
+   if( _cutscene.state >= k_cutscene_state_ready )
+   {
+      if( _cutscene.fadeout )
+      {
+         f32 l = ((f32)_cutscene.meta.info.end_frame/(f32)_cutscene.meta.info.framerate) - _cutscene.fadeout_start,
+             t = (_cutscene.time - _cutscene.fadeout_start) / l;
+         render = 1;
+         render_alpha = t;
+         _cutscene.fadeout_cooldown = 1.0f;
+      }
+   }
+   else
+   {
+      if( _cutscene.fadeout_cooldown > 0.0f )
+      {
+         render = 1;
+         render_alpha = _cutscene.fadeout_cooldown;
+         _cutscene.fadeout_cooldown -= vg.time_delta;
+      }
+   }
+
+   if( render )
+   {
+      glEnable(GL_BLEND);
+      glDisable(GL_DEPTH_TEST);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glBlendEquation(GL_FUNC_ADD);
+
+      shader_blitcolour_use();
+      shader_blitcolour_uColour( (v4f){ 0.04f, 0.02f, 0.03f, vg_clampf( render_alpha, 0.0f, 1.0f ) } );
+      render_fsquad();
+   }
+}
+
+void _cutscene_render( vg_camera *cam )
+{
+   if( _cutscene.state >= k_cutscene_state_ready )
+   {
+      for( u32 i=0; i<_cutscene.instance_count; i ++ )
+         cutscene_render_instance( &_cutscene.instances[i], cam );
+   }
+}
+
+void _cutscene_gui( ui_context *ctx )
+{
+   if( _cutscene.subtitle )
+   {
+      ctx->font = &vgf_default_small;
+      ctx->kern[1] = 16;
+      ui_px scale = 2;
+      ui_rect box = { 0,0, 1000, 80*2 };
+      ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, box );
+      box[1] = _vg_window.h - (box[3] + 8);
+
+      i32 lines = 1;
+      
+      const char *_c = _cutscene.subtitle;
+      u8 c;
+
+      i32 length = 0;
+      ui_px y = box[1];
+
+      while(1) 
+      {
+         c = *(_c ++);
+
+         /* TODO: This is pasted straight from vg_ui, maybe create a vg_ui_text_iter() ...? */
+         if( c == '\x1B' )
+         {
+            while( (c = *(_c ++)) )
+            {
+               if( c == 'm' ) 
+                  break;
+            } 
+           
+            if( c == 0 ) 
+               break;
+            else 
+               continue;
+         }
+
+         if( c >= 32 ) 
+            length ++;
+         else if( c == '\n' || c == '\0' ) 
+         {
+            ui_px w = length * ctx->font->sx*scale + 16;
+            ui_rect background_rect = { _vg_window.w/2 - w/2, y-8, w, ctx->font->sy*scale+16 };
+
+            ui_fill( ctx, background_rect, ui_opacity( GUI_COL_DARK, 0.75f ) );
+            y += (ctx->font->sy)*scale + 16;
+            length = 0;
+            lines ++;
+         }
+         
+         if( c == '\0' )
+            break;
+      }
+
+      ui_text( ctx, box, _cutscene.subtitle, scale, k_ui_align_center, 0 );
+      ctx->font = &vgf_default_small;
+      ctx->kern[1] = 0;
+   }
+}
+
+/* cutscene magi 
+ * ----------------------------------------------------------------------------
+ */
+
+static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
+{
+   if( _cutscene.state == k_cutscene_state_none )
+   {
+      ui_text( ctx, rect, "No cutscene loaded.", 1, k_ui_align_middle_center, 0 );
+      return;
+   }
+
+   if( _cutscene.state == k_cutscene_state_loading )
+   {
+      ui_text( ctx, rect, "Cutscene loading..", 1, k_ui_align_middle_center, 0 );
+      return;
+   }
+
+   if( _cutscene.state == k_cutscene_state_unloading )
+   {
+      ui_text( ctx, rect, "Cutscene UN-loading..", 1, k_ui_align_middle_center, 0 );
+      return;
+   }
+
+   ms_strip *usage[8];
+   for( u32 i=0; i<VG_ARRAY_LEN(usage); i ++ ) usage[i] = NULL;
+
+   ui_rect panel_l, panel_r;
+   ui_split( rect, k_ui_axis_v, 400, 4, panel_l, panel_r );
+
+   if( ui_clip( rect, panel_l, panel_l ) )
+   {
+      ui_px root[2] = { panel_l[0]+8, panel_l[1]+8 };
+      ui_rect box = { root[0], root[1], panel_l[2]-16, 16 };
+
+      for( u32 i=0; i<_cutscene.unique_refs; i ++ )
+      {
+         struct model_ref *mref = &_cutscene.refs[i];
+
+         char inf[128];
+         snprintf( inf, sizeof(inf), "%s (%u references)", mref->name, mref->reference_count );
+         ui_text( ctx, box, inf, 1, k_ui_align_middle_left, 0 );
+         box[1] += 16;
+      }
+   }
+
+   if( ui_clip( rect, panel_r, panel_r ) )
+   {
+      ui_px root[2] = { panel_r[0]+8, panel_r[1]+8 };
+
+      for( u32 i=0; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+      {
+         ms_strip *strip = af_arritm(&_cutscene.meta.strips, i );
+
+         if( !(strip->mode & k_ms_strip_mode_animation) )
+         {
+            ui_rect box = { root[0]+strip->offset, root[1], 1, panel_r[3]-16 };
+            ui_fill( ctx, box, 0xff00ff00 );
+
+            box[1] += box[3] -16;
+            box[2] = 200;
+            box[3] = 16;
+
+            if( ui_clip( panel_r, box, box ) )
+            {
+               if( strip->mode == k_ms_strip_mode_camera )
+                  ui_text( ctx, box, "Camera", 1, k_ui_align_middle_left, 0 );
+               if( strip->mode == k_ms_strip_mode_subtitle )
+                  ui_text( ctx, box, "\"", 1, k_ui_align_middle_left, 0 );
+               if( strip->mode == k_ms_strip_mode_fadeout )
+                  ui_text( ctx, box, "\\", 1, k_ui_align_middle_left, 0 );
+            }
+            continue;
+         }
+         
+         u32 layer = 0;
+         for( u32 k=0; k<VG_ARRAY_LEN(usage); k ++ )
+         {
+            if( usage[k] )
+               if( usage[k]->offset + (i32)usage[k]->strip.length < strip->offset )
+                  usage[k] = NULL;
+
+            if( !usage[k] )
+            {
+               usage[k] = strip;
+               layer = k;
+               break;
+            }
+         }
+
+         ui_rect box = { strip->offset, layer*32, (i32)strip->strip.length, 30 };
+         box[0] += root[0];
+         box[1] += root[1];
+
+         if( ui_clip( panel_r, box, box ) )
+         {
+            u32 colour = af_str_hash( _cutscene.meta.packed_strings, strip->strip.pstr_name );
+            ui_fill( ctx, box, colour | 0xff000000 );
+            ui_text( ctx, box, af_str( _cutscene.meta.packed_strings, strip->strip.pstr_name ), 
+                        1, k_ui_align_middle_center, 0 );
+         }
+      }
+
+      ui_rect cursor = { (f32)_cutscene.time*_cutscene.meta.info.framerate, 0, 1, VG_ARRAY_LEN(usage)*32 };
+      cursor[0] += root[0];
+      cursor[1] += root[1];
+      if( ui_clip( panel_r, cursor, cursor ) )
+         ui_fill( ctx, cursor, 0xffffffff );
+   }
+}
+
+static int cmd_cutscene_play( int argc, const char *argv[] )
+{
+   if( argc == 1 )
+      _cutscene_load_and_play( argv[0], 0, 0 );
+   return 1;
+}
+
+static int cmd_cutscene_inspector( int argc, const char *argv[] )
+{
+   ui_px w = 800, h = 400;
+   struct vg_magi_panel *magi = _vg_magi_open( w, h, VG_MAGI_ALL );
+   magi->title = "Cutscene Inpsector";
+   magi->data = NULL;
+   magi->ui_cb = cb_cutscene_view;
+   magi->close_cb = NULL;
+   return 1;
+}
+
+VG_API void _cutscene_register(void)
+{
+   vg_console_reg_cmd( "cutscene_play", cmd_cutscene_play, NULL );
+   vg_console_reg_cmd( "cutscene_inspector", cmd_cutscene_inspector, NULL );
+}
diff --git a/src/cutscene.h b/src/cutscene.h
new file mode 100644 (file)
index 0000000..534e6ab
--- /dev/null
@@ -0,0 +1,111 @@
+#if defined( SR_IMPLEMENTATION )
+# include "src/cutscene.c"
+#else
+
+struct cs_instance 
+{
+   bool disable_render;
+   u32 ref_id;
+   m4x3f *skinning_data;
+};
+
+struct cs_subtitle
+{
+   const char *key, *value;
+};
+
+struct _cutscene
+{
+   metascene meta;
+   vg_stack_allocator stack;
+
+   enum cutscene_state
+   {
+      k_cutscene_state_none,
+      k_cutscene_state_loading,
+      k_cutscene_state_unloading,
+      k_cutscene_state_ready,
+      k_cutscene_state_playing,
+      k_cutscene_state_done,
+   }
+   state;
+
+   struct model_ref
+   {
+      const char *name;
+      u32 name_hash;
+      u32 reference_count;
+
+      vg_model model;
+      struct cs_skeleton
+      {
+         ms_skeleton sk;
+         u32 skinning_offset;
+      }
+      *skeletons;
+      u32 total_skinning_bones;
+   }
+   * refs;
+   u32 unique_refs;
+
+   struct cs_instance *instances;
+   u32 instance_count;
+
+   struct cs_sampler
+   {
+      ms_strip *strip;
+      ms_override *override;
+      union
+      {
+         struct
+         {
+            ms_track *track;
+            f32 *target;
+            u32 keyframe;
+            u32 semantic;
+         }
+         curves;
+
+         struct
+         {
+            ms_skeleton *ref_sk;
+            m4x3f *skinning_data;
+         }
+         skeleton;
+      };
+   }
+   samplers[32];
+   u32 active_samplers;
+
+   ent_camera *active_camera;
+   struct cs_instance *player_binding;
+
+   u32 strip;
+   f32 time;
+
+   bool fadeout;
+   u8 skipped;
+   f32 fadeout_start, fadeout_cooldown;
+
+   const char *marker_this_frame;
+   const char *subtitle;
+   bool subtitle_length_warning;
+
+   bool freeze_player;
+
+   u32 raiser_entity;
+}
+extern _cutscene;
+
+VG_API void _cutscene_register(void);
+void _cutscene_render( vg_camera *cam );
+void _cutscene_render_fadeout(void);
+bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity );
+void _cutscene_unload(void);
+void cutscene_update( f32 delta );
+ent_camera *_cutscene_active_camera(void);
+void _cutscene_gui( ui_context *ctx );
+
+struct cs_instance *_cutscene_get_first_model_instance( const c8 *mdl_name );
+
+#endif
diff --git a/src/demo_check.c b/src/demo_check.c
new file mode 100644 (file)
index 0000000..926f8b5
--- /dev/null
@@ -0,0 +1,47 @@
+struct _demo_check _demo_check;
+
+static void demo_check_not_demo( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _demo_check.mode = 0;
+   _steam_api.demo_mode = 0;
+}
+
+static void demo_check_task( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+   c8 drm[ 32 ];
+   vg_stream drm_file;
+   if( vg_file_stream_open( &drm_file, "DRM", VG_STREAM_READ ) )
+   {
+      vg_stream_read( &drm_file, drm, sizeof(drm) );
+      vg_file_stream_close( &drm_file );
+      if( !strncmp( drm, "blibby!", sizeof(drm) ) )
+         _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)demo_check_not_demo );
+   }
+}
+
+VG_API void _demo_check_init(void)
+{
+   if( _demo_check.mode == 0 )
+   {
+      _demo_check.mode = 1;
+      _steam_api.demo_mode = 1;
+      _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)demo_check_task );
+   }
+}
+
+VG_API void _demo_check_opts(void)
+{
+   if( vg_long_opt( "demo", "Turn demo mode on" ) )
+   {
+      _demo_check.mode = 2;
+      _steam_api.demo_mode = 1;
+   }
+}
+
+VG_API bool _is_running_demo(void)
+{
+   return _demo_check.mode > 0;
+}
diff --git a/src/demo_check.h b/src/demo_check.h
new file mode 100644 (file)
index 0000000..fbb0bbf
--- /dev/null
@@ -0,0 +1,15 @@
+#if defined( SR_IMPLEMENTATION )
+# include "src/demo_check.c"
+#else
+
+struct _demo_check
+{
+   i32 mode;
+}
+extern _demo_check;
+
+VG_API void _demo_check_opts(void);
+VG_API void _demo_check_init(void);
+VG_API bool _is_running_demo(void);
+
+#endif
index 41f0fac7cd71db2b81f18795a59db24ea3a086a5..c6e5300df151707fbe77103383c30d34ff5f3611 100644 (file)
@@ -1,9 +1,6 @@
-#pragma once
-#include "vg/vg_m.h"
-#include "vg/vg_framebuffer.h"
-#include "vg/vg_render.h"
-#include "skaterift.h"
-#include "render.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/depth_compare.c"
+#else
 
 static inline void depth_compare_bind( 
       void (*uTexSceneDepth)(int),
@@ -22,3 +19,5 @@ static inline void depth_compare_bind(
    inverse[2] = cam->farz-cam->nearz;
    uInverseRatioMain( inverse );
 }
+
+#endif
index 73b49fdc45f4d5de7ad2d16618f23fc5549f98d3..b2d96e3cfb928f33cf166d44dbd5603f04d90f43 100644 (file)
@@ -1,5 +1,3 @@
-#include "ent_atom.h"
-
 struct _atom
 {
    struct atom_list
@@ -19,7 +17,7 @@ const char *_ent_atom_name( u32 atom_entity_id )
    if( atom->flags & k_ent_atom_scrap )
       return "<anonymous>";
    else
-      return af_str( &world->meta.af, atom->pstr_alias );
+      return af_str( world->meta.packed_strings, atom->pstr_alias );
 }
 
 i32 _ent_atom_get( u32 atom_entity_id )
@@ -32,7 +30,7 @@ i32 _ent_atom_get( u32 atom_entity_id )
       return atom->scrap_value;
    else
    {
-      const char *alias = af_str( &world->meta.af, atom->pstr_alias );
+      const char *alias = af_str( world->meta.packed_strings, atom->pstr_alias );
       return _atom_get( (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world, alias );
    }
 }
@@ -53,7 +51,7 @@ void _ent_atom_set( u32 atom_entity_id, i32 value )
    else
    {
       enum e_atom_list list = (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world;
-      const char *alias = af_str( &world->meta.af, atom->pstr_alias );
+      const char *alias = af_str( world->meta.packed_strings, atom->pstr_alias );
       _atom_set( list, alias, value );
       _atom_notify( list, alias );
    }
@@ -64,7 +62,7 @@ entity_event_result _ent_atom_event( ent_event *event )
    world_instance *world = &_world.main;
    bool pass = 0, fail = 0;
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "pass_equal" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "pass_equal" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -73,7 +71,7 @@ entity_event_result _ent_atom_event( ent_event *event )
       }
       else return k_entity_event_result_invalid;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "pass_greater" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "pass_greater" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -82,7 +80,7 @@ entity_event_result _ent_atom_event( ent_event *event )
       }
       else return k_entity_event_result_invalid;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -91,7 +89,7 @@ entity_event_result _ent_atom_event( ent_event *event )
       }
       else return k_entity_event_result_invalid;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_or" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_or" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -101,7 +99,7 @@ entity_event_result _ent_atom_event( ent_event *event )
       }
       else return k_entity_event_result_invalid;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_and" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_and" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -118,13 +116,16 @@ entity_event_result _ent_atom_event( ent_event *event )
    return k_entity_event_result_OK;
 }
 
-void serialize_atoms( enum e_atom_list list, vg_msg *msg )
+void serialize_atoms( enum e_atom_list list, vg_kvs *savedata, u32 root )
 {
+   // FIXME
+#if 0
    for( u32 i=0; i<_atom.lists[list].count; i ++ )
    {
       atom *a = &_atom.lists[list].atoms[i];
-      vg_msg_wkvnum( msg, a->alias, k_vg_msg_i32, 1, &a->status );
+      vg_kv_append_vu32( savedata, root, a->alias, &a->status, 1 );
    }
+#endif
 }
 
 static atom *_atom_internal( enum e_atom_list list, const char *alias )
@@ -157,7 +158,7 @@ void _atom_notify( enum e_atom_list list, const char *alias )
       if( atom->flags & k_ent_atom_scrap ) 
          continue;
 
-      if( af_str_eq( &world->meta.af, atom->pstr_alias, alias, vg_strdjb2(alias)) )
+      if( af_str_eq( world->meta.packed_strings, atom->pstr_alias, alias, vg_strdjb2(alias)) )
       {
          _world_raise_event( mdl_entity_id( k_ent_atom, i ), "changed" );
          _world_raise_event( mdl_entity_id( k_ent_atom, i ), value? "true": "false" );
@@ -258,7 +259,7 @@ void _ent_atom_register(void)
 
 void _ent_atom_init(void)
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( _steam_api.disabled )
       return;
index f8be7edd7a23feccfa523e6baa688b6d05a0d24b..1a950eefcc6ff68d4531067a6b5eb361919b9a67 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_atom.c"
+#else
 
 enum e_atom_list
 {
@@ -14,7 +16,7 @@ struct atom
    i32 status;
 };
 
-void serialize_atoms( enum e_atom_list list, vg_msg *msg );
+void serialize_atoms( enum e_atom_list list, vg_kvs *savedata, u32 root );
 
 void _atom_list_clear( enum e_atom_list list );
 i32 _atom_get( enum e_atom_list list, const char *alias );
@@ -25,3 +27,5 @@ void _atom_notify_list( enum e_atom_list list );
 entity_event_result _ent_atom_event( ent_event *event );
 void _ent_atom_register(void);
 void _ent_atom_init(void);
+
+#endif
index d68341ffb7f0863461dbd0aa0372e59efb8f18f8..7ad83ff71a2357a0435211baccc30da1c4ab493c 100644 (file)
@@ -1,5 +1,3 @@
-#include "entity.h"
-
 void ent_camera_unpack( ent_camera *ent, vg_camera *cam )
 {
    v3_copy( ent->co, cam->pos ); /* wow */
index bf4ce14f3ee38bdf50d537d9f971c5a7f9917fc2..5353ed5422dc5c6547d005c1a5a9ddd9fb63a5f6 100644 (file)
@@ -1,3 +1,7 @@
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_camera.c"
+#else
 
 void ent_camera_unpack( ent_camera *ent, vg_camera *cam );
+
+#endif
index e8eec541068fc21938bdb85f5e1649e4fd8d02b1..391a81c0139d3540dafac8c24cb76d510886fd93 100644 (file)
@@ -1,10 +1,3 @@
-#include "vg/vg_engine.h"
-#include "entity.h"
-#include "input.h"
-#include "gui.h"
-#include "audio.h"
-#include "ent_region.h"
-
 void _ent_challenge_clear( ent_challenge *challenge )
 {
    world_instance *world = &_world.main;
@@ -28,7 +21,7 @@ void _ent_challenge_win(void)
 
    if( !challenge->status )
    {
-      gui_notify( "\xb3 Challenge complete!", 5.0f, k_ui_fg );
+      _gui_notify( "\xb3 Challenge complete!", 5.0f, k_ui_fg );
    }
 
    _ent_challenge_clear( challenge );
@@ -56,16 +49,16 @@ entity_event_result ent_challenge_event( ent_event *event )
 {
    world_instance *world = &_world.main;
    ent_challenge *challenge = af_arritm( &world->ent_challenge, mdl_entity_id_id( event->recieve_entity_id ) );
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "view" ) )
    {
       if( world_set_event( k_world_event_challenge ) )
       {
          srinput.state = k_input_state_resume;
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
          vg_str text;
-         if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+         if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
             vg_strcat( &text, "Start" );
-         if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+         if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
             vg_strcat( &text, "Exit" );
 
          localplayer.immobile = 1;
@@ -140,7 +133,7 @@ void _restart_active_challenge(void)
    _world_raise_event( _world.active_challenge_id, "activate" );
 }
 
-void ent_challenge_update(void)
+void _ent_challenge_update(void)
 {
    world_instance *world = &_world.main;
 
@@ -162,7 +155,7 @@ void ent_challenge_update(void)
       if( button_down( k_srbind_maccept ) )
       {
          menu_close();
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
          _world.challenge_state = k_challenge_state_running;
          localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
          menu.disable_open = 0;
@@ -176,7 +169,7 @@ void ent_challenge_update(void)
             _world.active_challenge_id = 0;
             _world.challenge_target = NULL;
             _world.challenge_timer = 0.0f;
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
             _world.challenge_state = k_challenge_state_none;
             localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
             menu.disable_open = 0;
@@ -220,7 +213,7 @@ void ent_challenge_update(void)
             vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
             vg_audio_unlock();
             vg_info( "Challenge expired due to player being out of range.\n" );
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
    }
@@ -239,7 +232,7 @@ void ent_challenge_update(void)
             srinput.state = k_input_state_resume;
             _restart_active_challenge();
             _world.challenge_reset_timer = 0.0f;
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
       else
@@ -260,7 +253,7 @@ void _ent_challenge_ui( ui_context *ctx )
    ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
 
    ui_px w = 340;
-   ui_rect description_box = { vg.window_x - (w + 8), 8, w, 32 };
+   ui_rect description_box = { _vg_window.w - (w + 8), 8, w, 32 };
    ctx->font = &vgf_default_large;
    
    if( !(_world.challenge_state >= k_challenge_state_running) )
@@ -285,7 +278,7 @@ void _ent_challenge_ui( ui_context *ctx )
          ui_fill( ctx, description_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
          ui_outline( ctx, description_box, 1, colour, 0 );
 
-         const char *description = af_str( &world->meta.af, objective->pstr_description_ui );
+         const char *description = af_str( world->meta.packed_strings, objective->pstr_description_ui );
          ui_text( ctx, description_box, description, 1, k_ui_align_middle_center, colour );
 
          description_box[1] += description_box[3] + 4;
@@ -296,7 +289,7 @@ void _ent_challenge_ui( ui_context *ctx )
 
    if( _world.challenge_reset_timer > 0.0f )
    {
-      ui_rect box = { vg.window_x/2 - 200, vg.window_y - 200, 400, 100 };
+      ui_rect box = { _vg_window.w/2 - 200, _vg_window.h - 200, 400, 100 };
       ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, box, 1, GUI_COL_NORM, 0 );
 
@@ -332,7 +325,7 @@ static int _skaterift_challenge_ccmd( int argc, const char *argv[] )
    for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
    {
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-      const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
+      const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
       
       if( all || (atoi( argv[0] ) == index) )
       {
@@ -359,7 +352,7 @@ static int _skaterift_challenge_ccmd( int argc, const char *argv[] )
    for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
    {
       ent_route *route = af_arritm( &world->ent_route, i );
-      const char *alias = af_str( &world->meta.af, route->pstr_name );
+      const c8 *alias = af_str( world->meta.packed_strings, route->pstr_name );
 
       if( all || (atoi( argv[0] ) == index) )
       {
index 0e3a860ed0d3b2c2c13064cd0dbea1ff08e816f6..44845e6ac05666058b1d2c21336556ab2f497940 100644 (file)
@@ -1,9 +1,14 @@
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_challenge.c"
+#else
 
 entity_event_result ent_challenge_event( ent_event *event );
 void _ent_challenge_ui( ui_context *ctx );
 void _restart_active_challenge(void);
 void _ent_challenge_complete( ent_challenge *challenge );
 void _ent_challenge_win(void);
+void _ent_challenge_clear( ent_challenge *challenge );
 void _ent_challenge_register(void);
+void _ent_challenge_update(void);
+
+#endif
index eb95116b4d0f28dc3797e5596dc5a0953387b45a..693135e40516ce4f9433ab6e403fd990bca914a0 100644 (file)
@@ -1,13 +1,11 @@
-#include "ent_cutscene.h"
-
 entity_event_result _ent_cutscene_event( ent_event *event )
 {
    world_instance *world = &_world.main;
    ent_cutscene *cs = af_arritm( &world->ent_cutscene, mdl_entity_id_id( event->recieve_entity_id ) );
 
-        if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "play" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "play" ) )
    {
-      const char *path = af_str( &world->meta.af, cs->pstr_path );
+      const char *path = af_str( world->meta.packed_strings, cs->pstr_path );
       _cutscene_load_and_play( path, (cs->flags & k_ent_cutscene_freeze_player), event->recieve_entity_id );
 
       return k_entity_event_result_OK;
index 13e6ce953213762e3973db241b2955d75aa826d4..59adfab5bf71f5f68754eb12bc05e23c000d4b44 100644 (file)
@@ -1,3 +1,7 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_cutscene.c"
+#else
 
 entity_event_result _ent_cutscene_event( ent_event *event );
+
+#endif
index 0a4a6e492cd2f706d19ac0144c02cff3f9c81a8a..b8d3c9d7ac5581f0c03222fd79c61cf8670818af 100644 (file)
@@ -1,12 +1,8 @@
-#pragma once
-#include "entity.h"
-#include "player_glide.h"
-
 entity_event_result ent_glider_event( ent_event *event )
 {
    world_instance *world = &_world.main;
    ent_glider *glider = af_arritm( &world->ent_glider, mdl_entity_id_id( event->recieve_entity_id ) );
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "lock" ) )
    {
       // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
       if( event->flags == k_ent_event_data_const_i32 )
@@ -18,7 +14,7 @@ entity_event_result ent_glider_event( ent_event *event )
       else
          return k_entity_event_result_invalid;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "equip" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "equip" ) )
    {
       if( !(glider->flags & k_ent_glider_flag_locked) )
          player_glide_equip_glider();
index d92b4d25f5ad813073b3139a8c6a0712ea410f03..ff2683c35abf50ac6b56c2733af1cc96b925cf9c 100644 (file)
@@ -1,4 +1,8 @@
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_glider.c"
+#else
 
 entity_event_result ent_glider_call( ent_event *event );
+entity_event_result ent_glider_event( ent_event *event );
+
+#endif
index 8301bf70caed421e17b1a9e6ed4dca148ba804af..4eb437ae871160f1d4c12657c73bf089ef92e417 100644 (file)
@@ -1,5 +1,3 @@
-#include "ent_list.h"
-
 ent_list *_ent_list_get_aliased( const char *alias )
 {
    world_instance *world = &_world.main;
@@ -8,7 +6,7 @@ ent_list *_ent_list_get_aliased( const char *alias )
    {
       ent_list *list = af_arritm( &world->ent_list, i );
       if( list->alias_type == k_list_alias_string )
-         if( af_str_eq( &world->meta.af, list->pstr_alias, alias, hash ) )
+         if( af_str_eq( world->meta.packed_strings, list->pstr_alias, alias, hash ) )
             return list;
    }
    return NULL;
@@ -129,7 +127,7 @@ entity_event_result _ent_list_world_event( ent_event *event )
    world_instance *world = &_world.main;
    ent_list *list = af_arritm( &world->ent_list, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "visible" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "visible" ) )
    {
       // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
       if( event->flags == k_ent_event_data_const_i32 )
index 808d08d9f593c9e9c938e6da94f59f5c8761b93f..af4b359ed6d3a39fdcb2245c9bfd967b363840eb 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_list.c"
+#else
 
 struct ent_list_iter
 {
@@ -15,3 +17,5 @@ void _ent_list_set_visible( ent_list *list, bool visible );
 entity_event_result _ent_list_world_event( ent_event *event );
 bool _ent_list_check_completed( ent_list *list );
 void _ent_list_set_as_targets( ent_list *list, bool yes );
+
+#endif
index 5f264033b2fd83c533c206160fde9a6b7661b1ff..982ebb05d3f5291672ec9e4d616afad2df18de69 100644 (file)
@@ -1,5 +1,3 @@
-#include "ent_npc.h"
-
 struct
 {
    struct 
@@ -12,7 +10,7 @@ struct
       }
       state;
 
-      mdl_context mdl;
+      vg_model mdl;
       i32 sm_main, sm_hat, sm_glow;
       v3f co, p0, p1;
       f64 command_t;
@@ -41,7 +39,7 @@ struct
    }
    humans[4];
 
-   struct skeleton_anim anim_idle, anim_stand, anim_sit;
+   ms_skeletal_animation anim_idle, anim_stand, anim_sit;
 
    enum npc_sub_state
    {
@@ -207,8 +205,30 @@ static *_sub_contexts[] =
    },
 };
 
-void _ent_npc_init(void)
+static void _ent_npc_load_content( void *_, vg_async_info *async )
+{
+   vg_model_load( &_npc.gino.mdl, VG_MODEL_ENGINE_STANDARD, "models/gino.mdl", VG_STACK_USE_HEAP );
+   _npc.gino.sm_main = vg_model_get_submesh_index( &_npc.gino.mdl, "gino" );
+   _npc.gino.sm_hat = vg_model_get_submesh_index( &_npc.gino.mdl, "gino.hat" );
+   _npc.gino.sm_glow = vg_model_get_submesh_index( &_npc.gino.mdl, "gino.spt" );
+
+   ms_skeleton *sk = &localplayer.skeleton;
+   u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
+   for( u32 i=0; i<4; i ++ )
+   {
+      struct human_npc *human = &_npc.humans[i];
+      human->final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Final MTX" );
+   }
+   player_get_anim( &_npc.anim_idle, "idle_lean+y" );
+   player_get_anim( &_npc.anim_stand, "idle_cycle+y" );
+   player_get_anim( &_npc.anim_sit, "sit" );
+}
+
+VG_API void _ent_npc_init(void)
 {
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_ent_npc_load_content );
+
    for( u32 i=0; i<k_npc_max; i ++ )
    {
       struct sub_context *contexts = _sub_contexts[ i ];
@@ -220,30 +240,9 @@ void _ent_npc_init(void)
          struct sub_context *context = &contexts[i];
          if( context->alias == NULL )
             break;
-
          context->alias_hash = vg_strdjb2( context->alias );
       }
    }
-
-   mdl_context *mdl = &_npc.gino.mdl;
-   mdl_open( mdl, "models/gino.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
-   mdl_async_full_load_std( mdl, NULL );
-   _npc.gino.sm_main = mdl_get_submesh_index( mdl, "gino" );
-   _npc.gino.sm_hat = mdl_get_submesh_index( mdl, "gino.hat" );
-   _npc.gino.sm_glow = mdl_get_submesh_index( mdl, "gino.spt" );
-   mdl_close( mdl );
-
-   struct skeleton *sk = &localplayer.skeleton;
-   u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
-   for( u32 i=0; i<4; i ++ )
-   {
-      struct human_npc *human = &_npc.humans[i];
-      human->final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Final MTX" );
-   }
-   player_get_anim( &_npc.anim_idle, "idle_lean+y" );
-   player_get_anim( &_npc.anim_stand, "idle_cycle+y" );
-   player_get_anim( &_npc.anim_sit, "sit" );
 }
 
 void _ent_npc_reset(void)
@@ -312,9 +311,9 @@ void _ent_npc_speech( enum npc npc_id, const char *speech_alias )
       _npc.sub_state = k_npc_sub_reading;
       _cutscene.subtitle = sub->value;
 
-      gui_helper_reset( k_gui_helper_mode_black_bars );
+      _gui_helper_reset( k_gui_helper_mode_black_bars );
       vg_str text;
-      if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+      if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
          vg_strcat( &text, "Next" );
       v3_copy( localplayer.rb.co, _npc.sub_position );
    }
@@ -324,7 +323,7 @@ void _ent_npc_speech( enum npc npc_id, const char *speech_alias )
       _npc.sub_state = k_npc_sub_off;
       _npc.subtitles = NULL;
       _cutscene.subtitle = NULL;
-      gui_helper_reset( k_gui_helper_mode_clear );
+      _gui_helper_reset( k_gui_helper_mode_clear );
    }
 }
 
@@ -337,7 +336,7 @@ void _ent_npc_preupdate(void)
       {
          _npc.sub_state = k_npc_sub_off;
          _cutscene.subtitle = NULL;
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
       }
    }
 
@@ -423,7 +422,7 @@ void _ent_npc_preupdate(void)
       if( human->alive && (v3_dist2( localplayer.rb.co, human->co ) < 40.0f*40.0f) )
       {
          ms_keyframe apose[32], bpose[32];
-         struct skeleton *sk = &localplayer.skeleton;
+         ms_skeleton *sk = &localplayer.skeleton;
          player_pose *pose = &human->pose;
          pose->type = k_player_pose_type_ik;
          pose->board.lean = 0.0f;
@@ -458,7 +457,7 @@ void _ent_npc_render( vg_camera *cam )
          if( !((_cutscene.state == k_cutscene_state_playing) && human->in_cutscene) )
          {
             m4x3f *final_mtx = human->final_mtx;
-            struct skeleton *sk = &localplayer.skeleton;
+            ms_skeleton *sk = &localplayer.skeleton;
             render_playermodel( cam, world, 0, &human->playermodel, sk, final_mtx );
          }
       }
@@ -471,28 +470,27 @@ void _ent_npc_render( vg_camera *cam )
    shader_model_entity_uTexMain( 0 );
    shader_model_entity_uCamera( cam->transform[3] );
    shader_model_entity_uPv( cam->mtx.pv );
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+   WORLD_LINK_LIGHTING( world, model_entity );
 
-   mesh_bind( &_npc.gino.mdl.mesh );
-   glActiveTexture( GL_TEXTURE0 );
+   vg_model_bind_mesh( &_npc.gino.mdl );
 
    glDepthMask(GL_FALSE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    glBlendEquation(GL_FUNC_ADD);
-   glBindTexture( GL_TEXTURE_2D, _npc.gino.mdl.textures[1].glname );
+   vg_tex_bind( GL_TEXTURE_2D, &_npc.gino.mdl.textures[1].tex, 0 );
 
    m4x3f mmdl;
    m3x3_copy( cam->transform, mmdl );
    v3_copy( _npc.gino.co, mmdl[3] );
    shader_model_entity_uMdl( mmdl );
    glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
-   mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_glow ] );
+   vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_glow ] );
    glDrawBuffers( 2, (GLenum[]){ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 } );
 
    glDepthMask(GL_TRUE);
    glDisable(GL_BLEND);
-   glBindTexture( GL_TEXTURE_2D, _npc.gino.mdl.textures[0].glname );
+   vg_tex_bind( GL_TEXTURE_2D, &_npc.gino.mdl.textures[0].tex, 0 );
 
    v3f v0 = { localplayer.rb.co[0] - _npc.gino.co[0], 0.0f, localplayer.rb.co[2] - _npc.gino.co[2] };
    v3_normalize( v0 );
@@ -506,7 +504,7 @@ void _ent_npc_render( vg_camera *cam )
    m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
    shader_model_entity_uMdl( mmdl );
    shader_model_entity_uPvmPrev( m4mmdl );
-   mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_main ] );
+   vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_main ] );
 
    m3x3f mspin;
    v4f qspin;
@@ -517,7 +515,7 @@ void _ent_npc_render( vg_camera *cam )
    m4x4_mul( cam->mtx_prev.pv, m4mmdl, m4mmdl );
    shader_model_entity_uMdl( mmdl );
    shader_model_entity_uPvmPrev( m4mmdl );
-   mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_hat ] );
+   vg_model_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_hat ] );
 }
 
 entity_event_result ent_npc_event( ent_event *event )
@@ -540,7 +538,7 @@ entity_event_result ent_npc_event( ent_event *event )
    {
       if( npc_aliases[i] )
       {
-         if( AF_STR_EQ( &world->meta.af, npc->pstr_id, npc_aliases[i] ) )
+         if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_id, npc_aliases[i] ) )
          {
              npc_id = i;
              break;
@@ -550,21 +548,21 @@ entity_event_result ent_npc_event( ent_event *event )
 
    if( npc_id == k_npc_none )
    {
-      vg_warn( "No npc with alias: %s\n", af_str( &world->meta.af, npc->pstr_id ) );
+      vg_warn( "No npc with alias: %s\n", af_str( world->meta.packed_strings, npc->pstr_id ) );
       return k_entity_event_result_invalid;
    }
 
    if( npc_id == k_npc_gino )
    {
-      if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "interact" ) )
       {
          vg_audio_lock();
          vg_audio_oneshot( &audio_ui[1], 1.0f, 0.0f, 0, 0 );
          vg_audio_unlock();
-         _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+         _ent_npc_speech( npc_id, af_str( world->meta.packed_strings, npc->pstr_context_id ) );
          return k_entity_event_result_OK;
       }
-      else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
+      else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "proximity" ) )
       {
          if( _npc.gino.current_entity_id != event->source_entity_id )
          {
@@ -587,20 +585,20 @@ entity_event_result ent_npc_event( ent_event *event )
       struct human_npc *human = human_npc( npc_id );
       VG_ASSERT( human );
 
-      if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "interact" ) )
       {
          vg_audio_lock();
          vg_audio_oneshot( &audio_ui[1], 1.0f, 0.0f, 0, 0 );
          vg_audio_unlock();
-         _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+         _ent_npc_speech( npc_id, af_str( world->meta.packed_strings, npc->pstr_context_id ) );
          return k_entity_event_result_OK;
       }
-      else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
+      else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "proximity" ) )
       {
          human->anim = 0;
-              if( AF_STR_EQ( &world->meta.af, npc->pstr_anim, "sit" ) )
+              if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_anim, "sit" ) )
             human->anim = k_npc_sit;
-         else if( AF_STR_EQ( &world->meta.af, npc->pstr_anim, "stand" ) )
+         else if( AF_STR_EQ( world->meta.packed_strings, npc->pstr_anim, "stand" ) )
             human->anim = k_npc_stand;
 
          if( human->alive == 0 )
index 4b607b6eb293d8287c76b6ed21e93d885db60a3f..85342eb3465fa0b1d3eb9e95927c955e0784da45 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_npc.c"
+#else
 
 #define KCOL_JOHN KNRM
 #define KCOL_MIKE KBLU
@@ -17,7 +19,8 @@ enum npc
    k_npc_max
 };
 
-void _ent_npc_init(void);
+VG_API void _ent_npc_init(void);
+
 void _ent_npc_render( vg_camera *cam );
 void _ent_npc_goto( v3f pos, i32 uid );
 void _ent_npc_preupdate(void);
@@ -25,3 +28,5 @@ void _ent_npc_speech( enum npc npc_id, const char *speech_alias );
 void _ent_npc_reset(void);
 void _ent_npc_set_in_cutscene( enum npc npc_id, bool yes );
 entity_event_result ent_npc_event( ent_event *event );
+
+#endif
index 54e947c82812c199f8176454e54fdfc2bd91de60..b8ce2ebdb7e1c6fbc31141b12fa88986b709b650 100644 (file)
@@ -1,12 +1,3 @@
-#include "world.h"
-#include "world_load.h"
-#include "entity.h"
-#include "audio.h"
-#include "vg/vg_steam2.h"
-#include "ent_region.h"
-#include "player.h"
-#include "player_skate.h"
-
 static void ent_objective_pass( world_instance *world, ent_objective *objective )
 {
    objective->flags |= k_ent_objective_passed;
@@ -120,7 +111,7 @@ entity_event_result ent_objective_event( ent_event *event )
    world_instance *world = &_world.main;
    ent_objective *objective = af_arritm( &world->ent_objective, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "trigger" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "trigger" ) )
    {
       if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
       {
@@ -152,10 +143,10 @@ entity_event_result ent_objective_event( ent_event *event )
                   objective->flags |= k_ent_objective_failed;
                   _world.challenge_state = k_challenge_state_fail;
 
-                  gui_helper_reset( k_gui_helper_mode_black_bars );
+                  _gui_helper_reset( k_gui_helper_mode_black_bars );
                   vg_str str;
                   struct gui_helper *helper;
-                  if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+                  if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
                      vg_strcat( &str, "Retry" );
                }
             }
@@ -164,7 +155,7 @@ entity_event_result ent_objective_event( ent_event *event )
 
       return k_entity_event_result_OK;
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "hide" ) )
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "hide" ) )
    {
       // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
       if( event->flags == k_ent_event_data_const_i32 )
index e5e84ace853a6edb2cd2fcd5766c60ab175f3872..bca917b51b6ca0710a8e56bfbc952d3ab997d8a2 100644 (file)
@@ -1,4 +1,7 @@
-#pragma once
-#include "entity.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_objective.c"
+#else
+
 entity_event_result ent_objective_event( ent_event *event );
+
+#endif
index 3b95445823b6a1f79a66c756bc2d5d6ec3549099..bb5195789c9ba9271010f28cd8f158534f875b71 100644 (file)
@@ -1,5 +1,3 @@
-#include "ent_prop.h"
-
 void ent_prop_update( world_instance *world )
 {
    for( u32 i=0; i<af_arrcount( &world->ent_prop ); i ++ )
index 8e294eb531d342d56d5c9f7d65aa95593f1502fc..1f655c42b6e89d635286675d626d8b3983069927 100644 (file)
@@ -1,3 +1,7 @@
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_prop.c"
+#else
+
 void ent_prop_update( world_instance *world );
+
+#endif
index 2024ed6fc7738dc407cea96d34bb6619b904422d..a7fc82e2553c162c6817041a282d7a1a8dd73820 100644 (file)
@@ -1,8 +1,3 @@
-#include "ent_region.h"
-#include "gui.h"
-#include "network_common.h"
-#include "network.h"
-
 struct global_ent_region global_ent_region;
 
 u32 region_spark_colour( u32 flags )
@@ -24,10 +19,10 @@ entity_event_result ent_region_event( ent_event *event )
    if( region->v109.id_list != 0 )
       challenge_list = af_arritm( &world->ent_list, mdl_entity_id_id( region->v109.id_list ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_active" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "set_active" ) )
    {
-      gui_location_print_ccmd( 1, (const char *[]){af_str( &world->meta.af, region->pstr_title)} );
-      vg_strncpy( af_str( &world->meta.af, region->pstr_title ), 
+      gui_location_print_ccmd( 1, (const char *[]){af_str( world->meta.packed_strings, region->pstr_title)} );
+      vg_strncpy( af_str( world->meta.packed_strings, region->pstr_title ), 
                   global_ent_region.location, NETWORK_REGION_MAX,
                   k_strncpy_always_add_null );
       global_ent_region.flags = region->flags;
@@ -118,7 +113,7 @@ void ent_region_re_eval( world_instance *world, bool init )
             if( !(original_flags & (k_ent_route_flag_achieve_silver|k_ent_route_flag_achieve_gold)) &&
                  region->flags & (k_ent_route_flag_achieve_silver|k_ent_route_flag_achieve_gold) )
             {
-               gui_notify( "\xb3 Region completed!", 6.0f, k_ui_fg );
+               _gui_notify( "\xb3 Region completed!", 6.0f, k_ui_fg );
             }
          }
       }
index 4565d6456a8d3852036db68b2fd6de904c85cf43..24b9c8978018611684aaf07cc83fd36d3da46d6c 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "world_entity.h"
-#include "network_common.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_region.c"
+#else
 
 struct global_ent_region
 {
@@ -18,3 +18,5 @@ struct ent_region_unlock_data
 u32 region_spark_colour( u32 flags );
 void ent_region_re_eval( world_instance *world, bool init );
 entity_event_result ent_region_event( ent_event *event );
+
+#endif
index 711e71c0e947be5e6cc6c120b81bba2fe03efaac..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-#include "ent_relay.h"
index 9030863ec9bf90f809510c997df807feda6a3700..263df8dbe115e64c7940d87b83089de1bde655a5 100644 (file)
@@ -1,2 +1,4 @@
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_relay.c"
+#else
+#endif
index c82593d29ca9a139c91ecaec8de7f14f11d2020e..1d8273d17b39be1d37d0c796ac4a6521e7d09791 100644 (file)
@@ -1,9 +1,3 @@
-#include "ent_route.h"
-#include "input.h"
-#include "gui.h"
-#include "network_requests.h"
-#include "user_profile.h"
-
 struct _ent_route _ent_route;
 
 entity_event_result ent_route_event( ent_event *event )
@@ -11,15 +5,15 @@ entity_event_result ent_route_event( ent_event *event )
    world_instance *world = &_world.main;
    ent_route *route = af_arritm( &world->ent_route, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "view" ) )
    {
       if( world_set_event( k_world_event_route_leaderboard ) )
       {
          menu_close();
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
          vg_str text;
 
-         if( gui_new_helper( input_button_list[k_srbind_mback], &text ) )
+         if( _gui_new_helper( input_button_list[k_srbind_mback], &text ) )
             vg_strcat( &text, "Exit" );
          _ent_route.viewing_route_id = event->recieve_entity_id;
          localplayer.immobile = 1;
@@ -53,7 +47,7 @@ void ent_route_preupdate(void)
       {
          srinput.state = k_input_state_resume;
          localplayer.immobile = 0;
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
          return;
       }
    }
@@ -66,9 +60,9 @@ void _ent_route_imgui( ui_context *ctx )
 
    u32 index = mdl_entity_id_id( _ent_route.viewing_route_id );
 
-   ui_fill( ctx, (ui_rect){0,0,vg.window_x,vg.window_y}, 0x01ffffff );
+   ui_fill( ctx, (ui_rect){0,0,_vg_window.w,_vg_window.h}, 0x01ffffff );
    ui_px w = 500;
-   ent_route_leaderboard_ui( ctx, (ui_rect){ vg.window_x/2 - w/2, 64, w, 0 }, index );
+   ent_route_leaderboard_ui( ctx, (ui_rect){ _vg_window.w/2 - w/2, 64, w, 0 }, index );
 }
 
 void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index )
@@ -135,7 +129,7 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
       char mod_uid[ ADDON_UID_MAX ];
 
       addon_make_uid( _world.main.addon_id, mod_uid );
-      network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
+      network_request_scoreboard( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ),
                                   NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, route_index );
    }
 
@@ -146,6 +140,11 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
       return;
    }
 
+   ui_fill( ctx, leaderboard_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+   ui_text( ctx, leaderboard_box, "FIXME FIXME!!!!!", 1, k_ui_align_middle_center, 0 );
+
+   //FIXME////FIXME
+#if 0
    vg_msg body;
    vg_msg_init( &body, board->data, board->data_len );
 
@@ -275,8 +274,8 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
          u64 steamid; 
          vg_msg_getkvintg( &body, "steamid", k_vg_msg_u64, &steamid, NULL );
          ui_px y = bl[1];
-         if( (y + 200+8) > vg.window_y )
-            y = vg.window_y - (200+8);
+         if( (y + 200+8) > _vg_window.h )
+            y = _vg_window.h - (200+8);
          _user_profile_ui( ctx, (ui_rect){ bl[0]-(360+8),y, 360,200 }, steamid );
       }
 
@@ -286,30 +285,17 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
          {
             skaterift.activity = k_skaterift_default;
 
-            u32 last_minute = (u32)( lastsec / 60 );
-
-            // TODO: put this in a header
-            u32 minutes_span = (centiseconds+(200*60)) / (100*60);
-            vg_queue_clear( &_remote_replay.buffer );
-            _remote_replay.min_frame_t = 0.0;
-            _remote_replay.total_chunks = minutes_span;
-            _remote_replay.chunks_downloaded = 0;
+            // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
             u64 steamid; 
             vg_msg_getkvintg( &body, "steamid", k_vg_msg_u64, &steamid, NULL );
-            _remote_replay.steamid = steamid;
-            _remote_replay.state = k_remote_replay_state_init;
-            _remote_replay.last_second = lastsec;
-            
-            for( u32 i=0; i<minutes_span; i ++ )
-            {
-               struct remote_replay_chunk *chunk = &_remote_replay.chunks[i];
-               chunk->minute = last_minute - minutes_span + 1 + i;
-               chunk->state = k_chunk_state_none;
-            }
+#endif
+            u64 steamid = 0;
+            _remote_replay_reset( centiseconds, lastsec, steamid );
 
             world_clear_event( k_world_event_route_leaderboard );
             srinput.state = k_input_state_resume;
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
             _replay2_open_player( k_replay_type_network, 0 );
          }
       }
@@ -320,6 +306,7 @@ void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index
    _ent_route.entries_max = count;
    vg_ui.frosting = 0.015f;
    ui_flush( ctx, k_ui_shader_colour, NULL );
+#endif
    vg_ui.frosting = 0.0f;
    ctx->font = &vgf_default_small;
 }
index 2c8f08046c3b54d1fe3e021bd5b286d7f975601c..830e882b7b2261c62f0dbbb2364fa61c07008d38 100644 (file)
@@ -1,5 +1,6 @@
-#pragma once
-#include "entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_route.c"
+#else
 
 struct _ent_route
 {
@@ -17,3 +18,5 @@ entity_event_result ent_route_event( ent_event *event );
 void ent_route_preupdate(void);
 void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index );
 void _ent_route_imgui( ui_context *ctx );
+
+#endif
index a35b8fc89a87a8bcfb691657c843ef27bf604ec9..650ed31d770ef7b66e7f386bb629df51f8cf7dc4 100644 (file)
@@ -1,5 +1,3 @@
-#include "ent_script.h"
-
 struct
 {
    void **userdata_array;
@@ -46,7 +44,7 @@ void ent_script_alloc( world_instance *world, vg_stack_allocator *stack )
    for( u32 i=0; i<af_arrcount( &world->ent_script ); i ++ )
    {
       ent_script *script = af_arritm( &world->ent_script, i );
-      const char *script_name = af_str( &world->meta.af, script->pstr_script_name );
+      const char *script_name = af_str( world->meta.packed_strings, script->pstr_script_name );
 
       for( u32 j=0; 1; j ++ )
       {
index a29b2fe2418bb8701b81fbce14d98bc4d4d1278f..d6bb64b06b83ccb72a6d501db634fbc023e4fcb1 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_script.c"
+#else
 
 struct script_event_allocate
 {
@@ -57,3 +59,5 @@ void ent_script_start( world_instance *world );
 void ent_script_update( world_instance *world );
 void ent_script_alloc( world_instance *world, vg_stack_allocator *stack );
 entity_event_result _ent_script_world_event( ent_event *event );
+
+#endif
index 004d716471cad66a214bd892918f2fa3575296ad..efe5a2921fea6e60ff7a097acc6834b057e95016 100644 (file)
@@ -1,17 +1,3 @@
-#include "vg/vg_steam2.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_tex.h"
-#include "vg/vg_image.h"
-#include "vg/vg_loader.h"
-#include "ent_skateshop.h"
-#include "world.h"
-#include "player.h"
-#include "gui.h"
-#include "menu.h"
-#include "addon.h"
-#include "save.h"
-#include "network.h"
-
 struct global_skateshop _skateshop;
 
 static void skateshop_update_viewpage(void)
@@ -34,22 +20,12 @@ static void skateshop_update_viewpage(void)
    }
 }
 
-static void skateshop_init_async( void *userdata )
-{
-   THREAD_0;
-
-   skaterift.rt_textures[ k_skaterift_rt_workshop_preview ] = vg.tex_missing;
-   skaterift.rt_textures[ k_skaterift_rt_server_status ] = vg.tex_missing;
-   render_server_status_gui();
-}
-
 /*
  * VG event init
  */
-void skateshop_init(void)
+VG_API void _skateshop_init(void)
 {
-   THREAD_1;
-   vg_async_call( &vg.main_tasks, skateshop_init_async, NULL );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 }
 
 static addon_cache_id skateshop_selected_board_cache_id(void)
@@ -68,7 +44,7 @@ static void skateshop_server_helper_update(void)
    vg_str text;
    vg_strnull( &text, _skateshop.helper_toggle->text, sizeof(_skateshop.helper_toggle->text) );
 
-   if( g_client.demo_mode )
+   if( _is_running_demo() )
    {
       vg_strcat( &text, "Not availible in demo" );
    }
@@ -85,39 +61,37 @@ struct skateshop_scan_info
 {
    enum addon_type type;
 };
-static void skateshop_addon_scan_task( vg_async_task *task )
+static void skateshop_addon_scan_task( struct skateshop_scan_info *in_args, vg_async_info *async )
 {
-   THREAD_1;
-   struct skateshop_scan_info *info = (void *)task->data;
-   if( info->type == k_addon_type_board )
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   if( in_args->type == k_addon_type_board )
       _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
-   else if( info->type == k_addon_type_player )
+   else if( in_args->type == k_addon_type_player )
       _addon_mount_content_folder( k_addon_type_world, "playermodels", ".mdl" );
-   else if( info->type == k_addon_type_world )
+   else if( in_args->type == k_addon_type_world )
       _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
 }
 
 static void skateshop_scan( enum addon_type specific_type )
 {
-   THREAD_0;
-   _mount_workshop_addons( NULL );
-   vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct skateshop_scan_info), 1 );
-   struct skateshop_scan_info *info = (void *)task->data;
-   info->type = specific_type;
-   vg_async_task_dispatch( task, skateshop_addon_scan_task );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _mount_workshop_addons();
+   struct skateshop_scan_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct skateshop_scan_info) );
+   out_args->type = specific_type;
+   _vg_async_send( out_args, (vg_async_fn)skateshop_addon_scan_task );
 }
 
 static void ent_skateshop_helpers_pickable( const char *acceptance )
 {
    vg_str text;
 
-   if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+   if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
       vg_strcat( &text, "Exit" );
 
-   if( (_skateshop.helper_pick = gui_new_helper( input_button_list[k_srbind_maccept], &text)))
+   if( (_skateshop.helper_pick = _gui_new_helper( input_button_list[k_srbind_maccept], &text)))
       vg_strcat( &text, acceptance );
 
-   if( (_skateshop.helper_browse = gui_new_helper( input_axis_list[k_sraxis_mbrowse_h], &text )))
+   if( (_skateshop.helper_browse = _gui_new_helper( input_axis_list[k_sraxis_mbrowse_h], &text )))
       vg_strcat( &text, "Browse" );
 }
 
@@ -137,7 +111,7 @@ static void skateshop_accept_board( addon_cache_id cache_id )
       addon_cache_watch( k_addon_type_board, cache_id );
       localplayer.board_view_slot = cache_id;
       network_send_item( k_netmsg_playeritem_board );
-      gui_helper_reset( k_gui_helper_mode_clear );
+      _gui_helper_reset( k_gui_helper_mode_clear );
       skateshop_playermod( 0 );
       _skateshop.open = 0;
    }
@@ -146,7 +120,7 @@ static void skateshop_accept_board( addon_cache_id cache_id )
 void charshop_quitsave(void)
 {
    _skateshop.open = 0;
-   gui_helper_reset( k_gui_helper_mode_clear );
+   _gui_helper_reset( k_gui_helper_mode_clear );
    skateshop_playermod( 0 );
    srinput.state = k_input_state_resume;
 
@@ -163,14 +137,18 @@ void charshop_quitsave(void)
       
       if( model->flags & PLAYER_MODEL_FLAG_CUSTOMIZABLE )
       {
+         // FIXME////FIXME/FIXME write cpart
+#if 0
          addon_cache_entry *cache_entry = get_addon_cache_entry( k_addon_type_player, slot );
          memcpy( cache_entry->local_cpart, localplayer.playermodel.cpart, ADDON_CPART_MAX );
 
          savedata_file file;
          init_savefile( &file, "" );
-         addon_make_savedata_path( cache_entry->addon_id, file.path );
-         vg_msg_wkvstr( &file.msg, "cpart", localplayer.playermodel.cpart );
-         write_savefile( &file, 1 );
+         //addon_make_savedata_path( cache_entry->addon_id, file.path );
+
+         //vg_msg_wkvstr( &file.msg, "cpart", localplayer.playermodel.cpart );
+         //write_savefile( &file, 1 );
+#endif
       }
 
       network_send_item( k_netmsg_playeritem_player );
@@ -199,7 +177,7 @@ void ent_skateshop_update(void)
             else
             {
                _skateshop.open = 0;
-               gui_helper_reset( k_gui_helper_mode_clear );
+               _gui_helper_reset( k_gui_helper_mode_clear );
                skateshop_playermod( 0 );
                srinput.state = k_input_state_resume;
             }
@@ -274,7 +252,7 @@ void ent_skateshop_update(void)
       {
          f64 delta = vg.time_real - network_client.last_intent_change;
 
-         if( (delta > 5.0) && (!g_client.demo_mode) )
+         if( (delta > 5.0) && !_is_running_demo() )
          {
             _skateshop.helper_pick->greyed = 0;
             if( button_down( k_srbind_maccept ) )
@@ -353,7 +331,7 @@ fade_out:;
    float scale = 0.2f,
          thickness = 0.03f;
 
-   font3d_bind( &gui.font, k_font_shader_default, 0, world, cam );
+   font3d_bind( &gui.font, k_font_shader_default, 0, cam );
    shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
 
    /* Selection counter
@@ -372,9 +350,9 @@ fade_out:;
       char buf[16];
       vg_str str;
       vg_strnull( &str, buf, sizeof(buf) );
-      vg_strcati32( &str, _skateshop.selected_board_index+1 );
+      vg_strcati64( &str, _skateshop.selected_board_index+1, 10 );
       vg_strcatch( &str, '/' );
-      vg_strcati32( &str, valid_count );
+      vg_strcati64( &str, valid_count, 10 );
       font3d_simple_draw( 0, buf, cam, mmdl );
    }
    else
@@ -397,17 +375,17 @@ fade_out:;
    {
       _skateshop.render.item_title = "";
       _skateshop.render.item_desc = "";
-      vg_msg msg;
-      vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
-      if( vg_msg_seekframe( &msg, "workshop" ) )
+      u32 workshop_block = vg_kv_find( &reg->metadata, 0, "workshop" );
+      if( workshop_block )
       {
-         const char *title = vg_msg_getkvstr( &msg, "title" );
-         if( title ) _skateshop.render.item_title = title;
+         const c8 *title = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, workshop_block, "title" ), NULL );
+         if( title ) 
+            _skateshop.render.item_title = title;
 
-         const char *dsc = vg_msg_getkvstr( &msg, "author" );
-         if( dsc ) _skateshop.render.item_desc = dsc;
-         vg_msg_skip_frame( &msg );
+         const c8 *dsc = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, workshop_block, "author" ), NULL );
+         if( dsc ) 
+            _skateshop.render.item_desc = dsc;
       }
 
       _skateshop.render.addon_id = entry->addon_id;
@@ -509,7 +487,7 @@ entity_event_result ent_skateshop_event( ent_event *event )
    world_instance *world = &_world.main;
    ent_skateshop *shop = af_arritm( &world->ent_skateshop, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "open" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "open" ) )
    {
       if( world_set_event( k_world_event_shop ) )
       {
@@ -521,7 +499,7 @@ entity_event_result ent_skateshop_event( ent_event *event )
             skateshop_scan( k_addon_type_board );
          }
 
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
 
          if( shop->type == k_skateshop_type_charshop )
          {
@@ -573,7 +551,7 @@ void charshop_gui( ui_context *ctx )
 
    i32 R = menu_nav( &_skateshop.charshop_row, mv, _skateshop.charshop_row_max );
 
-   ui_rect panel = { 8, 8, 350, vg.window_y };
+   ui_rect panel = { 8, 8, 350, _vg_window.h };
    ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
    ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
    ui_rect_pad( panel, (ui_px[]){8,8} );
@@ -625,14 +603,12 @@ void charshop_gui( ui_context *ctx )
          player__use_model( id );
          addon_reg *reg = addon_details( id );
 
-         vg_msg msg;
-         vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
-         if( vg_msg_seekframe( &msg, "workshop" ) )
+         u32 workshop_block = vg_kv_find( &reg->metadata, 0, "workshop" );
+         if( workshop_block )
          {
-            const char *title = vg_msg_getkvstr( &msg, "title" );
-            if( title ) _skateshop.render.item_title = title;
-            vg_msg_skip_frame( &msg );
+            const c8 *title = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, workshop_block, "title" ), NULL );
+            if( title ) 
+               _skateshop.render.item_title = title;
          }
       }
 
@@ -664,7 +640,7 @@ void charshop_gui( ui_context *ctx )
          for( u32 i=0; i<prop_count; i ++ )
          {
             editer_property *prop = af_arritm( &model->editer_property, i );
-            const char *alias = af_str( &model->mdl.af, prop->pstr_alias );
+            const char *alias = af_str( &model->model.packed_strings, prop->pstr_alias );
 
             if( prop->ui_type == k_editer_type_toggle )
             {
@@ -701,7 +677,7 @@ void charshop_gui( ui_context *ctx )
             }
             else if( prop->ui_type == k_editer_type_selecter )
             {
-               const char *options = af_str( &model->mdl.af, prop->max.pstr_options );
+               const char *options = af_str( model->model.packed_strings, prop->max.pstr_options );
                if( menu_options( ctx, panel, R == i+1, &_skateshop.charshop_col, alias, options, 
                                  &view->property_values[i]._u32, mh, enter ) )
                   edited = 1;
@@ -739,7 +715,7 @@ void charshop_gui( ui_context *ctx )
    ctx->font = &vgf_default_small;
 }
 
-void ent_skateshop_gui( ui_context *ctx )
+void _ent_skateshop_gui( ui_context *ctx )
 {
    if( _world.event == k_world_event_shop )
    {
@@ -775,7 +751,7 @@ void ent_skateshop_gui( ui_context *ctx )
             v2_divs( handles[i], handles[i][3], handles[i] );
             v2_muladds( (v2f){0.5f,0.5f}, handles[i],  0.5f, handles[i] );
             handles[i][1] = 1.0f - handles[i][1];
-            v2_mul( (v2f){ vg.window_x, vg.window_y }, handles[i], handles[i] );
+            v2_mul( (v2f){ _vg_window.w, _vg_window.h }, handles[i], handles[i] );
          }
 
          ui_px r = 24;
index fc5e3046a291819d81241946921776a18ffec811..49d0caa6abfc7e931d58e5cb54d68f9a821b878e 100644 (file)
@@ -1,10 +1,6 @@
-#pragma once
-#include "world.h"
-#include "world_load.h"
-#include "player.h"
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_skateshop.c"
+#else
 
 #define SKATESHOP_VIEW_SLOT_MAX    5
 
@@ -45,7 +41,7 @@ struct global_skateshop
 }
 extern _skateshop;
 
-void skateshop_init(void);
+VG_API void _skateshop_init(void);
 void ent_skateshop_update(void);
 void ent_skateshop_render( vg_camera *cam );
 
@@ -53,3 +49,6 @@ void skateshop_autostart_loading(void);
 void skateshop_world_preupdate(void);
 entity_event_result ent_skateshop_event( ent_event *event );
 void skateshop_world_preview_preupdate(void);
+void _ent_skateshop_gui( ui_context *ctx );
+
+#endif
index 52b33d48a5b65b70dd0f5471f8c8619d2eeaed17..e7072419c817f76cc5461afba4dd7e95f48430cc 100644 (file)
@@ -1,11 +1,8 @@
-#include "world.h"
-#include "particle.h"
-
 static f32 k_tornado_strength = 0.0f,
            k_tornado_ratio    = 0.5f,
            k_tornado_range    = 10.f;
 
-void ent_tornado_register(void)
+VG_API void _ent_tornado_register(void)
 {
    vg_console_reg_var( "k_tonado_strength", &k_tornado_strength,
                         k_var_dtype_f32, VG_VAR_PERSISTENT|VG_VAR_CHEAT );
@@ -21,8 +18,7 @@ void ent_tornado_debug(void)
    for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
    {
       ent_marker *marker = af_arritm( &world->ent_marker, i );
-
-      if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
       {
          v3f p1;
          v3_add( marker->transform.co, (v3f){0,20,0}, p1 );
@@ -44,8 +40,7 @@ void ent_tornado_forces( v3f co, v3f cv, v3f out_a )
    for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
    {
       ent_marker *marker = af_arritm( &world->ent_marker, i );
-
-      if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
       {
          v3f d, dir;
          v3_sub( co, marker->transform.co, d );
@@ -74,8 +69,7 @@ void ent_tornado_pre_update(void)
    for( u32 i=0; i<af_arrcount(&world->ent_marker); i ++ )
    {
       ent_marker *marker = af_arritm( &world->ent_marker, i );
-
-      if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tornado" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tornado" ) )
       {
          v3f co;
          vg_rand_sphere( &vg.rand, co );
index c2dfb8be48d5aaf0709a1aba0cdd61fc6090f446..424f9d0d1a12fb30816eab109e6c3bcd1129ce4b 100644 (file)
@@ -1,6 +1,10 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_tornado.c"
+#else
 
-void ent_tornado_register(void);
+VG_API void _ent_tornado_register(void);
 void ent_tornado_debug(void);
 void ent_tornado_forces( v3f co, v3f cv, v3f out_a );
 void ent_tornado_pre_update(void);
+
+#endif
index a14f62f7aeebffe5349ded118a988507496e1aeb..693fcfb0ddb72561fed32574fff4d3a422fe74f0 100644 (file)
@@ -1,5 +1,3 @@
-#include "world.h"
-
 void ent_traffic_update( world_instance *world, v3f pos )
 {
    for( u32 i=0; i<af_arrcount( &world->ent_traffic ); i++ ){
index 18d8d1ed57947e2d149846aaed8782bdcf76beee..6d60f5e19188c6684941b6f031305af7c8eed64c 100644 (file)
@@ -1,3 +1,5 @@
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/ent_traffic.c"
+#else
 void ent_traffic_update( world_instance *world, v3f pos );
+#endif
index 200450292b60a77bad2e8caa3e7a83009d6bc28b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,16 +0,0 @@
-#include "world.h"
-#include "entity.h"
-#include "world_entity.h"
-
-#include "ent_objective.h"
-#include "ent_skateshop.h"
-#include "ent_relay.h"
-#include "ent_challenge.h"
-#include "ent_route.h"
-#include "ent_region.h"
-#include "ent_glider.h"
-#include "ent_prop.h"
-#include "world_water.h"
-
-#include <string.h>
-
index 10ca6b495030aedfe2ea3d32e0cd212c41f8e8dc..0d6b4dd3216568399a94c40d83f1cb3b70dd32bc 100644 (file)
@@ -1,8 +1,6 @@
-#pragma once
-
-#include "vg/vg_audio.h"
-#include "vg/vg_ui/imgui.h"
-#include "model.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/entity.c"
+#else
 
 typedef struct ent_spawn ent_spawn;
 typedef struct ent_light ent_light;
@@ -781,3 +779,5 @@ struct ent_event
    }
    data;
 };
+
+#endif
diff --git a/src/font.c b/src/font.c
new file mode 100644 (file)
index 0000000..514de1c
--- /dev/null
@@ -0,0 +1,252 @@
+VG_TIER_2 void font3d_load( font3d *font, const c8 *mdl_path, vg_stack_allocator *stack )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &font->model, mdl_path ) );
+   vg_model_stream_metadata( &ctx, stack );
+   vg_model_stream_meshes_gpu( &ctx, NULL );
+   vg_model_stream_textures_gpu( &ctx );
+
+   u32 temp_frame = _vg_start_temp_frame();
+   {
+      array_file_ptr fonts;
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &fonts, ent_font, _vg_temp_stack() );
+      VG_ASSERT( af_arrcount(&fonts) );
+      font->info = *((ent_font *)af_arritm(&fonts,0));
+   }
+   _vg_end_temp_frame( temp_frame );
+
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &font->font_variants, ent_font_variant, stack );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &font->glyphs, ent_glyph, stack );
+   vg_model_stream_close( &ctx );
+}
+
+VG_TIER_0 u32 font3d_find_variant( font3d *font, const c8 *name )
+{
+   for( u32 i=0; i<af_arrcount( &font->font_variants ); i ++ )
+   {
+      ent_font_variant *variant = af_arritm( &font->font_variants, i );
+      if( !strcmp( af_str( font->model.packed_strings, variant->name ), name ) )
+         return i;
+   }
+
+   return 0;
+}
+
+struct _font3d_render
+{
+   v4f offset;
+   font3d *font;
+   u32 variant_id;
+
+   enum font_shader shader;
+}
+static gui_font3d;
+
+/*
+ * world can be null if not using world shader 
+ */
+VG_TIER_0 void font3d_bind( font3d *font, enum font_shader shader, i32 depth_compare, vg_camera *cam )
+{
+   gui_font3d.shader = shader;
+   gui_font3d.font = font;
+   vg_tex_bind( GL_TEXTURE_2D, &font->model.textures[0].tex, 1 );
+
+   if( shader == k_font_shader_default )
+   {
+      shader_model_font_use();
+      shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
+      shader_model_font_uTexMain( 1 );
+      shader_model_font_uDepthMode( depth_compare );
+      if( depth_compare )
+      {
+         depth_compare_bind( shader_model_font_uTexSceneDepth,
+                             shader_model_font_uInverseRatioDepth,
+                             shader_model_font_uInverseRatioMain, cam );
+      }
+      shader_model_font_uPv( cam->mtx.pv );
+   }
+   else if( shader == k_font_shader_world )
+   {
+      shader_scene_font_use();
+      shader_scene_font_uTexGarbage(0);
+      shader_scene_font_uTexMain(1);
+
+      shader_scene_font_uPv( g_render.cam.mtx.pv );
+      shader_scene_font_uTime( vg.time );
+
+      WORLD_LINK_TERRAIN_NOISE( &_world.main, scene_font );
+      WORLD_LINK_LIGHTING( &_world.main, scene_font );
+      shader_scene_font_uCamera( g_render.cam.transform[3] );
+   }
+
+   vg_model_bind_mesh( &font->model );
+}
+
+VG_TIER_0 ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 )
+{
+   if( utf32 < font->info.glyph_utf32_base ) return NULL;
+   if( utf32 >= font->info.glyph_utf32_base+font->info.glyph_count) return NULL;
+
+   u32 index = utf32 - font->info.glyph_utf32_base;
+       index += font->info.glyph_start;
+       index += font->info.glyph_count * variant_id;
+   return af_arritm( &font->glyphs, index );
+}
+
+VG_API void font3d_set_transform( const c8 *text, vg_camera *cam, m4x3f transform )
+{
+   v4_copy( (v4f){0.0f,0.0f,0.0f,1.0f}, gui_font3d.offset );
+
+   m4x4f prev_mtx;
+   m4x3_expand( transform, prev_mtx );
+   m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx );
+
+   if( gui_font3d.shader == k_font_shader_default )
+   {
+      shader_model_font_uPvmPrev( prev_mtx );
+      shader_model_font_uMdl( transform );
+   }
+   else if( gui_font3d.shader == k_font_shader_world )
+   {
+      shader_scene_font_uPvmPrev( prev_mtx );
+      shader_scene_font_uMdl( transform );
+   }
+}
+
+VG_API void font3d_setoffset( v4f offset )
+{
+   if( gui_font3d.shader == k_font_shader_default )
+      shader_model_font_uOffset( offset );
+   else if( gui_font3d.shader == k_font_shader_world )
+      shader_scene_font_uOffset( offset );
+}
+
+VG_API void font3d_setcolour( v4f colour )
+{
+   if( gui_font3d.shader == k_font_shader_default )
+      shader_model_font_uColour( colour );
+#if 0
+   else if( gui_font3d.shader == k_font_shader_world )
+      shader_scene_font_uColour( colour );
+#endif
+}
+
+VG_API void font3d_draw( const c8 *text )
+{
+   u8 *u8pch = (u8*)text;
+
+   u32 max_chars = 512;
+   while( u8pch && max_chars )
+   {
+      max_chars --;
+
+      u32 c0 = *u8pch, c1;
+      u8pch ++;
+
+      if( !c0 ) 
+         break;
+      ent_glyph *glyph0 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c0 ),
+                *glyph1 = NULL;
+      /* multibyte characters */
+      if( c0 >= 1 && c0 < k_SRglyph_ascii_min )
+      {
+         c1 = *u8pch;
+         if( !c1 ) break;
+         glyph1 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c1 );
+      }
+
+      if( c0 == k_SRglyph_ctrl_variant )
+      {
+         gui_font3d.variant_id = c1;
+         u8pch ++;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_size )
+      {
+         gui_font3d.offset[3] = (float)c1 * (1.0f/255.0f);
+         u8pch ++;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_baseline )
+      {
+         gui_font3d.offset[1] = 0.0f;
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_center )
+      {
+         if( glyph1 )
+         {
+            float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
+            gui_font3d.offset[1] = diff * 0.5f;
+         }
+         continue;
+      }
+      else if( c0 == k_SRglyph_ctrl_top )
+      {
+         if( glyph1 )
+         {
+            float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
+            gui_font3d.offset[1] = diff;
+         }
+         continue;
+      }
+
+      if( !glyph0 ) 
+         continue;
+
+      if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle))
+      {
+         v4f v0;
+         v2_sub( glyph0->size, glyph1->size, v0 );
+         v2_muladds( gui_font3d.offset, v0, -0.5f, v0 );
+         v0[2] = gui_font3d.offset[2];
+         v0[3] = gui_font3d.offset[3];
+
+         font3d_setoffset( v0 );
+         vg_model_draw_elements( glyph0->indice_start, glyph0->indice_count );
+         continue;
+      }
+      else
+      {
+         font3d_setoffset( gui_font3d.offset );
+         vg_model_draw_elements( glyph0->indice_start, glyph0->indice_count );
+      }
+
+      gui_font3d.offset[0] += glyph0->size[0]*gui_font3d.offset[3];
+   }
+}
+
+VG_API f32 font3d_simple_draw( u32 variant_id, const c8 *text, vg_camera *cam, m4x3f transform )
+{
+   if( !text )
+      return 0.0f;
+
+   gui_font3d.variant_id = variant_id;
+   font3d_set_transform( text, cam, transform );
+   font3d_draw( text );
+   return gui_font3d.offset[0];
+}
+
+VG_TIER_0 f32 font3d_string_width( u32 variant_id, const c8 *text )
+{
+   if( !text ) 
+      return 0.0f;
+   f32 width = 0.0f;
+
+   const u8 *buf = (const u8 *)text;
+   for( u32 i=0;; i++ )
+   {
+      u32 c = buf[i];
+      if( !c ) 
+         break;
+
+      ent_glyph *glyph = font3d_glyph( gui_font3d.font, variant_id, c );
+      if( !glyph ) 
+         continue;
+
+      width += glyph->size[0];
+   }
+
+   return width;
+}
index c1da41c5be748588388f5f61606b193ceb70fa20..a69c4971a496ebad2bf8a5f5156c4c88b31adfc5 100644 (file)
@@ -1,13 +1,6 @@
-#pragma once
-#include "model.h"
-#include "entity.h"
-#include "vg/vg_camera.h"
-#include "shaders/model_font.h"
-#include "shaders/scene_font.h"
-#include "world_render.h"
-#include "depth_compare.h"
-#include "vg/vg_tex.h"
-#include <string.h>
+#if defined( SR_IMPLEMENTATION )
+# include "src/font.c"
+#else
 
 enum efont_SRglyph{
    k_SRglyph_end           = 0x00, /* control characters */
@@ -71,257 +64,28 @@ enum efont_SRglyph{
 };
 
 typedef struct font3d font3d;
-struct font3d{
-   mdl_context mdl;
-   GLuint texture;
-   glmesh mesh;
-
+struct font3d
+{
+   vg_model model;
    ent_font info;
-   array_file_ptr font_variants,
-                 glyphs;
+   array_file_ptr font_variants, glyphs;
 };
 
-static void font3d_load( font3d *font, const char *mdl_path, void *alloc )
-{
-   THREAD_1;
-   mdl_context *mdl = &font->mdl;
-   mdl_open( mdl, mdl_path, alloc );
-   mdl_load_metadata_block( mdl, alloc );
-
-   vg_stack_clear( &vg.scratch );
-   array_file_ptr fonts;
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &fonts, ent_font, &vg.scratch );
-   font->info = *((ent_font *)af_arritm(&fonts,0));
-
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &font->font_variants, ent_font_variant, alloc );
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &font->glyphs, ent_glyph, alloc );
-   vg_stack_clear( &vg.scratch );
-
-   if( !font->mdl.texture_count )
-      vg_fatal_error( "No texture in font file" );
-
-   mdl_texture *tex0 = &mdl->textures[ 0 ];
-   void *data = vg_stack_allocate( &vg.scratch, tex0->file.pack_size, 8, "Pack data" );
-   mdl_fread_pack_file( mdl, &tex0->file, data );
-
-   mdl_async_load_glmesh( mdl, &font->mesh, NULL );
-   vg_tex2d_load_qoi_async( data, tex0->file.pack_size, VG_TEX2D_LINEAR|VG_TEX2D_CLAMP, &font->texture );
-
-   mdl_close( mdl );
-}
-
-static u32 font3d_find_variant( font3d *font, const char *name )
-{
-   for( u32 i=0; i<af_arrcount( &font->font_variants ); i ++ )
-   {
-      ent_font_variant *variant = af_arritm( &font->font_variants, i );
-
-      if( !strcmp( af_str( &font->mdl.af, variant->name ), name ) )
-         return i;
-   }
-
-   return 0;
-}
-
-struct _font3d_render{
-   v4f offset;
-   font3d *font;
-   u32 variant_id;
-
-   enum font_shader {
-      k_font_shader_default,
-      k_font_shader_world
-   }
-   shader;
-}
-static gui_font3d;
-
-/*
- * world can be null if not using world shader 
- */
-static void font3d_bind( font3d *font, enum font_shader shader, int depth_compare, world_instance *world,vg_camera *cam )
+enum font_shader 
 {
-   gui_font3d.shader = shader;
-   gui_font3d.font = font;
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, font->texture );
-
-   if( shader == k_font_shader_default )
-   {
-      shader_model_font_use();
-      shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
-      shader_model_font_uTexMain( 1 );
-      shader_model_font_uDepthMode( depth_compare );
-
-      if( depth_compare )
-      {
-         depth_compare_bind( 
-            shader_model_font_uTexSceneDepth,
-            shader_model_font_uInverseRatioDepth,
-            shader_model_font_uInverseRatioMain, cam );
-      }
-
-      shader_model_font_uPv( cam->mtx.pv );
-   }
-   else if( shader == k_font_shader_world )
-   {
-      shader_scene_font_use();
-      shader_scene_font_uTexGarbage(0);
-      shader_scene_font_uTexMain(1);
-
-      shader_scene_font_uPv( g_render.cam.mtx.pv );
-      shader_scene_font_uTime( vg.time );
-
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_font );
-
-      bind_terrain_noise();
-      shader_scene_font_uCamera( g_render.cam.transform[3] );
-   }
-   mesh_bind( &font->mesh );
-}
-
-static ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 ){
-   if( utf32 < font->info.glyph_utf32_base ) return NULL;
-   if( utf32 >= font->info.glyph_utf32_base+font->info.glyph_count) return NULL;
-
-   u32 index = utf32 - font->info.glyph_utf32_base;
-       index += font->info.glyph_start;
-       index += font->info.glyph_count * variant_id;
-   return af_arritm( &font->glyphs, index );
-}
-
-static void font3d_set_transform( const char *text,
-                                  vg_camera *cam, m4x3f transform ){
-   v4_copy( (v4f){0.0f,0.0f,0.0f,1.0f}, gui_font3d.offset );
-
-   m4x4f prev_mtx;
-   m4x3_expand( transform, prev_mtx );
-   m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx );
-
-   if( gui_font3d.shader == k_font_shader_default ){
-      shader_model_font_uPvmPrev( prev_mtx );
-      shader_model_font_uMdl( transform );
-   }
-   else if( gui_font3d.shader == k_font_shader_world ){
-      shader_scene_font_uPvmPrev( prev_mtx );
-      shader_scene_font_uMdl( transform );
-   }
-}
+   k_font_shader_default,
+   k_font_shader_world
+};
 
-static void font3d_setoffset( v4f offset ){
-   if( gui_font3d.shader == k_font_shader_default )
-      shader_model_font_uOffset( offset );
-   else if( gui_font3d.shader == k_font_shader_world )
-      shader_scene_font_uOffset( offset );
-}
+VG_TIER_2 void font3d_load( font3d *font, const c8 *mdl_path, vg_stack_allocator *stack );
+VG_TIER_0 u32 font3d_find_variant( font3d *font, const c8 *name );
+VG_TIER_0 void font3d_bind( font3d *font, enum font_shader shader, i32 depth_compare, vg_camera *cam );
+VG_TIER_0 ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 );
+VG_API void font3d_set_transform( const c8 *text, vg_camera *cam, m4x3f transform );
+VG_API void font3d_setoffset( v4f offset );
+VG_API void font3d_setcolour( v4f colour );
+VG_API void font3d_draw( const c8 *text );
+VG_API f32 font3d_simple_draw( u32 variant_id, const c8 *text, vg_camera *cam, m4x3f transform );
+VG_TIER_0 f32 font3d_string_width( u32 variant_id, const c8 *text );
 
-static void font3d_setcolour( v4f colour ){
-   if( gui_font3d.shader == k_font_shader_default )
-      shader_model_font_uColour( colour );
-#if 0
-   else if( gui_font3d.shader == k_font_shader_world )
-      shader_scene_font_uColour( colour );
 #endif
-}
-
-static void font3d_draw( const char *text ){
-   u8 *u8pch = (u8*)text;
-
-   u32 max_chars = 512;
-   while( u8pch && max_chars ){
-      max_chars --;
-
-      u32 c0 = *u8pch, c1;
-      u8pch ++;
-
-      if( !c0 ) break;
-
-      ent_glyph *glyph0 = font3d_glyph( gui_font3d.font, 
-                                        gui_font3d.variant_id, c0 ),
-                *glyph1 = NULL;
-
-      /* multibyte characters */
-      if( c0 >= 1 && c0 < k_SRglyph_ascii_min ){
-         c1 = *u8pch;
-         if( !c1 ) break;
-         glyph1 = font3d_glyph( gui_font3d.font, gui_font3d.variant_id, c1 );
-      }
-
-      if( c0 == k_SRglyph_ctrl_variant ){
-         gui_font3d.variant_id = c1;
-         u8pch ++;
-         continue;
-      }
-      else if( c0 == k_SRglyph_ctrl_size ){
-         gui_font3d.offset[3] = (float)c1 * (1.0f/255.0f);
-         u8pch ++;
-         continue;
-      }
-      else if( c0 == k_SRglyph_ctrl_baseline ){
-         gui_font3d.offset[1] = 0.0f;
-         continue;
-      }
-      else if( c0 == k_SRglyph_ctrl_center ){
-         if( glyph1 ){
-            float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
-            gui_font3d.offset[1] = diff * 0.5f;
-         }
-         continue;
-      }
-      else if( c0 == k_SRglyph_ctrl_top ){
-         if( glyph1 ){
-            float diff = glyph1->size[1] - glyph1->size[1]*gui_font3d.offset[3];
-            gui_font3d.offset[1] = diff;
-         }
-         continue;
-      }
-
-      if( !glyph0 ) continue;
-
-      if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle)){
-         v4f v0;
-         v2_sub( glyph0->size, glyph1->size, v0 );
-         v2_muladds( gui_font3d.offset, v0, -0.5f, v0 );
-         v0[2] = gui_font3d.offset[2];
-         v0[3] = gui_font3d.offset[3];
-
-         font3d_setoffset( v0 );
-         mesh_drawn( glyph0->indice_start, glyph0->indice_count );
-         continue;
-      }
-      else{
-         font3d_setoffset( gui_font3d.offset );
-         mesh_drawn( glyph0->indice_start, glyph0->indice_count );
-      }
-
-      gui_font3d.offset[0] += glyph0->size[0]*gui_font3d.offset[3];
-   }
-}
-
-static f32 font3d_simple_draw( u32 variant_id, const char *text, 
-                               vg_camera *cam, m4x3f transform ){
-   if( !text ) return 0.0f;
-
-   gui_font3d.variant_id = variant_id;
-   font3d_set_transform( text, cam, transform );
-   font3d_draw( text );
-   return gui_font3d.offset[0];
-}
-
-static f32 font3d_string_width( u32 variant_id, const char *text ){
-   if( !text ) return 0.0f;
-   float width = 0.0f;
-
-   const u8 *buf = (const u8 *)text;
-   for( int i=0;; i++ ){
-      u32 c = buf[i];
-      if(!c) break;
-
-      ent_glyph *glyph = font3d_glyph( gui_font3d.font, variant_id, c );
-      if( !glyph ) continue;
-
-      width += glyph->size[0];
-   }
-
-   return width;
-}
diff --git a/src/freecam.c b/src/freecam.c
deleted file mode 100644 (file)
index c0a0f57..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "skaterift.h"
-#include "player.h"
-#include "player_render.h"
-#include "replay2.h"
-#include "input.h"
-
-void freecam_preupdate(void)
-{
-   vg_camera *cam = &_replay2.replay_freecam;
-   v3f angles;
-   v3_copy( cam->angles, angles );
-   player_look( angles, 1.0f );
-
-   f32 decay = vg_maxf(0.0f,1.0f-vg.time_frame_delta*10.0f);
-
-   v3f d;
-   v3_sub( angles, cam->angles, d );
-   v3_muladds( _replay2.freecam_w, d, 20.0f, _replay2.freecam_w );
-   v3_muls( _replay2.freecam_w, decay, _replay2.freecam_w );
-   v3_muladds( cam->angles, _replay2.freecam_w, vg.time_frame_delta, cam->angles );
-   cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
-
-   vg_camera_update_transform( cam );
-
-   v3f lookdir = { 0.0f, 0.0f, -1.0f },
-       sidedir = { 1.0f, 0.0f,  0.0f };
-   
-   m3x3_mulv( cam->transform, lookdir, lookdir );
-   m3x3_mulv( cam->transform, sidedir, sidedir );
-
-   v2f input;
-   joystick_state( k_srjoystick_steer, input );
-   v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
-   
-   v3_muladds( _replay2.freecam_v, lookdir, -input[1], _replay2.freecam_v );
-   v3_muladds( _replay2.freecam_v, sidedir, input[0], _replay2.freecam_v );
-
-   v3_muls( _replay2.freecam_v, decay, _replay2.freecam_v );
-   v3_muladds( cam->pos,_replay2.freecam_v, vg.time_frame_delta, cam->pos );
-}
diff --git a/src/freecam.h b/src/freecam.h
deleted file mode 100644 (file)
index 1f9f5e2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-void freecam_preupdate(void);
-int freecam_cmd( int argc, const char *argv[] );
index fab3e35a05b2f4779011a5b2cec77e4725ede47e..00554c79ad38ddc9a30f5e4fafa85e422daa9014 100644 (file)
@@ -775,7 +775,7 @@ struct task_writeusertime
 
 static void setlap_task( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    struct task_writeusertime *info = (void *)task->data;
    db_writeusertime( info->uid, info->steamid, info->centiseconds, info->last_second, info->only_if_faster );
 }
index 4730a5221098154a2514d73eef9849abfe3c6408..6386d96c5b7e3a990d3755dd8884084c4cb4a165 100644 (file)
@@ -1,12 +1,13 @@
-#pragma once
-
-#include "vg/vg_platform.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_async2.h"
-#include "network_msg.h"
-#include "network_common.h"
+#include "vg/vg.h"
 #include <sys/socket.h>
 
+#include "gameserver_database.h"
+#include "gameserver_db.h"
+#include "gameserver_monitor.h"
+#include "gameserver_replay.h"
+#include "gameserver_requests.h"
+
+
 #define CLIENT_KNOWLEDGE_SAME_WORLD0 0x1
 #define CLIENT_KNOWLEDGE_SAME_WORLD1 0x2
 #define CLIENT_KNOWLEDGE_FRIENDS     0x4 /* unused */
index cff7600491fb1e10cfaa4636a67d495ddec36ecb..c66ab66c57f1f40f8f71306468ce06fcaa595cf0 100644 (file)
@@ -163,7 +163,7 @@ static i32 leaderboard_time_compare( vg_skipper_context *ctx, void *comparand, u
 
 bool db_writeusertime( char uid[DB_TABLE_UID_MAX], u64 steamid, u32 centiseconds, u64 last_second, bool only_if_faster )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    u64 leaderboard_addr = db_leaderboard_address( uid ),
        table = leaderboard_addr + offsetof(struct skaterift_leaderboard,entries);
@@ -213,7 +213,7 @@ bool db_writeusertime( char uid[DB_TABLE_UID_MAX], u64 steamid, u32 centiseconds
 
 bool db_get_username( u64 steamid, char *out_username, u32 username_max )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    u64 user_address = vg_db_translate( &_gs_db.db, _gs_db.users_tree, steamid );
    if( user_address )
@@ -230,7 +230,7 @@ bool db_get_username( u64 steamid, char *out_username, u32 username_max )
 
 void _db_edit_profile( struct profile_edits *info )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    if( info->steamid == k_steamid_max )
       return;
 
@@ -268,13 +268,13 @@ void _db_edit_profile( struct profile_edits *info )
 
 static void task_edit_profile( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    _db_edit_profile( (void *)task->data );
 }
 
 void db_action_edit_profile( struct profile_edits *edits )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    vg_async_task *task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct profile_edits), 1 );
    memcpy( (void *)task->data, edits, sizeof(struct profile_edits) );
    vg_async_task_dispatch( task, task_edit_profile );
@@ -282,7 +282,7 @@ void db_action_edit_profile( struct profile_edits *edits )
 
 enum request_status gameserver_read_highscore_table( vg_msg *msg, char uid[ DB_TABLE_UID_MAX ] )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    u64 leaderboard_address = db_leaderboard_address( uid );
    u64 table_address = leaderboard_address + offsetof(struct skaterift_leaderboard,entries);
@@ -332,7 +332,7 @@ enum request_status gameserver_read_highscore_table( vg_msg *msg, char uid[ DB_T
 
 enum request_status _gs_db_get_profile( vg_msg *msg, u64 steamid )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    u16 top3_count = 0, 
        top10_count = 0;
@@ -404,7 +404,7 @@ struct task_db_dump
 
 void _gs_db_dump_task( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    struct task_db_dump *info = (void *)task->data;
 
    FILE *fp = fopen( info->output_path, "w" );
@@ -518,7 +518,7 @@ void _gs_db_dump_task( vg_async_task *task )
 
 void db_action_dump( const char *path, bool kv_mode )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    vg_async_task *task = vg_allocate_async_task( &_gs_db.tasks, sizeof(struct task_db_dump) + strlen(path)+1, 1 );
    struct task_db_dump *info = (void *)task->data;
    info->mode = kv_mode? k_dump_mode_kv: k_dump_mode_commands;
index 3a70d3b3fd4e5d0dffdf1a9d082ff9b8bbc35889..f3f64eed2b4e21d93d4725d3c61ff7a87e0fc6dc 100644 (file)
@@ -17,7 +17,7 @@ struct task_monitor_write
 
 void _monitor_write_task( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    struct task_monitor_write *info = (void *)task->data;
 
    FILE *fp = fopen( _gs_monitor.html_path, "w" );
@@ -212,7 +212,7 @@ struct task_journal
 
 void _monitor_journal_task( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    struct task_journal *info = (void *)task->data;
    fputs( info->buf, _gs_monitor.journal_fp );
 }
@@ -243,11 +243,11 @@ void _gs_monitor_journal( bool thread1, const char *message, ... )
 
    if( thread1 ) 
    {
-      THREAD_1;
+      VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    }
    else
    {
-      THREAD_0;
+      VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    }
 
    va_list args;
index 42d85bf38df3468b545d5b1f769c153f5eb3b8f0..325d54ebc4b6a863078d69b8e18c81264892461e 100644 (file)
@@ -15,7 +15,7 @@ struct serialized_replay
 
 static void task_write_replay( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    struct serialized_replay *info = (void *)task->data;
    vg_make_directory( "replaydata" );
 
@@ -177,7 +177,7 @@ void _gs_replay_request_save( u32 client_id, u64 steamid, i64 last_second, u32 c
 {
    if( async )
    {
-      THREAD_1;
+      VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
       vg_async_task *task = vg_allocate_async_task( &_gameserver.tasks, sizeof(struct request_save_info), 1 );
       struct request_save_info *info = (void *)task->data;
       info->client_id = client_id;
@@ -188,7 +188,7 @@ void _gs_replay_request_save( u32 client_id, u64 steamid, i64 last_second, u32 c
       return;
    }
 
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    struct gameserver_client *client = &_gameserver.clients[ client_id ];
    if( client->steamid != steamid )
index 72d0f6a9b843f9f34ddec93a3818936e015ed4c8..d8d2ea9908c44f9cd04176b211471e2a822c6bf1 100644 (file)
@@ -15,7 +15,7 @@ static gs_request *_get_request( u16 request_id )
 
 static void log_request_status( u16 request_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    gs_request *req = _get_request( request_id );
    const char *associated_username = "none";
@@ -59,7 +59,7 @@ void _gs_requests_init(void)
 
 static void _gs_release_request( u16 client_id, u16 request_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    VG_ASSERT( request_id );
 
    gs_request *req = _get_request( request_id );
@@ -75,7 +75,7 @@ static void _gs_release_request( u16 client_id, u16 request_id )
 
 void _gs_requests_client_disconnect( u32 client_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    gs_request_client *rc = &_gs_requests.clients[ client_id ];
    u16 request_id = rc->active_chain.tail;
    while( request_id )
@@ -93,7 +93,7 @@ static void task_request_run( vg_async_task *task );
 
 void _gs_requests_tick(void)
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    for( u32 i=0; i<NETWORK_MAX_PLAYERS; i ++ )
    {
@@ -206,7 +206,7 @@ void _gs_requests_tick(void)
 
 static void task_request_processing_complete( vg_async_task *task )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    struct task_request_run_info *info = (void *)task->data;
    gs_request *req = _get_request( info->pool_id );
 
@@ -234,7 +234,7 @@ static void task_request_processing_complete( vg_async_task *task )
 
 static void task_request_run( vg_async_task *task )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    struct task_request_run_info *info = (void *)task->data;
    gs_request *req = _get_request( info->pool_id );
@@ -412,7 +412,7 @@ E0:;
 
 void _gs_handle_request_message( u32 client_id, SteamNetworkingMessage_t *msg )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( !packet_minsize( msg, sizeof(netmsg_request)+1 ))
    {
diff --git a/src/gui.c b/src/gui.c
new file mode 100644 (file)
index 0000000..4d1f103
--- /dev/null
+++ b/src/gui.c
@@ -0,0 +1,340 @@
+struct
+{
+   struct gui_helper
+   {
+      vg_input_op *binding;
+      c8 text[32];
+      int greyed;
+   }
+   helpers[4];
+   u32 helper_count;
+
+   enum gui_helper_mode helper_mode;
+
+   struct gui_notifier
+   {
+      const char *string;
+      f32 duration, time_left; /* seconds */
+      u32 colour;
+   }
+   notifiers[ 4 ];
+
+   struct icon_call 
+   {
+      enum gui_icon icon;
+      v4f location;
+      v4f colour;
+      int colour_changed;
+   }
+   icon_draw_buffer[64];
+   u32 icon_draw_count;
+   v4f cur_icon_colour;
+   int colour_changed;
+
+   char location[64];
+   f64  location_time;
+
+   f32 factive;
+   font3d font;
+
+   v3f trick_co;
+   vg_model model_icons;
+
+   i32 icon_submeshes[ k_gui_icon_count ];
+}
+static gui = {.cur_icon_colour = {1.0f,1.0f,1.0f,1.0f},.colour_changed=1};
+
+VG_API void _gui_notify( const char *string, f32 duration, u32 colour )
+{
+   struct gui_notifier *notifier = NULL;
+   for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
+   {
+      notifier = &gui.notifiers[i];
+      if( notifier->time_left > 0.0f )
+      {
+         notifier = NULL;
+         continue;
+      }
+      else break;
+   }
+
+   if( !notifier )
+      return;
+
+   notifier->string = string;
+   notifier->duration = duration;
+   notifier->time_left = duration;
+   notifier->colour = colour;
+}
+
+VG_API void _gui_helper_reset( enum gui_helper_mode mode )
+{
+   gui.helper_count = 0;
+   gui.helper_mode = mode;
+}
+
+VG_API struct gui_helper *_gui_new_helper( vg_input_op *bind, vg_str *out_text )
+{
+   if( gui.helper_count >= VG_ARRAY_LEN(gui.helpers) )
+   {
+      vg_error( "Too many helpers\n" );
+      return NULL;
+   }
+
+   struct gui_helper *helper = &gui.helpers[ gui.helper_count ++ ];
+   helper->greyed = 0;
+   helper->binding = bind;
+   vg_strnull( out_text, helper->text, sizeof(helper->text) );
+   return helper;
+}
+
+VG_API void _gui_render_icons(void)
+{
+   vg_camera ortho;
+
+   float fl = 0.0f,
+         fr = _vg_window.w,
+         fb = 0.0f,
+         ft = _vg_window.h,
+         rl = 1.0f / (fr-fl),
+         tb = 1.0f / (ft-fb);
+
+   m4x4_zero( ortho.mtx.p );
+   ortho.mtx.p[0][0] = 2.0f * rl;
+   ortho.mtx.p[1][1] = 2.0f * tb;
+   ortho.mtx.p[3][0] = (fr + fl) * -rl;
+   ortho.mtx.p[3][1] = (ft + fb) * -tb;
+   ortho.mtx.p[3][3] = 1.0f;
+   m4x3_identity( ortho.transform );
+   vg_camera_update_view( &ortho );
+   m4x4_mul( ortho.mtx.p, ortho.mtx.v, ortho.mtx.pv );   /* HACK */
+   vg_camera_finalize( &ortho );
+
+   /* icons */
+   font3d_bind( &gui.font, k_font_shader_default, 0, &ortho );
+   vg_model_bind_mesh( &gui.model_icons );
+
+   m4x3f mmdl;
+   m4x3_identity( mmdl );
+   shader_model_font_uMdl( mmdl );
+
+   vg_tex_bind( GL_TEXTURE_2D, &gui.model_icons.textures[0].tex, 0 );
+   shader_model_font_uTexMain( 0 );
+
+   for( u32 i=0; i<gui.icon_draw_count; i++ )
+   {
+      struct icon_call *call = &gui.icon_draw_buffer[i];
+
+      if( call->colour_changed )
+         shader_model_font_uColour( call->colour );
+      shader_model_font_uOffset( call->location );
+
+      i32 index = gui.icon_submeshes[ call->icon ];
+      mdl_submesh *sm = &gui.model_icons.submeshes[ index ];
+      if( sm )
+         vg_model_draw_submesh( sm );
+   }
+
+   gui.icon_draw_count = 0;
+}
+
+VG_API void _gui_draw( ui_context *ctx )
+{
+   /* helpers 
+    * -----------------------------------------------------------------  */
+
+   gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f, vg.time_frame_delta*2.0f );
+
+   {
+      ui_px y = 80;
+      ui_px w = 360, h = 60;
+      ctx->font = &vgf_default_large;
+      for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
+      {
+         struct gui_notifier *notifier = &gui.notifiers[i];
+         notifier->time_left -= vg.time_frame_delta;
+         if( notifier->time_left > 0.0f )
+         {
+            const float k_trans = 0.2;
+            float t0 = notifier->time_left,
+                  t1 = notifier->duration - t0,
+                  t  = vg_smoothstepf( vg_minf( vg_minf( k_trans, t0 ), t1 ) / k_trans ),
+                  x  = (f32)(w+8) * t;
+            ui_rect box = { _vg_window.w - (ui_px)x, y, w, h };
+            ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, t*0.6f ) );
+            ui_outline( ctx, box, 1, ui_opacity( GUI_COL_NORM, t*0.6f ), 0 );
+            ui_text( ctx, box, notifier->string, 1, k_ui_align_middle_center, ui_colour( ctx, notifier->colour ) );
+         }
+         y += h + 8;
+      }
+   }
+
+   if( _cutscene.state >= k_cutscene_state_ready )
+   {
+      ctx->font = &vgf_default_small;
+      return;
+   }
+   
+   ctx->font = &vgf_default_title;
+   ui_px height = ctx->font->ch + 16;
+   ui_rect lwr = { 0, _vg_window.h - height, _vg_window.w, height };
+
+   ui_px x = 0;
+   for( u32 i=0; i<gui.helper_count; i++ )
+   {
+      struct gui_helper *helper = &gui.helpers[i];
+
+      char buf[128];
+      vg_str str;
+      vg_strnull( &str, buf, sizeof(buf) );
+      vg_input_string( &str, helper->binding, 1 );
+      
+      ui_rect box = { x, lwr[1], 1000, lwr[3] };
+
+      u32 fg = 0;
+      f32 opacity = 0.4f;
+      if( helper->greyed ) 
+      {
+         fg = ui_colour(ctx, k_ui_fg+2);
+         opacity = 0.1f;
+      }
+
+      struct ui_vert *bg = ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, opacity ) );
+      u32 w;
+      box[0] += 16;
+      w = ui_text( ctx, box, buf, 1, k_ui_align_middle_left, fg );
+      w *= ctx->font->sx;
+      bg[1].co[0] = x + w + 32;
+      bg[2].co[0] = x + w + 32;
+      x += w + 32;
+
+      box[0] = x;
+      bg = ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, opacity*0.7f ) );
+      box[0] += 8;
+      w = ui_text( ctx, box, helper->text, 1, k_ui_align_middle_left, fg );
+      w *= ctx->font->sx;
+      bg[1].co[0] = box[0] + w + 16;
+      bg[2].co[0] = box[0] + w + 16;
+      x += w + 32;
+   }
+
+   if( (gui.helper_mode == k_gui_helper_mode_black_bars) && gui.helper_count )
+   {
+      ui_rect box = { x, lwr[1], _vg_window.w - x, height };
+      ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
+
+      box[0] = 0;
+      box[1] = 0;
+      box[2] = _vg_window.w;
+      ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
+   }
+
+   vg_ui.frosting = gui.factive*0.015f; 
+   ui_flush( ctx, k_ui_shader_colour, NULL );
+   vg_ui.frosting = 0.0f;
+
+   f64 loc_t = (vg.time_real - gui.location_time) / 5.0;
+   if( (loc_t < 1.0) && (gui.location_time != 0.0) )
+   {
+      f32 t = 1.0f-vg_minf(1.0f,vg_minf(loc_t*20.0f,2.0f-loc_t*2.0f)),
+          o = 1.0f-t*t*(2.0f-t);
+
+      ui_rect box = { 0, (_vg_window.h*2)/3 - height/2, _vg_window.w, height };
+      ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, 0.5f ) );
+      ui_text( ctx, box, gui.location, 1, k_ui_align_middle_center, 0 );
+
+      vg_ui.colour[3] = o;
+      ui_flush( ctx, k_ui_shader_colour, NULL );
+   }
+
+   vg_ui.colour[3] = 1.0f;
+   ctx->font = &vgf_default_small;
+}
+
+static int gui_location_print_ccmd( int argc, const char *argv[] )
+{
+   if( argc > 0 )
+   {
+      char new_loc[64];
+      vg_str str;
+      vg_strnull( &str, new_loc, 64 );
+      for( int i=0; i<argc; i++ )
+      {
+         vg_strcat( &str, argv[i] );
+         vg_strcat( &str, " " );
+      }
+      if( !strcmp(gui.location,new_loc) ) return 0;
+      vg_strncpy( new_loc, gui.location, 64, k_strncpy_always_add_null );
+      gui.location_time = vg.time_real;
+   }
+   return 0;
+}
+
+static void gui_draw_icon( enum gui_icon icon, v2f co, f32 size )
+{
+   if( gui.icon_draw_count == VG_ARRAY_LEN(gui.icon_draw_buffer) )
+      return;
+
+   struct icon_call *call = &gui.icon_draw_buffer[ gui.icon_draw_count ++ ];
+
+   call->icon = icon;
+   call->location[0] = co[0] * (f32)_vg_window.w;
+   call->location[1] = co[1] * (f32)_vg_window.h;
+   call->location[2] = 0.0f;
+   call->location[3] = size * (f32)_vg_window.w;
+
+   v4_copy( gui.cur_icon_colour, call->colour );
+   call->colour_changed = gui.colour_changed;
+   gui.colour_changed = 0;
+}
+
+static void gui_icon_setcolour( v4f colour ){
+   gui.colour_changed = 1;
+   v4_copy( colour, gui.cur_icon_colour );
+}
+
+VG_API void _gui_register(void)
+{
+   vg_console_reg_cmd( "gui_location", gui_location_print_ccmd, NULL );
+}
+
+static void _gui_load_content_async( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   font3d_load( &gui.font, "models/rs_font.mdl", VG_STACK_USE_HEAP );
+
+   vg_model *mdl = &gui.model_icons;
+   vg_model_load( mdl, VG_MODEL_ENGINE_STANDARD, "models/rs_icons.mdl", VG_STACK_USE_HEAP );
+   VG_ASSERT( mdl->texture_count );
+   gui.icon_submeshes[ k_gui_icon_tick1 ] = vg_model_get_submesh_index( mdl, "icon_tick1" );
+   gui.icon_submeshes[ k_gui_icon_tick2 ] = vg_model_get_submesh_index( mdl, "icon_tick2" );
+   gui.icon_submeshes[ k_gui_icon_run ] = vg_model_get_submesh_index( mdl, "icon_run" );
+   gui.icon_submeshes[ k_gui_icon_challenge ] = vg_model_get_submesh_index( mdl, "icon_challenge" );
+   gui.icon_submeshes[ k_gui_icon_exclaim ] = vg_model_get_submesh_index( mdl, "icon_exclaim" );
+   gui.icon_submeshes[ k_gui_icon_board ] = vg_model_get_submesh_index( mdl, "icon_board" );
+   gui.icon_submeshes[ k_gui_icon_world ] = vg_model_get_submesh_index( mdl, "icon_world" );
+   gui.icon_submeshes[ k_gui_icon_rift ] = vg_model_get_submesh_index( mdl, "icon_rift" );
+   gui.icon_submeshes[ k_gui_icon_rift_run ] = vg_model_get_submesh_index( mdl, "icon_rift_run" );
+   gui.icon_submeshes[ k_gui_icon_rift_run_2d ] = vg_model_get_submesh_index( mdl, "icon_rift_run2d" );
+   gui.icon_submeshes[ k_gui_icon_friend ] = vg_model_get_submesh_index( mdl, "icon_friend" );
+   gui.icon_submeshes[ k_gui_icon_player ] = vg_model_get_submesh_index( mdl, "icon_player" );
+   gui.icon_submeshes[ k_gui_icon_player2d ] = vg_model_get_submesh_index( mdl, "icon_player2d" );
+   gui.icon_submeshes[ k_gui_icon_glider ] = vg_model_get_submesh_index( mdl, "icon_glider" );
+   gui.icon_submeshes[ k_gui_icon_spawn ] = vg_model_get_submesh_index( mdl, "icon_spawn" );
+   gui.icon_submeshes[ k_gui_icon_spawn_select ] = vg_model_get_submesh_index( mdl, "icon_spawn_select" );
+   gui.icon_submeshes[ k_gui_icon_rift_run_gold ] = vg_model_get_submesh_index( mdl,"icon_rift_run_medal_gold");
+   gui.icon_submeshes[ k_gui_icon_rift_run_silver]= vg_model_get_submesh_index( mdl,"icon_rift_run_medal_silver");
+   gui.icon_submeshes[ k_gui_icon_story2d ]= vg_model_get_submesh_index( mdl,"icon_story2d");
+   gui.icon_submeshes[ k_gui_icon_story_done2d ]= vg_model_get_submesh_index( mdl,"icon_story_done2d");
+}
+
+VG_API void _gui_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_gui_load_content_async );
+}
+
+VG_API bool _gui_helpers_active(void)
+{
+   return gui.helper_count > 0;
+}
index 51ef911a97678fdff54a85fa41aeed3e26da7d29..ec3e52df8da17aa490e6d016199c088f3153be05 100644 (file)
--- a/src/gui.h
+++ b/src/gui.h
@@ -1,17 +1,21 @@
-#pragma once
-#include "font.h"
-#include "input.h"
-#include "player.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_ui/imgui.h"
-
+#if defined( SR_IMPLEMENTATION )
+# include "src/gui.c"
+#else
 #define GUI_COL_DARK   ui_opacity( 0x00000000, 0.7f )
 #define GUI_COL_NORM   ui_opacity( 0x00101010, 0.7f )
 #define GUI_COL_ACTIVE ui_opacity( 0x00444444, 0.7f )
 #define GUI_COL_CLICK  ui_opacity( 0x00858585, 0.7f )
 #define GUI_COL_HI     ui_opacity( 0x00ffffff, 0.8f )
 
-enum gui_icon {
+enum gui_helper_mode
+{
+   k_gui_helper_mode_default,
+   k_gui_helper_mode_black_bars,
+   k_gui_helper_mode_clear
+};
+
+enum gui_icon 
+{
    k_gui_icon_tick1    = 0,
    k_gui_icon_tick2,
    k_gui_icon_run,
@@ -32,364 +36,18 @@ enum gui_icon {
    k_gui_icon_spawn_select,
    k_gui_icon_story2d,
    k_gui_icon_story_done2d,
-
    k_gui_icon_count,
 };
 
-#define GUI_HELPER_TEXT_LENGTH 32
-
-struct
-{
-   struct gui_helper
-   {
-      vg_input_op *binding;
-      char text[GUI_HELPER_TEXT_LENGTH];
-      int greyed;
-   }
-   helpers[4];
-   u32 helper_count;
-
-   enum gui_helper_mode
-   {
-      k_gui_helper_mode_default,
-      k_gui_helper_mode_black_bars,
-      k_gui_helper_mode_clear
-   }
-   helper_mode;
-
-   struct gui_notifier
-   {
-      const char *string;
-      f32 duration, time_left; /* seconds */
-      u32 colour;
-   }
-   notifiers[ 4 ];
-
-   struct icon_call 
-   {
-      enum gui_icon icon;
-      v4f location;
-      v4f colour;
-      int colour_changed;
-   }
-   icon_draw_buffer[64];
-   u32 icon_draw_count;
-   v4f cur_icon_colour;
-   int colour_changed;
-
-   char location[64];
-   f64  location_time;
-
-   f32 factive;
-   font3d font;
-
-   v3f trick_co;
-
-   mdl_context model_icons;
-   GLuint icons_texture;
-   glmesh icons_mesh;
-
-   i32 icon_submeshes[ k_gui_icon_count ];
-}
-static gui = {.cur_icon_colour = {1.0f,1.0f,1.0f,1.0f},.colour_changed=1};
-
-void gui_notify( const char *string, f32 duration, u32 colour )
-{
-         // JINGLE SOME KEYS HERE
-         // JINGLE SOME KEYS HERE
-         // JINGLE SOME KEYS HERE
-         // JINGLE SOME KEYS HERE
-         // JINGLE SOME KEYS HERE
-   struct gui_notifier *notifier = NULL;
-   for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
-   {
-      notifier = &gui.notifiers[i];
-      if( notifier->time_left > 0.0f )
-      {
-         notifier = NULL;
-         continue;
-      }
-      else break;
-   }
-
-   if( !notifier )
-      return;
-
-   notifier->string = string;
-   notifier->duration = duration;
-   notifier->time_left = duration;
-   notifier->colour = colour;
-}
-
-static void gui_helper_reset( enum gui_helper_mode mode )
-{
-   gui.helper_count = 0;
-   gui.helper_mode = mode;
-}
-
-static struct gui_helper *gui_new_helper( vg_input_op *bind, vg_str *out_text )
-{
-   if( gui.helper_count >= VG_ARRAY_LEN(gui.helpers) ){
-      vg_error( "Too many helpers\n" );
-      return NULL;
-   }
-
-   struct gui_helper *helper = &gui.helpers[ gui.helper_count ++ ];
-   helper->greyed = 0;
-   helper->binding = bind;
-   vg_strnull( out_text, helper->text, sizeof(helper->text) );
-   return helper;
-}
-
-static void gui_render_icons(void)
-{
-   vg_camera ortho;
-
-   float fl = 0.0f,
-         fr = vg.window_x,
-         fb = 0.0f,
-         ft = vg.window_y,
-         rl = 1.0f / (fr-fl),
-         tb = 1.0f / (ft-fb);
-
-   m4x4_zero( ortho.mtx.p );
-   ortho.mtx.p[0][0] = 2.0f * rl;
-   ortho.mtx.p[1][1] = 2.0f * tb;
-   ortho.mtx.p[3][0] = (fr + fl) * -rl;
-   ortho.mtx.p[3][1] = (ft + fb) * -tb;
-   ortho.mtx.p[3][3] = 1.0f;
-   m4x3_identity( ortho.transform );
-   vg_camera_update_view( &ortho );
-   m4x4_mul( ortho.mtx.p, ortho.mtx.v, ortho.mtx.pv );   /* HACK */
-   vg_camera_finalize( &ortho );
-
-   /* icons */
-   font3d_bind( &gui.font, k_font_shader_default, 0, NULL, &ortho );
-   mesh_bind( &gui.icons_mesh );
-
-   m4x3f mmdl;
-   m4x3_identity( mmdl );
-   shader_model_font_uMdl( mmdl );
-
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, gui.icons_texture );
-   shader_model_font_uTexMain( 0 );
-
-   for( u32 i=0; i<gui.icon_draw_count; i++ )
-   {
-      struct icon_call *call = &gui.icon_draw_buffer[i];
-
-      if( call->colour_changed )
-         shader_model_font_uColour( call->colour );
-      shader_model_font_uOffset( call->location );
-
-      i32 index = gui.icon_submeshes[ call->icon ];
-      mdl_submesh *sm = &gui.model_icons.submeshes[ index ];
-      if( sm )
-         mdl_draw_submesh( sm );
-   }
-
-   gui.icon_draw_count = 0;
-}
-
-static void gui_draw( ui_context *ctx )
-{
-   /* helpers 
-    * -----------------------------------------------------------------  */
-
-   gui.factive = vg_lerpf( gui.factive, gui.helper_count?1.0f:0.0f, vg.time_frame_delta*2.0f );
-
-   {
-      ui_px y = 80;
-      ui_px w = 360, h = 60;
-      ctx->font = &vgf_default_large;
-      for( u32 i=0; i<VG_ARRAY_LEN(gui.notifiers); i ++ )
-      {
-         struct gui_notifier *notifier = &gui.notifiers[i];
-         notifier->time_left -= vg.time_frame_delta;
-         if( notifier->time_left > 0.0f )
-         {
-            const float k_trans = 0.2;
-            float t0 = notifier->time_left,
-                  t1 = notifier->duration - t0,
-                  t  = vg_smoothstepf( vg_minf( vg_minf( k_trans, t0 ), t1 ) / k_trans ),
-                  x  = (f32)(w+8) * t;
-            ui_rect box = { vg.window_x - (ui_px)x, y, w, h };
-            ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, t*0.6f ) );
-            ui_outline( ctx, box, 1, ui_opacity( GUI_COL_NORM, t*0.6f ), 0 );
-            ui_text( ctx, box, notifier->string, 1, k_ui_align_middle_center, ui_colour( ctx, notifier->colour ) );
-         }
-         y += h + 8;
-      }
-   }
-
-   if( _cutscene.state >= k_cutscene_state_ready )
-   {
-      ctx->font = &vgf_default_small;
-      return;
-   }
-   
-   ctx->font = &vgf_default_title;
-   ui_px height = ctx->font->ch + 16;
-   ui_rect lwr = { 0, vg.window_y - height, vg.window_x, height };
-
-   ui_px x = 0;
-   for( u32 i=0; i<gui.helper_count; i++ )
-   {
-      struct gui_helper *helper = &gui.helpers[i];
-
-      char buf[128];
-      vg_str str;
-      vg_strnull( &str, buf, sizeof(buf) );
-      vg_input_string( &str, helper->binding, 1 );
-      
-      ui_rect box = { x, lwr[1], 1000, lwr[3] };
-
-      u32 fg = 0;
-      f32 opacity = 0.4f;
-      if( helper->greyed ) 
-      {
-         fg = ui_colour(ctx, k_ui_fg+2);
-         opacity = 0.1f;
-      }
-
-      struct ui_vert *bg = ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, opacity ) );
-      u32 w;
-      box[0] += 16;
-      w = ui_text( ctx, box, buf, 1, k_ui_align_middle_left, fg );
-      w *= ctx->font->sx;
-      bg[1].co[0] = x + w + 32;
-      bg[2].co[0] = x + w + 32;
-      x += w + 32;
-
-      box[0] = x;
-      bg = ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, opacity*0.7f ) );
-      box[0] += 8;
-      w = ui_text( ctx, box, helper->text, 1, k_ui_align_middle_left, fg );
-      w *= ctx->font->sx;
-      bg[1].co[0] = box[0] + w + 16;
-      bg[2].co[0] = box[0] + w + 16;
-      x += w + 32;
-   }
-
-   if( (gui.helper_mode == k_gui_helper_mode_black_bars) && gui.helper_count )
-   {
-      ui_rect box = { x, lwr[1], vg.window_x - x, height };
-      ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
-
-      box[0] = 0;
-      box[1] = 0;
-      box[2] = vg.window_x;
-      ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.4f ) );
-   }
-
-   vg_ui.frosting = gui.factive*0.015f; 
-   ui_flush( ctx, k_ui_shader_colour, NULL );
-   vg_ui.frosting = 0.0f;
-
-   f64 loc_t = (vg.time_real - gui.location_time) / 5.0;
-   if( (loc_t < 1.0) && (gui.location_time != 0.0) )
-   {
-      f32 t = 1.0f-vg_minf(1.0f,vg_minf(loc_t*20.0f,2.0f-loc_t*2.0f)),
-          o = 1.0f-t*t*(2.0f-t);
-
-      ui_rect box = { 0, (vg.window_y*2)/3 - height/2, vg.window_x, height };
-      ui_fill( ctx, box, ui_opacity( GUI_COL_NORM, 0.5f ) );
-      ui_text( ctx, box, gui.location, 1, k_ui_align_middle_center, 0 );
-
-      vg_ui.colour[3] = o;
-      ui_flush( ctx, k_ui_shader_colour, NULL );
-   }
-
-   vg_ui.colour[3] = 1.0f;
-   ctx->font = &vgf_default_small;
-}
-
-static int gui_location_print_ccmd( int argc, const char *argv[] )
-{
-   if( argc > 0 )
-   {
-      char new_loc[64];
-      vg_str str;
-      vg_strnull( &str, new_loc, 64 );
-      for( int i=0; i<argc; i++ )
-      {
-         vg_strcat( &str, argv[i] );
-         vg_strcat( &str, " " );
-      }
-      if( !strcmp(gui.location,new_loc) ) return 0;
-      vg_strncpy( new_loc, gui.location, 64, k_strncpy_always_add_null );
-      gui.location_time = vg.time_real;
-   }
-   return 0;
-}
-
-static void gui_draw_icon( enum gui_icon icon, v2f co, f32 size )
-{
-   if( gui.icon_draw_count == VG_ARRAY_LEN(gui.icon_draw_buffer) )
-      return;
-
-   struct icon_call *call = &gui.icon_draw_buffer[ gui.icon_draw_count ++ ];
-
-   call->icon = icon;
-   call->location[0] = co[0] * (f32)vg.window_x;
-   call->location[1] = co[1] * (f32)vg.window_y;
-   call->location[2] = 0.0f;
-   call->location[3] = size * (f32)vg.window_x;
-
-   v4_copy( gui.cur_icon_colour, call->colour );
-   call->colour_changed = gui.colour_changed;
-   gui.colour_changed = 0;
-}
-
-static void gui_icon_setcolour( v4f colour ){
-   gui.colour_changed = 1;
-   v4_copy( colour, gui.cur_icon_colour );
-}
-
-void gui_register(void)
-{
-   vg_console_reg_cmd( "gui_location", gui_location_print_ccmd, NULL );
-}
-
-static void gui_init(void)
-{
-   THREAD_1;
-   font3d_load( &gui.font, "models/rs_font.mdl", &vg.rtmem );
+VG_API void _gui_register(void);
+VG_API void _gui_init(void);
 
-   /* load icons */
-   mdl_context *mdl = &gui.model_icons;
-   mdl_open( mdl, "models/rs_icons.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
+VG_API struct gui_helper *_gui_new_helper( vg_input_op *bind, vg_str *out_text );
+VG_API void _gui_helper_reset( enum gui_helper_mode mode );
+VG_API void _gui_notify( const char *string, f32 duration, u32 colour );
 
-   gui.icon_submeshes[ k_gui_icon_tick1 ] = mdl_get_submesh_index( mdl, "icon_tick1" );
-   gui.icon_submeshes[ k_gui_icon_tick2 ] = mdl_get_submesh_index( mdl, "icon_tick2" );
-   gui.icon_submeshes[ k_gui_icon_run ] = mdl_get_submesh_index( mdl, "icon_run" );
-   gui.icon_submeshes[ k_gui_icon_challenge ] = mdl_get_submesh_index( mdl, "icon_challenge" );
-   gui.icon_submeshes[ k_gui_icon_exclaim ] = mdl_get_submesh_index( mdl, "icon_exclaim" );
-   gui.icon_submeshes[ k_gui_icon_board ] = mdl_get_submesh_index( mdl, "icon_board" );
-   gui.icon_submeshes[ k_gui_icon_world ] = mdl_get_submesh_index( mdl, "icon_world" );
-   gui.icon_submeshes[ k_gui_icon_rift ] = mdl_get_submesh_index( mdl, "icon_rift" );
-   gui.icon_submeshes[ k_gui_icon_rift_run ] = mdl_get_submesh_index( mdl, "icon_rift_run" );
-   gui.icon_submeshes[ k_gui_icon_rift_run_2d ] = mdl_get_submesh_index( mdl, "icon_rift_run2d" );
-   gui.icon_submeshes[ k_gui_icon_friend ] = mdl_get_submesh_index( mdl, "icon_friend" );
-   gui.icon_submeshes[ k_gui_icon_player ] = mdl_get_submesh_index( mdl, "icon_player" );
-   gui.icon_submeshes[ k_gui_icon_player2d ] = mdl_get_submesh_index( mdl, "icon_player2d" );
-   gui.icon_submeshes[ k_gui_icon_glider ] = mdl_get_submesh_index( mdl, "icon_glider" );
-   gui.icon_submeshes[ k_gui_icon_spawn ] = mdl_get_submesh_index( mdl, "icon_spawn" );
-   gui.icon_submeshes[ k_gui_icon_spawn_select ] = mdl_get_submesh_index( mdl, "icon_spawn_select" );
-   gui.icon_submeshes[ k_gui_icon_rift_run_gold ] = mdl_get_submesh_index( mdl,"icon_rift_run_medal_gold");
-   gui.icon_submeshes[ k_gui_icon_rift_run_silver]= mdl_get_submesh_index( mdl,"icon_rift_run_medal_silver");
-   gui.icon_submeshes[ k_gui_icon_story2d ]= mdl_get_submesh_index( mdl,"icon_story2d");
-   gui.icon_submeshes[ k_gui_icon_story_done2d ]= mdl_get_submesh_index( mdl,"icon_story_done2d");
+VG_API void _gui_draw( ui_context *ctx );
+VG_API void _gui_render_icons(void);
+VG_API bool _gui_helpers_active(void);
 
-   vg_stack_clear( &vg.scratch );
-   if( !gui.model_icons.texture_count )
-      vg_fatal_error( "No texture in menu file" );
-   mdl_texture *tex0 = &gui.model_icons.textures[ 0 ];
-   void *data = vg_stack_allocate( &vg.scratch, tex0->file.pack_size, 8, "Pack data" );
-   mdl_fread_pack_file( &gui.model_icons, &tex0->file, data );
-   vg_tex2d_load_qoi_async( data, tex0->file.pack_size, VG_TEX2D_LINEAR|VG_TEX2D_CLAMP, &gui.icons_texture );
-   mdl_async_load_glmesh( &gui.model_icons, &gui.icons_mesh, NULL );
-   mdl_close( &gui.model_icons );
-}
+#endif
diff --git a/src/input.c b/src/input.c
new file mode 100644 (file)
index 0000000..a4a61f7
--- /dev/null
@@ -0,0 +1,290 @@
+#define INPUT_BASIC( KB, JS ) \
+   (vg_input_op[]){vg_keyboard, KB, vg_joy_button, JS, vg_end}
+
+// TODO: This can probably be converted into a KV file and then compiled down into the vg_input ops.. ?
+static vg_input_op *input_button_list[] = {
+[k_srbind_jump]  = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
+[k_srbind_push]  = INPUT_BASIC( SDLK_w, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_trick0] = (vg_input_op[]){
+   vg_mouse, SDL_BUTTON_LEFT,
+   vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
+},
+[k_srbind_trick1] = (vg_input_op[]){
+   vg_mouse, SDL_BUTTON_RIGHT,
+   vg_joy_button, SDL_CONTROLLER_BUTTON_B, vg_end
+},
+[k_srbind_trick2] = (vg_input_op[]){ 
+   vg_mouse, SDL_BUTTON_LEFT, vg_mode_mul, vg_mouse, SDL_BUTTON_RIGHT, 
+   vg_mode_absmax, vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end 
+},
+[k_srbind_skate] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_use]   = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_X ),
+[k_srbind_reset] = INPUT_BASIC( SDLK_r, SDL_CONTROLLER_BUTTON_DPAD_UP ),
+[k_srbind_camera]= INPUT_BASIC( SDLK_c, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_mleft] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_mright]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_world_left] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_world_right]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
+[k_srbind_mup]   = INPUT_BASIC( SDLK_UP, SDL_CONTROLLER_BUTTON_DPAD_UP ),
+[k_srbind_mdown] = INPUT_BASIC( SDLK_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN ),
+[k_srbind_mback] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_mopen] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_START ),
+[k_srbind_mquick] = INPUT_BASIC( SDLK_q, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_mclose]= (vg_input_op[]){ vg_joy_button, SDL_CONTROLLER_BUTTON_START, vg_end },
+[k_srbind_mhub]  = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_maccept] = (vg_input_op[]){
+   vg_keyboard, SDLK_e, vg_gui_visible, 0,
+      vg_keyboard, SDLK_RETURN, vg_keyboard, SDLK_RETURN2,
+   vg_gui_visible, 1,
+   vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
+},
+[k_srbind_replay_play]    = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
+[k_srbind_replay_resume]  = (vg_input_op[]){vg_end},//INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_ ),
+[k_srbind_replay_freecam] = INPUT_BASIC( SDLK_f, SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_replay_hide_ui] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_X ),
+[k_srbind_sit]   = INPUT_BASIC( SDLK_z, SDL_CONTROLLER_BUTTON_B ),
+[k_srbind_lobby] = INPUT_BASIC( SDLK_TAB, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
+[k_srbind_chat ] = (vg_input_op[]){ vg_keyboard, SDLK_y, vg_end },
+[k_srbind_run ] = (vg_input_op[]){ vg_keyboard, SDLK_LSHIFT, 
+   vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, vg_end },
+
+[k_srbind_miniworld_resume]  = (vg_input_op[]){
+   vg_keyboard, SDLK_RETURN, vg_gui_visible, 0,
+   vg_keyboard, SDLK_RETURN2,
+   vg_gui_visible, 1,
+   vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
+},
+[k_srbind_miniworld_teleport]= INPUT_BASIC( SDLK_q, 
+                                       SDL_CONTROLLER_BUTTON_LEFTSHOULDER ),
+[k_srbind_skid] = (vg_input_op[]){ vg_keyboard, SDLK_LCTRL, vg_end },
+[k_srbind_devbutton] = (vg_input_op[]){ vg_keyboard, SDLK_3, vg_end },
+[k_srbind_max]=NULL
+};
+
+static vg_input_op *input_axis_list[] = {
+[k_sraxis_grab] = (vg_input_op[]){
+   vg_keyboard, SDLK_LSHIFT, 
+   vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, vg_end
+},
+[k_sraxis_mbrowse_h] = (vg_input_op[]){
+   vg_mode_sub, vg_keyboard, SDLK_LEFT,
+   vg_mode_add, vg_keyboard, SDLK_RIGHT,
+   vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTX,
+   vg_end
+},
+[k_sraxis_mbrowse_v] = (vg_input_op[]){
+   vg_mode_sub, vg_keyboard, SDLK_DOWN,
+   vg_mode_add, vg_keyboard, SDLK_UP,
+   vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTY,
+   vg_end
+},
+[k_sraxis_replay_h] = (vg_input_op[]){
+   vg_mode_sub, vg_keyboard, SDLK_q,
+   vg_mode_add, vg_keyboard, SDLK_e,
+   vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+   vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+   vg_end
+},
+[k_sraxis_skid] = (vg_input_op[]){
+   vg_mode_sub, vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+   vg_mode_add, vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+   vg_end
+},
+[k_sraxis_max]=NULL
+};
+
+static vg_input_op *input_joy_list[] = {
+[k_srjoystick_steer] = (vg_input_op[]){
+   vg_index, 0, vg_mode_sub, vg_keyboard, SDLK_a,
+                vg_mode_add, vg_keyboard, SDLK_d,
+   vg_index, 1, vg_mode_sub, vg_keyboard, SDLK_w,
+                vg_mode_add, vg_keyboard, SDLK_s,
+                vg_mode_absmax, vg_joy_ls,
+   vg_end
+},
+[k_srjoystick_grab] = (vg_input_op[]){
+   vg_joy_rs, vg_end
+},
+[k_srjoystick_look] = (vg_input_op[]){
+   vg_joy_rs, vg_end
+},
+[k_srjoystick_max]=NULL
+};
+
+struct 
+{
+   float axis_states[ k_sraxis_max ][2];
+   v2f joystick_states[ k_srjoystick_max ][2];
+   u8 button_states[ k_srbind_max ][2];
+
+   enum input_state 
+   {
+      k_input_state_enabled,
+      k_input_state_resume,
+      k_input_state_resuming,
+      k_input_state_pause
+   }
+   state;
+}
+static srinput;
+
+static bool input_filter_generic(void)
+{
+   if( (srinput.state != k_input_state_enabled) || vg_console.enabled || (workshop_form.page != k_workshop_form_hidden) )
+      return 1;
+   else 
+      return 0;
+}
+
+static bool buttons_filter_fixed(void)
+{
+   if( input_filter_generic() ) 
+      return 1;
+   if( vg.gameloop_stage == k_gameloop_update_fixed )
+      if( vg.fixed_iterations > 0 )
+         return 1;
+
+   return 0;
+}
+
+/* Rising edge of button */
+bool button_down( enum sr_bind button )
+{
+   if( buttons_filter_fixed() ) 
+      return 0;
+
+   if( (skaterift.activity == k_skaterift_menu) && 
+       (button < k_srbind_mopen) && 
+       (vg_input.display_input_method != k_input_method_kbm) )
+      return 0;
+
+   if(  srinput.button_states[ button ][0] && !srinput.button_states[ button ][1] )
+      return 1;
+
+   return 0;
+}
+
+/* Falling edge of button */
+bool button_up( enum sr_bind button )
+{
+   if( buttons_filter_fixed() ) 
+      return 0;
+
+   if( (skaterift.activity == k_skaterift_menu) && 
+       (button < k_srbind_mopen) && 
+       (vg_input.display_input_method != k_input_method_kbm) )
+      return 0;
+
+   if( !srinput.button_states[ button ][0] && srinput.button_states[ button ][1] )
+      return 1;
+   
+   return 0;
+}
+
+/* State of button */
+bool button_press( enum sr_bind button )
+{
+   if( input_filter_generic() )
+      return 0;
+
+   if( (skaterift.activity == k_skaterift_menu) && 
+       (button < k_srbind_mopen) && 
+       (vg_input.display_input_method != k_input_method_kbm))
+      return 0;
+
+   return srinput.button_states[ button ][0];
+}
+
+void joystick_state( enum sr_joystick joystick, v2f state )
+{
+   /* TODO: This fucking sucks */
+   if( (skaterift.activity == k_skaterift_menu) && (vg_input.display_input_method != k_input_method_kbm) &&
+       (menu.main_index != k_menu_main_map) && 
+       !((menu.main_index == k_menu_main_online) && menu.choosing_country ) )
+   {
+      v2_zero( state );
+      return;
+   }
+
+   if( input_filter_generic() )
+      v2_zero( state );
+   else
+      v2_copy( srinput.joystick_states[ joystick ][0], state );
+}
+
+f32 axis_state( enum sr_axis axis )
+{
+   if( (skaterift.activity == k_skaterift_menu) && 
+       (axis < k_sraxis_mbrowse_h ) && 
+       (vg_input.display_input_method != k_input_method_kbm))
+      return 0;
+
+   if( input_filter_generic() )
+      return 0.0f;
+
+   return srinput.axis_states[axis][0];
+}
+
+void skaterift_preupdate_inputs(void)
+{
+   if( srinput.state == k_input_state_resuming )
+      srinput.state = k_input_state_enabled;
+
+   if( srinput.state == k_input_state_resume )
+      srinput.state = k_input_state_resuming;
+
+   for( u32 i=0; i<k_srbind_max; i++ )
+   {
+      srinput.button_states[i][1] = srinput.button_states[i][0];
+      srinput.button_states[i][0] = 0;
+   }
+
+   for( u32 i=0; i<k_srjoystick_max; i++ )
+   {
+      v2_copy( srinput.joystick_states[i][0], srinput.joystick_states[i][1] );
+      v2_zero( srinput.joystick_states[i][0] );
+   }
+
+   for( u32 i=0; i<k_sraxis_max; i++ )
+   {
+      srinput.axis_states[i][1] = srinput.axis_states[i][0];
+      srinput.axis_states[i][0] = 0.0f;
+   }
+
+   for( int i=0; i<k_srbind_max; i++ )
+   {
+      vg_input_op *prog = input_button_list[i];
+      if( prog )
+         vg_exec_input_program( k_vg_input_type_button_u8, prog, &srinput.button_states[i][0] );
+   }
+
+   for( int i=0; i<k_sraxis_max; i++ )
+   {
+      vg_input_op *prog = input_axis_list[i];
+      if( prog )
+         vg_exec_input_program( k_vg_input_type_axis_f32, prog, &srinput.axis_states[i][0] );
+   }
+
+   for( int i=0; i<k_srjoystick_max; i++ )
+   {
+      vg_input_op *prog = input_joy_list[i];
+      if( prog )
+         vg_exec_input_program( k_vg_input_type_joy_v2f, prog, srinput.joystick_states[i][0] );
+   }
+
+   f32 x = srinput.axis_states[k_sraxis_mbrowse_h][0],
+       y = srinput.axis_states[k_sraxis_mbrowse_v][0],
+       sensitivity = 0.35f;
+
+   if( fabsf(x) > sensitivity )
+   {
+      if( x > 0.0f ) srinput.button_states[k_srbind_mright][0] = 1;
+      else           srinput.button_states[k_srbind_mleft][0] = 1;
+   }
+
+   if( fabsf(y) > sensitivity )
+   {
+      if( y > 0.0f ) srinput.button_states[k_srbind_mup][0] = 1;
+      else           srinput.button_states[k_srbind_mdown][0] = 1;
+   }
+}
index 4b33fac6cd3fc11f76edc7e841a5194447bd5a24..14006d27defc9c167455ba657344a02162cf8208 100644 (file)
@@ -1,9 +1,6 @@
-#pragma once
-#include "vg/vg_platform.h" 
-#include "vg/vg_console.h"
-#include "vg/vg_input.h"
-#include "vg/vg_m.h"
-#include "font.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/input.c"
+#else
 
 enum sr_bind
 {
@@ -66,289 +63,11 @@ enum sr_axis{
    k_sraxis_max
 };
 
+bool button_down( enum sr_bind button );
+bool button_up( enum sr_bind button );
+bool button_press( enum sr_bind button );
+void joystick_state( enum sr_joystick joystick, v2f state );
+f32 axis_state( enum sr_axis axis );
+void skaterift_preupdate_inputs(void);
 
-#define INPUT_BASIC( KB, JS ) \
-   (vg_input_op[]){vg_keyboard, KB, vg_joy_button, JS, vg_end}
-
-static vg_input_op *input_button_list[] = {
-[k_srbind_jump]  = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
-[k_srbind_push]  = INPUT_BASIC( SDLK_w, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_trick0] = (vg_input_op[]){
-   vg_mouse, SDL_BUTTON_LEFT,
-   vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
-},
-[k_srbind_trick1] = (vg_input_op[]){
-   vg_mouse, SDL_BUTTON_RIGHT,
-   vg_joy_button, SDL_CONTROLLER_BUTTON_B, vg_end
-},
-[k_srbind_trick2] = (vg_input_op[]){ 
-   vg_mouse, SDL_BUTTON_LEFT, vg_mode_mul, vg_mouse, SDL_BUTTON_RIGHT, 
-   vg_mode_absmax, vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end 
-},
-[k_srbind_skate] = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_use]   = INPUT_BASIC( SDLK_e, SDL_CONTROLLER_BUTTON_X ),
-[k_srbind_reset] = INPUT_BASIC( SDLK_r, SDL_CONTROLLER_BUTTON_DPAD_UP ),
-[k_srbind_camera]= INPUT_BASIC( SDLK_c, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_mleft] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_mright]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_world_left] = INPUT_BASIC( SDLK_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_world_right]= INPUT_BASIC( SDLK_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT ),
-[k_srbind_mup]   = INPUT_BASIC( SDLK_UP, SDL_CONTROLLER_BUTTON_DPAD_UP ),
-[k_srbind_mdown] = INPUT_BASIC( SDLK_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN ),
-[k_srbind_mback] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_mopen] = INPUT_BASIC( SDLK_ESCAPE, SDL_CONTROLLER_BUTTON_START ),
-[k_srbind_mquick] = INPUT_BASIC( SDLK_q, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_mclose]= (vg_input_op[]){ vg_joy_button, SDL_CONTROLLER_BUTTON_START, vg_end },
-[k_srbind_mhub]  = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_maccept] = (vg_input_op[]){
-   vg_keyboard, SDLK_e, vg_gui_visible, 0,
-      vg_keyboard, SDLK_RETURN, vg_keyboard, SDLK_RETURN2,
-   vg_gui_visible, 1,
-   vg_joy_button, SDL_CONTROLLER_BUTTON_A, vg_end
-},
-[k_srbind_replay_play]    = INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_A ),
-[k_srbind_replay_resume]  = (vg_input_op[]){vg_end},//INPUT_BASIC( SDLK_SPACE, SDL_CONTROLLER_BUTTON_ ),
-[k_srbind_replay_freecam] = INPUT_BASIC( SDLK_f, SDL_CONTROLLER_BUTTON_Y ),
-[k_srbind_replay_hide_ui] = INPUT_BASIC( SDLK_h, SDL_CONTROLLER_BUTTON_X ),
-[k_srbind_sit]   = INPUT_BASIC( SDLK_z, SDL_CONTROLLER_BUTTON_B ),
-[k_srbind_lobby] = INPUT_BASIC( SDLK_TAB, SDL_CONTROLLER_BUTTON_DPAD_LEFT ),
-[k_srbind_chat ] = (vg_input_op[]){ vg_keyboard, SDLK_y, vg_end },
-[k_srbind_run ] = (vg_input_op[]){ vg_keyboard, SDLK_LSHIFT, 
-   vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT, vg_end },
-
-[k_srbind_miniworld_resume]  = (vg_input_op[]){
-   vg_keyboard, SDLK_RETURN, vg_gui_visible, 0,
-   vg_keyboard, SDLK_RETURN2,
-   vg_gui_visible, 1,
-   vg_joy_button, SDL_CONTROLLER_BUTTON_X, vg_end
-},
-[k_srbind_miniworld_teleport]= INPUT_BASIC( SDLK_q, 
-                                       SDL_CONTROLLER_BUTTON_LEFTSHOULDER ),
-[k_srbind_skid] = (vg_input_op[]){ vg_keyboard, SDLK_LCTRL, vg_end },
-[k_srbind_devbutton] = (vg_input_op[]){ vg_keyboard, SDLK_3, vg_end },
-[k_srbind_max]=NULL
-};
-
-static vg_input_op *input_axis_list[] = {
-[k_sraxis_grab] = (vg_input_op[]){
-   vg_keyboard, SDLK_LSHIFT, 
-   vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, vg_end
-},
-[k_sraxis_mbrowse_h] = (vg_input_op[]){
-   vg_mode_sub, vg_keyboard, SDLK_LEFT,
-   vg_mode_add, vg_keyboard, SDLK_RIGHT,
-   vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTX,
-   vg_end
-},
-[k_sraxis_mbrowse_v] = (vg_input_op[]){
-   vg_mode_sub, vg_keyboard, SDLK_DOWN,
-   vg_mode_add, vg_keyboard, SDLK_UP,
-   vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_LEFTY,
-   vg_end
-},
-[k_sraxis_replay_h] = (vg_input_op[]){
-   vg_mode_sub, vg_keyboard, SDLK_q,
-   vg_mode_add, vg_keyboard, SDLK_e,
-   vg_mode_sub, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERLEFT,
-   vg_mode_add, vg_joy_axis, SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
-   vg_end
-},
-[k_sraxis_skid] = (vg_input_op[]){
-   vg_mode_sub, vg_joy_button, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
-   vg_mode_add, vg_joy_button, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
-   vg_end
-},
-[k_sraxis_max]=NULL
-};
-
-static vg_input_op *input_joy_list[] = {
-[k_srjoystick_steer] = (vg_input_op[]){
-   vg_index, 0, vg_mode_sub, vg_keyboard, SDLK_a,
-                vg_mode_add, vg_keyboard, SDLK_d,
-   vg_index, 1, vg_mode_sub, vg_keyboard, SDLK_w,
-                vg_mode_add, vg_keyboard, SDLK_s,
-                vg_mode_absmax, vg_joy_ls,
-   vg_end
-},
-[k_srjoystick_grab] = (vg_input_op[]){
-   vg_joy_rs, vg_end
-},
-[k_srjoystick_look] = (vg_input_op[]){
-   vg_joy_rs, vg_end
-},
-[k_srjoystick_max]=NULL
-};
-
-struct 
-{
-   float axis_states[ k_sraxis_max ][2];
-   v2f joystick_states[ k_srjoystick_max ][2];
-   u8 button_states[ k_srbind_max ][2];
-
-   enum input_state 
-   {
-      k_input_state_enabled,
-      k_input_state_resume,
-      k_input_state_resuming,
-      k_input_state_pause
-   }
-   state;
-}
-static srinput;
-
-static int input_filter_generic(void)
-{
-   if(    (srinput.state != k_input_state_enabled)
-       || vg_console.enabled
-       || (workshop_form.page != k_workshop_form_hidden) )
-      return 1;
-   else 
-      return 0;
-}
-
-static int buttons_filter_fixed(void)
-{
-   if( input_filter_generic() ) 
-      return 1;
-   if( vg.engine_stage == k_engine_stage_update_fixed )
-      if( vg.fixed_iterations > 0 )
-         return 1;
-
-   return 0;
-}
-
-/* Rising edge of button */
-static int button_down( enum sr_bind button )
-{
-   if( buttons_filter_fixed() ) 
-      return 0;
-
-   if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm) )
-      return 0;
-
-   if(  srinput.button_states[ button ][0] && !srinput.button_states[ button ][1] )
-      return 1;
-
-   return 0;
-}
-
-/* Falling edge of button */
-static int button_up( enum sr_bind button )
-{
-   if( buttons_filter_fixed() ) 
-      return 0;
-
-   if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm) )
-      return 0;
-
-   if( !srinput.button_states[ button ][0] && srinput.button_states[ button ][1] )
-      return 1;
-   
-   return 0;
-}
-
-/* State of button */
-static int button_press( enum sr_bind button )
-{
-   if( input_filter_generic() )
-      return 0;
-
-   if( (skaterift.activity == k_skaterift_menu) && (button < k_srbind_mopen) && (vg_input.display_input_method != k_input_method_kbm))
-      return 0;
-
-   return srinput.button_states[ button ][0];
-}
-
-static void joystick_state( enum sr_joystick joystick, v2f state )
-{
-   /* TODO: This fucking sucks */
-   if( (skaterift.activity == k_skaterift_menu) && (vg_input.display_input_method != k_input_method_kbm) &&
-       (menu.main_index != k_menu_main_map) && 
-       !((menu.main_index == k_menu_main_online) && menu.choosing_country ) )
-   {
-      v2_zero( state );
-      return;
-   }
-
-   if( input_filter_generic() )
-      v2_zero( state );
-   else
-      v2_copy( srinput.joystick_states[ joystick ][0], state );
-}
-
-static float axis_state( enum sr_axis axis )
-{
-   if( (skaterift.activity == k_skaterift_menu) && 
-       (axis < k_sraxis_mbrowse_h ) && 
-       (vg_input.display_input_method != k_input_method_kbm))
-      return 0;
-
-   if( input_filter_generic() )
-      return 0.0f;
-
-   return srinput.axis_states[axis][0];
-}
-
-static void skaterift_preupdate_inputs(void)
-{
-   if( srinput.state == k_input_state_resuming )
-      srinput.state = k_input_state_enabled;
-
-   if( srinput.state == k_input_state_resume )
-      srinput.state = k_input_state_resuming;
-
-   for( u32 i=0; i<k_srbind_max; i++ )
-   {
-      srinput.button_states[i][1] = srinput.button_states[i][0];
-      srinput.button_states[i][0] = 0;
-   }
-
-   for( u32 i=0; i<k_srjoystick_max; i++ )
-   {
-      v2_copy( srinput.joystick_states[i][0], srinput.joystick_states[i][1] );
-      v2_zero( srinput.joystick_states[i][0] );
-   }
-
-   for( u32 i=0; i<k_sraxis_max; i++ )
-   {
-      srinput.axis_states[i][1] = srinput.axis_states[i][0];
-      srinput.axis_states[i][0] = 0.0f;
-   }
-
-   for( int i=0; i<k_srbind_max; i++ )
-   {
-      vg_input_op *prog = input_button_list[i];
-      if( prog )
-         vg_exec_input_program( k_vg_input_type_button_u8, prog, &srinput.button_states[i][0] );
-   }
-
-   for( int i=0; i<k_sraxis_max; i++ )
-   {
-      vg_input_op *prog = input_axis_list[i];
-      if( prog )
-         vg_exec_input_program( k_vg_input_type_axis_f32, prog, &srinput.axis_states[i][0] );
-   }
-
-   for( int i=0; i<k_srjoystick_max; i++ )
-   {
-      vg_input_op *prog = input_joy_list[i];
-      if( prog )
-         vg_exec_input_program( k_vg_input_type_joy_v2f, prog, srinput.joystick_states[i][0] );
-   }
-
-   f32 x = srinput.axis_states[k_sraxis_mbrowse_h][0],
-       y = srinput.axis_states[k_sraxis_mbrowse_v][0],
-       sensitivity = 0.35f;
-
-   if( fabsf(x) > sensitivity )
-   {
-      if( x > 0.0f ) srinput.button_states[k_srbind_mright][0] = 1;
-      else           srinput.button_states[k_srbind_mleft][0] = 1;
-   }
-
-   if( fabsf(y) > sensitivity )
-   {
-      if( y > 0.0f ) srinput.button_states[k_srbind_mup][0] = 1;
-      else           srinput.button_states[k_srbind_mdown][0] = 1;
-   }
-}
+#endif
index f368a2edf4ae0f2c35988a0280d5346a09c99df7..6d65fd29866d0ca5604b958cf7e58a342a9ab28f 100644 (file)
@@ -1,18 +1,3 @@
-#pragma once
-#include "skaterift.h"
-#include "menu.h"
-#include "model.h"
-#include "entity.h"
-#include "input.h"
-#include "world_map.h"
-#include "audio.h"
-#include "workshop.h"
-#include "gui.h"
-#include "control_overlay.h"
-#include "network.h"
-#include "shaders/model_menu.h"
-#include "ent_atom.h"
-
 struct global_menu menu = { .skip_starter = 0, .prof_row = -1 };
 
 void menu_at_begin(void)
@@ -33,18 +18,23 @@ static int cmd_menu_impromptu( int argc, const char *argv[] )
    return 1;
 }
 
-void menu_register(void)
+VG_API void _menu_register(void)
 {
    vg_console_reg_var( "skip_starter_menu", &menu.skip_starter, k_var_dtype_i32, VG_VAR_PERSISTENT );
    vg_console_reg_cmd( "menu_impromptu", cmd_menu_impromptu, NULL );
 }
 
-void menu_init(void)
+static void _menu_load_content_async( void *_, vg_async_info *async )
+{
+   u32 flags = VG_TEX_CLAMP|VG_TEX_NOMIP|VG_TEX_NEAREST;
+   _vg_tex_load( &menu.prem_tex,             "textures/prem.qoi", flags );
+   _vg_tex_load( &menu.guide_pump_tex,       "textures/guide_pump.qoi", flags );
+   _vg_tex_load( &menu.guide_fliptrick_tex,  "textures/guide_fliptrick.qoi", flags );
+}
+
+VG_API void _menu_init(void)
 {
-   u32 flags = VG_TEX2D_CLAMP|VG_TEX2D_NOMIP|VG_TEX2D_NEAREST;
-   vg_tex2d_load_qoi_async_file( "textures/prem.qoi", flags, &menu.prem_tex );
-   vg_tex2d_load_qoi_async_file( "textures/guide_pump.qoi", flags, &menu.guide_pump_tex );
-   vg_tex2d_load_qoi_async_file( "textures/guide_fliptrick.qoi", flags, &menu.guide_fliptrick_tex );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_menu_load_content_async );
 }
 
 static void menu_update_world_filter(void)
@@ -85,11 +75,10 @@ void menu_on_world_change( addon_id addon )
    menu.world_list_selected_index[ super_id ] = index;
    menu.clicked_world_id = addon;
 
-   vg_msg msg;
-   vg_msg_init( &msg, reg->metadata, reg->metadata_len );
    const char *name = NULL;
-   if( vg_msg_seekframe( &msg, "workshop" ) )
-      name = vg_msg_getkvstr( &msg, "title" );
+   u32 workshop_block = vg_kv_find( &reg->metadata, 0, "workshop" );
+   if( workshop_block )
+      name = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, workshop_block, "title" ), NULL );
    if( !name )
       name = reg->alias.folder;
    menu.clicked_world_name = name;
@@ -98,7 +87,7 @@ void menu_on_world_change( addon_id addon )
 
 void menu_open( enum menu_page page )
 {
-   gui_helper_reset( k_gui_helper_mode_clear );
+   _gui_helper_reset( k_gui_helper_mode_clear );
    skaterift.activity = k_skaterift_menu;
 
    if( _cutscene.state != k_cutscene_state_none )
@@ -461,7 +450,7 @@ void menu_heading( ui_context *ctx, ui_rect inout_panel, const char *label, u32
    ui_text( ctx, rect, label, 1, k_ui_align_middle_center, colour? colour: ui_colour(ctx, k_ui_blue+k_ui_brighter) );
 }
 
-static u32 medal_colour( ui_context *ctx, u32 flags )
+u32 medal_colour( ui_context *ctx, u32 flags )
 {
    if( flags & k_ent_route_flag_achieve_gold ) 
       return ui_colour( ctx, k_ui_yellow );
@@ -604,11 +593,9 @@ void menu_update_world_list(void)
             flags |= MENU_WORLD_FLAG_HUB;
 
          const char *name = NULL;
-         vg_msg msg;
-         vg_msg_init( &msg, reg->metadata, reg->metadata_len );
-
-         if( vg_msg_seekframe( &msg, "workshop" ) )
-            name = vg_msg_getkvstr( &msg, "title" );
+         u32 workshop_block = vg_kv_find( &reg->metadata, 0, "workshop" );
+         if( workshop_block )
+            name = vg_kv_value( &reg->metadata, vg_kv_find( &reg->metadata, workshop_block, "title" ), NULL );
 
          if( !name )
             name = reg->alias.folder;
@@ -705,7 +692,7 @@ void menu_gui( ui_context *ctx )
       //menu_try_find_cam( 3 );
 
       ui_rect panel = { 0,0, 800, 200 },
-              screen = { 0,0, vg.window_x,vg.window_y };
+              screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect_center( screen, panel );
       ui_fill( ctx, panel, GUI_COL_DARK );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
@@ -765,14 +752,14 @@ void menu_gui( ui_context *ctx )
    }
 
 
-   if( vg.settings_open )
+   if( _vg_settings_is_open() )
    {
       if( button_down( k_srbind_mback ) )
       {
          vg_audio_lock();
          vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
          vg_audio_unlock();
-         vg_settings_close();
+         _vg_settings_close();
          srinput.state = k_input_state_resume;
       }
 
@@ -783,7 +770,7 @@ void menu_gui( ui_context *ctx )
    if( menu.page == k_menu_page_credits )
    {
       ui_rect panel = { 0,0, 600, 400 },
-              screen = { 0,0, vg.window_x,vg.window_y };
+              screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect_center( screen, panel );
       ui_fill( ctx, panel, GUI_COL_DARK );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
@@ -831,7 +818,7 @@ void menu_gui( ui_context *ctx )
    {
       i32 R = menu_nav( &menu.intro_row, mv, 3 );
       ui_rect panel = { 0,0, 600, 400 },
-              screen = { 0,0, vg.window_x,vg.window_y };
+              screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect_center( screen, panel );
       ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
@@ -845,7 +832,7 @@ void menu_gui( ui_context *ctx )
       ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
       ctx->font = &vgf_default_large;
 
-      menu_checkbox( ctx, panel, R == 0, "Show controls overlay (good for new players)", &control_overlay.enabled );
+      menu_checkbox( ctx, panel, R == 0, "Show controls overlay (good for new players)", &_control_overlay.enabled );
       menu_checkbox( ctx, panel, R == 1, "Auto connect to global server", &network_client.auto_connect );
 
       ui_rect end = { panel[0], panel[1] + panel[3] - 100, panel[2], 100 };
@@ -867,7 +854,7 @@ void menu_gui( ui_context *ctx )
    {
       i32 R = menu_nav( &menu.prem_row, mh, 1 );
       ui_rect panel = { 0,0, 600, 400+240 },
-              screen = { 0,0, vg.window_x,vg.window_y };
+              screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect_center( screen, panel );
       ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
@@ -908,7 +895,7 @@ void menu_gui( ui_context *ctx )
 /* PAGE impromptu */
    else if( menu.page == k_menu_page_impromptu_guide )
    {
-      ui_rect screen = { 0,0, vg.window_x,vg.window_y };
+      ui_rect screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect image = { 0,0, 780, 840 };
       ui_rect panel;
 
@@ -945,7 +932,7 @@ void menu_gui( ui_context *ctx )
    else if( menu.page == k_menu_page_quick )
    {
       ui_px pad = 64;
-      ui_rect panel = { 24, pad, 300, vg.window_y-(pad*2) };
+      ui_rect panel = { 24, pad, 300, _vg_window.h-(pad*2) };
       ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
       ui_rect_pad( panel, (ui_px[]){8,8} );
@@ -987,7 +974,7 @@ void menu_gui( ui_context *ctx )
                if( world_clear_event( k_world_event_challenge ) )
                {
                   _ent_challenge_clear( af_arritm( &_world.main.ent_challenge, mdl_entity_id_id( _world.active_challenge_id ) ) );
-                  gui_helper_reset( k_gui_helper_mode_clear );
+                  _gui_helper_reset( k_gui_helper_mode_clear );
                   _world.challenge_state = k_challenge_state_none;
                   _world.active_challenge_id = 0;
                   _world.challenge_target = NULL;
@@ -1050,7 +1037,7 @@ void menu_gui( ui_context *ctx )
    else if( menu.page == k_menu_page_spectate )
    {
       ui_px pad = 64;
-      ui_rect panel = { 24, pad, 300, vg.window_y-(pad*2) };
+      ui_rect panel = { 24, pad, 300, _vg_window.h-(pad*2) };
       ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
       ui_rect_pad( panel, (ui_px[]){8,8} );
@@ -1088,9 +1075,9 @@ void menu_gui( ui_context *ctx )
                localplayer.immobile = 1;
                vg_camera_copy( &localplayer.cam, &netplayers.spectate_camera );
 
-               gui_helper_reset( k_gui_helper_mode_black_bars );
+               _gui_helper_reset( k_gui_helper_mode_black_bars );
                vg_str text;
-               if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+               if( _gui_new_helper( input_button_list[k_srbind_mback], &text ))
                   vg_strcat( &text, "Stop spectating" );
             }
 
@@ -1115,7 +1102,7 @@ n1:
    {
       i32 R = menu_nav( &menu.cs_row, mh, 1 );
       ui_rect panel = { 0,0, 600, 160 },
-              screen = { 0,0, vg.window_x,vg.window_y };
+              screen = { 0,0, _vg_window.w,_vg_window.h };
       ui_rect_center( screen, panel );
       ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
       ui_outline( ctx, panel, 1, GUI_COL_NORM, 0 );
@@ -1160,7 +1147,7 @@ n1:
 
    ctx->font = &vgf_default_title;
    ui_px height = ctx->font->ch + 16;
-   ui_rect topbar = { 0, 0, vg.window_x, height };
+   ui_rect topbar = { 0, 0, _vg_window.w, height };
 
    const char *opts[] = {
       [k_menu_main_main] = "Menu",
@@ -1248,10 +1235,10 @@ n1:
       }
 
       if( draw )
-         ui_fill( ctx, (ui_rect){ x+8,0, vg.window_x-(x+8),height }, GUI_COL_NORM );
+         ui_fill( ctx, (ui_rect){ x+8,0, _vg_window.w-(x+8),height }, GUI_COL_NORM );
       else
       {
-         x = vg.window_x/2 - x/2;
+         x = _vg_window.w/2 - x/2;
          ui_fill( ctx, (ui_rect){ 0, 0, x-8, height }, GUI_COL_NORM );
       }
    }
@@ -1267,14 +1254,14 @@ n1:
       menu_backable_to_exit = 1;
       menu.bg_blur = 0;
 
-      world_map_gui( ctx, (ui_rect){ 0, height, vg.window_x, vg.window_y - height }, mh, mv, &menu_backable_to_exit );
+      world_map_gui( ctx, (ui_rect){ 0, height, _vg_window.w, _vg_window.h - height }, mh, mv, &menu_backable_to_exit );
 
       if( world_map.spawn_timer > 0.0f )
          menu_backable_to_exit = 0;
    }
    else /* menu.main_index != k_menu_main_map) */
    {
-      ui_rect list0 = { vg.window_x/2 - 512/2, height+32, 512, vg.window_y-height-64 }, list;
+      ui_rect list0 = { _vg_window.w/2 - 512/2, height+32, 512, _vg_window.h-height-64 }, list;
       rect_copy( list0, list );
       ui_rect_pad( list, (ui_px[2]){8,8} );
 
@@ -1325,9 +1312,7 @@ n1:
 
          ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
          if( menu_button( ctx, end, R == 3, 1, "Quit Game" ) )
-         {
-            vg.window_should_close = 1;
-         }
+            _vg_terminate();
       }
 /* PAGE main */
       else if( menu.main_index == k_menu_main_online )
@@ -1336,7 +1321,7 @@ n1:
          {
             menu_backable_to_exit = 0;
             bool close = _user_profile_country_picker( ctx, (ui_rect){ 8, height+32, 
-                                                                       vg.window_x-16, vg.window_y-(height+32+16) } );
+                                                                       _vg_window.w-16, _vg_window.h-(height+32+16) } );
             if( close )
                menu.choosing_country = 0;
          }
@@ -1470,7 +1455,7 @@ n1:
          ctx->font = &vgf_default_large;
          list[1] -= 8;
          menu_heading( ctx, list, "Game", 0 );
-         menu_checkbox( ctx, list, R == 0, "Show controls overlay", &control_overlay.enabled );
+         menu_checkbox( ctx, list, R == 0, "Show controls overlay", &_control_overlay.enabled );
          menu_checkbox( ctx, list, R == 1, "Auto connect to global server", &network_client.auto_connect );
 
          menu_heading( ctx, list, "Audio/Video", 0 );
@@ -1490,7 +1475,7 @@ n1:
          menu_heading( ctx, end, "Advanced", 0 );
          if( menu_button( ctx, end, R == 8, 1, "Open Engine Settings" ) )
          {
-            vg_settings_open();
+            _vg_settings_open();
          }
       }
 /* PAGE guide */
@@ -1501,7 +1486,7 @@ n1:
 
          ui_px w = 700,
                marg = list0[0]+list0[2],
-               pw = vg.window_x - marg,
+               pw = _vg_window.w - marg,
                infx = pw/2 - w/2 + marg;
          ui_rect inf = { infx, height +32, w, 800 };
 
index 242cb74cfadbde1f13f0a423f8fcf9cf7d87cd6c..e8dfbb2497fe637b8c4c57bf47d1fa805161d7bb 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/menu.c"
+#else
 
 #define MENU_STACK_SIZE 8
 #define MENU_WORLD_MAX_COUNT 10
@@ -7,10 +9,6 @@
 #define MENU_WORLD_FLAG_DONE   0x2
 #define MENU_WORLD_FLAG_LOCKED 0x4
 
-#include "vg/vg_engine.h"
-#include "entity.h"
-#include "world_map.h"
-
 enum menu_page
 {
    k_menu_page_any,
@@ -61,7 +59,7 @@ struct global_menu
    const char *web_link;   /* if set; modal */
    i32 web_choice;
 
-   GLuint prem_tex, guide_pump_tex, guide_fliptrick_tex;
+   vg_tex prem_tex, guide_pump_tex, guide_fliptrick_tex;
 
    addon_id world_list_entries[ MENU_WORLD_MAX_COUNT ];
    const char *world_list_names[ MENU_WORLD_MAX_COUNT ];
@@ -81,8 +79,9 @@ struct global_menu
 }
 extern menu;
 
-void menu_register(void);
-void menu_init(void);
+VG_API void _menu_register(void);
+VG_API void _menu_init(void);
+
 void menu_at_begin(void);
 void menu_gui( ui_context *ctx );
 void menu_open( enum menu_page page );
@@ -107,3 +106,6 @@ bool menu_checkbox( ui_context *ctx, ui_rect inout_panel, bool select, const cha
 bool menu_options( ui_context *ctx, ui_rect inout_panel, bool select, i32 *subselect_x, const char *str_label, 
                    const char *options, u32 *data, i32 mh, i32 menter );
 void menu_decor_select( ui_context *ctx, ui_rect rect );
+u32 medal_colour( ui_context *ctx, u32 flags );
+
+#endif
index dc46ed69eddd75a9f00767c3fa4f9a7121529511..9fa0482f2da66c13d00c32b8bd17eb9798ef2952 100644 (file)
-#include "metascene.h"
-#include "vg/vg_magi.h"
-
-struct _cutscene _cutscene;
-
-void metascene_load( ms_context *ms, const char *path, void *alloc )
+void metascene_load( metascene *ms, const c8 *path, vg_stack_allocator *stack )
 {
-   af_open( &ms->af, path, MS_VERSION_MIN, MS_VERSION_NR, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->infos, ms_scene_info, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->instances, ms_instance, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->overrides, ms_override, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->strips, ms_strip, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->tracks, ms_track, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->keyframes, ms_keyframe, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->cameras, ent_camera, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->audios, ent_audio, alloc );
-   AF_LOAD_ARRAY_STRUCT( &ms->af, &ms->audio_clips, ent_audio_clip, alloc );
-   af_load_array( &ms->af, &ms->curves, "ms_curves", alloc, sizeof(ms_curve_keyframe) );
-   af_close( &ms->af );
-
-   if( af_arrcount( &ms->infos ) )
-   {
-      ms_scene_info *src_inf = af_arritm( &ms->infos, 0 );
-      ms->info = *src_inf;
-   }
-   else
-      vg_fatal_error( "No scene info in metascene.\n" );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   vg_zero_mem( ms, sizeof(metascene) );
+
+   vg_stream stream;
+   VG_ASSERT( vg_file_stream_open( &stream, path, VG_STREAM_READ ) );
+
+   u32 temp_frame = _vg_start_temp_frame();
+
+   array_file_context af;
+   VG_ASSERT( af_open_stream( &af, &stream, MS_VERSION_MIN, MS_VERSION_NR, _vg_temp_stack() ) );
+
+   array_file_ptr strings;
+   af_load_array( &af, &strings, "strings", stack, 1 );
+   ms->packed_strings = strings.data;
+
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->infos, ms_scene_info, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->instances, ms_instance, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->overrides, ms_override, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->strips, ms_strip, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->tracks, ms_track, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->keyframes, ms_keyframe, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->cameras, ent_camera, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->audios, ent_audio, stack );
+   AF_LOAD_ARRAY_STRUCT( &af, &ms->audio_clips, ent_audio_clip, stack );
+   af_load_array( &af, &ms->curves, "ms_curves", stack, sizeof(ms_curve_keyframe) );
+
+   VG_ASSERT( af_arrcount( &ms->infos ) );
+   ms_scene_info *src_inf = af_arritm( &ms->infos, 0 );
+   ms->info = *src_inf;
+
+   vg_file_stream_close( &stream );
+   _vg_end_temp_frame( temp_frame );
 }
 
-struct cs_instance *_cutscene_get_first_model_instance( const char *mdl_name )
+u32 skeleton_bone_id( ms_skeleton *skele, const char *name )
 {
-   for( u32 i=0; i<_cutscene.instance_count; i ++ )
-   {
-      struct cs_instance *inst = &_cutscene.instances[i];
-      struct model_ref *mref = &_cutscene.refs[ inst->ref_id ];
-      
-      if( vg_str_eq( mdl_name, mref->name ) )
-         return inst;
-   }
+   for( u32 i=1; i<skele->bone_count; i++ )
+      if( !strcmp( skele->bones[i].name, name ))
+         return i;
 
-   return NULL;
-}
+   vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
+   vg_fatal_error( "Bone does not exist\n" );
 
-void _cutscene_unload(void)
-{
-   vg_info( "Unloading cutscene\n" );
-   vg_audio_lock();
-   vg_audio_set_flagged_pause( AUDIO_FLAG_CUTSCENE, 0 );
-   vg_audio_fadeout_flagged_audio( AUDIO_FLAG_CUTSCENE, 1.0f );
-   vg_audio_unlock();
-
-   for( u32 i=0; i<_cutscene.unique_refs; i ++ )
-      mdl_sync_std_unload( &_cutscene.refs[i].mdl );
-
-   _cutscene.unique_refs = 0;
-   _cutscene.active_camera = NULL;
-   _cutscene.strip = 0;
-   _cutscene.time = 0.0f;
-   _cutscene.active_samplers = 0;
-   _cutscene.state = k_cutscene_state_unloading;
-   _cutscene.player_binding = NULL;
-   _cutscene.subtitle = NULL;
-   _cutscene.raiser_entity = 0;
-   _cutscene.fadeout = 0;
-   _cutscene.skipped = 0;
-   _cutscene.fadeout_start = 0.0f;
+   return 0;
 }
 
-/*
- * Find associated entity data. We should also probably do this on the world
- * thingy
- */
-struct cs_asoc
+void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num )
 {
-   mdl_context *orig_data;
-   u16 entity_type,
-       entity_index;
-   ms_override *override;
-};
-
-static void _cutscene_override_asoc( u32 instance_id, u32 override_index, struct cs_asoc *out_asoc )
-{
-   struct cs_instance *instance = &_cutscene.instances[ instance_id ];
-   mdl_context *mdl = &_cutscene.refs[ instance->ref_id ].mdl;
-
-   ms_instance *oins = af_arritm( &_cutscene.meta.instances, instance_id );
-   ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + override_index );
-
-   out_asoc->orig_data = mdl;
-   out_asoc->entity_type = override->entity_type;
-   out_asoc->override = override;
-   const char *name = af_str( &_cutscene.meta.af, override->pstr_name );
-   u32 name_hash = af_str_hash( &_cutscene.meta.af, override->pstr_name );
-
-   if( out_asoc->entity_type != 28 ) 
-      goto NOT_IMPLEMENTED;
-
-   for( u32 j=0; j<mdl->armature_count; j ++ )
-   {
-      mdl_armature *armature = &mdl->armatures[ j ];
-      if( af_str_eq( &mdl->af, armature->pstr_name, name, name_hash ) )
-      {
-         out_asoc->entity_index = j;
-         return;
-      }
-   }
-
-NOT_IMPLEMENTED:
-
-   vg_fatal_error( "The data association was not found.\n"
-                   "  Entity Type: %u\n"
-                   "  Entity name: %s\n", override->entity_type, name );
+   for( int i=0; i<num; i++ )
+      kfb[i] = kfa[i];
 }
 
-static void _cutscene_get_strip_asoc( ms_strip *strip, struct cs_asoc *out_asoc )
+
+/* apply a rotation from the perspective of root */
+void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q )
 {
-   VG_ASSERT( strip->mode & k_ms_strip_mode_animation );
-   if( strip->strip.instance_id == 0xffffffff )
-   {
-      out_asoc->orig_data = NULL;// &_cutscene.meta;
-      out_asoc->entity_type = mdl_entity_id_type( strip->strip.object_id );
-      out_asoc->entity_index = mdl_entity_id_id( strip->strip.object_id );
-      out_asoc->override = NULL;
-   }
-   else
-      _cutscene_override_asoc( strip->strip.instance_id, strip->strip.object_id, out_asoc );
+   v3f v0, co;
+   v3_add( kf->co, offset, co );
+   v3_sub( co, origin, v0 );
+   q_mulv( q, v0, v0 );
+   v3_add( v0, origin, co );
+   v3_sub( co, offset, kf->co );
+
+   q_mul( q, kf->q, kf->q );
+   q_normalize( kf->q );
 }
 
-static void sync_cutscene_loaded( void *userdata )
+void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd )
 {
-   THREAD_0;
-
-   vg_info( "Cutscene loaded\n" );
-   _cutscene.state = k_cutscene_state_ready;
+   v3_lerp( kfa->co, kfb->co, t, kfd->co );
+   q_nlerp( kfa->q,  kfb->q,  t, kfd->q );
+   v3_lerp( kfa->s,  kfb->s,  t, kfd->s );
 }
 
-struct cutscene_load_info 
-{
-   u32 nothing;
-   char path[];
-};
-static void cutscene_load_thread( vg_async_task *task )
+/*
+ * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
+ */
+void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count )
 {
-   struct cutscene_load_info *info = (void *)task->data;
-   vg_info( "Loading cutscene: %s\n", info->path );
-
-   vg_stack_init( &_cutscene.stack, NULL, VG_MB(20), "Cutscene Stack" );
-   metascene_load( &_cutscene.meta, info->path, &_cutscene.stack );
-
-   _cutscene.instance_count = af_arrcount( &_cutscene.meta.instances );
-   _cutscene.instances = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_instance) * _cutscene.instance_count, 
-                                             8, "Instances" );
-
-   _cutscene.refs = vg_stack_allocate( &_cutscene.stack, 0, 8, "References" );
-   _cutscene.unique_refs = 0;
-   for( u32 i=0; i < _cutscene.instance_count; i ++ )
+   if( t <= 0.0001f )
    {
-      ms_instance *instance = af_arritm( &_cutscene.meta.instances, i );
-      const char *name = af_str( &_cutscene.meta.af, instance->pstr_name );
-      u32 name_hash = af_str_hash( &_cutscene.meta.af, instance->pstr_name );
-
-      struct model_ref *ref = NULL;
-      u32 ref_id = 0;
-
-      for( u32 j=0; j<_cutscene.unique_refs; j ++ )
-      {
-         struct model_ref *ref_j = &_cutscene.refs[ j ];
-
-         if( af_str_eq( &_cutscene.meta.af, instance->pstr_name, ref_j->name, ref_j->name_hash ) )
-         {
-            ref = ref_j;
-            ref_id = j;
-            break;
-         }
-      }
-
-      if( !ref )
-      {
-         _cutscene.refs = vg_stack_extend_last( &_cutscene.stack, sizeof(struct model_ref) );
-         ref_id = _cutscene.unique_refs;
-         ref = &_cutscene.refs[ ref_id ];
-         ref->name = name;
-         ref->name_hash = name_hash;
-         ref->reference_count = 0;
-         vg_info( "Indexed reference '%s'\n", name );
-         _cutscene.unique_refs ++;
-      }
-
-      ref->reference_count ++;
-      _cutscene.instances[ i ].ref_id = ref_id;
-      _cutscene.instances[ i ].skinning_data = NULL;
-      _cutscene.instances[ i ].disable_render = 0;
-   }
-
-   /* load model data */
-   for( u32 i=0; i<_cutscene.unique_refs; i ++ )
-   {
-      struct model_ref *ref = &_cutscene.refs[ i ];
-      char mdl_path_buf[ 512 ];
-      vg_str mdl_path;
-      vg_strnull( &mdl_path, mdl_path_buf, sizeof(mdl_path_buf) );
-      vg_strcat( &mdl_path, ref->name );
-      vg_strcat( &mdl_path, ".mdl" );
-
-      vg_info( "Loading instance model: %s\n", mdl_path.buffer );
-      mdl_open( &ref->mdl, mdl_path.buffer, &_cutscene.stack );
-      mdl_load_metadata_block( &ref->mdl, &_cutscene.stack );
-      mdl_async_full_load_std( &ref->mdl, NULL );
-      mdl_close( &ref->mdl );
-
-      u32 skeleton_count = ref->mdl.armature_count;
-      if( skeleton_count )
-      {
-         ref->skeletons = vg_stack_allocate( &_cutscene.stack, sizeof(struct cs_skeleton) * skeleton_count, 8, "Skeletons" );
-         ref->total_skinning_bones = 0;
-         for( u32 j=0; j<skeleton_count; j ++ )
-         {
-            struct cs_skeleton *skele = &ref->skeletons[ j ];
-            skeleton_setup( &skele->sk, &ref->mdl, j, &_cutscene.stack );
-            skele->skinning_offset = ref->total_skinning_bones;
-            ref->total_skinning_bones += skele->sk.bone_count;
-         }
-      }
-      else 
-      {
-         ref->skeletons = NULL;
-         ref->total_skinning_bones = 0;
-      }
-   }
-
-   /* allocate skinning memory per-instance */
-   for( u32 i=0; i<_cutscene.instance_count; i ++ )
-   {
-      struct cs_instance *ins = &_cutscene.instances[ i ];
-      struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
-
-      ins->skinning_data = vg_stack_allocate( &_cutscene.stack, sizeof(m4x3f) * ref->total_skinning_bones,
-                                              8, "Skinning Data" );
-      for( u32 j=0; j<ref->total_skinning_bones; j ++ )
-         m4x3_identity( ins->skinning_data[ j ] );
-
-      /* load overrides */
-      ms_instance *oins = af_arritm( &_cutscene.meta.instances, i );
-      for( u32 j=0; j<oins->override_count; j ++ )
-      {
-         ms_override *override = af_arritm( &_cutscene.meta.overrides, oins->override_start + j );
-
-         struct cs_asoc asoc;
-         _cutscene_override_asoc( i, j, &asoc );
-
-         VG_ASSERT( asoc.entity_type == 28 );
-
-         struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
-         m4x3f mmdl;
-         mdl_transform_m4x3( &override->transform, mmdl );
-
-         for( u32 l=0; l<skele->sk.bone_count; l ++ )
-            m4x3_copy( mmdl, ins->skinning_data[skele->skinning_offset+l] );
-      }
+      keyframe_copy_pose( kfa, kfd, count );
+      return;
    }
-
-   /* audio packs */
-   for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
+   else if( t >= 0.9999f )
    {
-      ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
-
-      for( u32 k=0; k<audio->clip_count; k++ )
-      {
-         ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start+k );
-
-         if( clip->_.file.pack_size )
-            vg_error( "Currently not support packed audio in metascene..." );
-         else
-         {
-            clip->_.clip.path = af_str( &_cutscene.meta.af, clip->_.file.pstr_path );
-            clip->_.clip.flags = audio->flags;
-            clip->_.clip.any_data = NULL;
-            clip->_.clip.size = 0;
-         }
-
-         audio_clip_load( &clip->_.clip, &_cutscene.stack );
-      }
+      keyframe_copy_pose( kfb, kfd, count );
+      return;
    }
 
-   vg_async_call( &vg.main_tasks, sync_cutscene_loaded, NULL );
+   for( int i=0; i<count; i++ )
+      keyframe_lerp( kfa+i, kfb+i, t, kfd+i );
 }
 
-bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity )
+void skeleton_lerp_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd )
 {
-   if( _cutscene.state != k_cutscene_state_none )
-   {
-      vg_error( "Tried to play cutscene '%s' while already playing one.\n", path );
-      return 0;
-   }
-
-   _cutscene.raiser_entity = raiser_entity;
-
-   for( u32 i=0; i<k_npc_max; i ++ )
-      _ent_npc_set_in_cutscene( i, 0 );
-
-   _cutscene.state = k_cutscene_state_loading;
-   _cutscene.time = 0.0f;
-   _cutscene.strip = 0;
-   _cutscene.active_samplers = 0;
-   _cutscene.freeze_player = freeze_player;
+   keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
+}
 
-   u32 len = strlen( path ) +1;
-   vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct cutscene_load_info) + len, 1 );
-   struct cutscene_load_info *info = (void *)task->data;
-   strcpy( info->path, path );
-   vg_async_task_dispatch( task, cutscene_load_thread );
-   return 1;
+void skeleton_copy_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd )
+{
+   keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
 }
 
 /*
- * Currently draws everything as skinned meshes.
+ * Sample animation between 2 closest frames using time value. Output is a
+ * keyframe buffer that is allocated with an appropriate size
+ *
+ * Time is in SECONDS
  */
-void cutscene_render_instance( struct cs_instance *ins, world_instance *world, vg_camera *cam )
+void skeleton_sample_anim( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output )
 {
-   if( ins->disable_render )
-      return;
+   ms_strip *strip = anim->strip;
+   f32 animtime  = fmodf( time*anim->framerate, (f32)strip->strip.length ),
+       animframe = floorf( animtime ),
+       t = animtime - animframe;
 
-   struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
-   mdl_context *mdl = &ref->mdl;
-   mesh_bind( &mdl->mesh );
+   u32 frame = (u32)animframe % strip->strip.length,
+       next  = (frame+1) % strip->strip.length;
 
-   shader_model_character_view_use();
-   shader_model_character_view_uCamera( cam->transform[3] );
-   shader_model_character_view_uPv( cam->mtx.pv );
-   shader_model_character_view_uDepthMode( 0 );
-   shader_model_character_view_uShadeless( 0 );
-   shader_model_character_view_uUvOffset( (v2f){0,0} );
+   ms_keyframe *base  = anim->keyframes_base + strip->strip.count*frame,
+               *nbase = anim->keyframes_base + strip->strip.count*next;
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view );
+   skeleton_lerp_pose( skele, base, nbase, t, output );
+}
 
-   glActiveTexture( GL_TEXTURE0 );
-   shader_model_character_view_uTexMain( 0 );
+/* time is in SECONDS */
+int skeleton_sample_anim_clamped( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output )
+{
+   ms_strip *strip = anim->strip;
+   f32 end = (strip->strip.length-1)/anim->framerate;
+   skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
 
-   u32 armature_id = 0x00;
-   u32 material_id = 0x00;
-   bool using_additive = 0;
+   if( time > end ) return 0;
+   else             return 1;
+}
 
-   for( u32 i=0; i<mdl->mesh_count; i ++ )
-   {
-      mdl_mesh *mesh = &mdl->meshes[ i ];
-      VG_ASSERT( mesh->armature_id );
+static int should_apply_bone( ms_skeleton *skele, u32 id, anim_apply type )
+{
+   ms_skeleton_bone *sb = &skele->bones[ id ],
+                        *sp = &skele->bones[ sb->parent ];
 
-      if( mesh->armature_id != armature_id )
+   if( type == k_anim_apply_defer_ik )
+   {
+      if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer )
       {
-         armature_id = mesh->armature_id;
-         u32 sk_index = mdl_entity_id_id( armature_id );
-
-         struct cs_skeleton *skele = &ref->skeletons[ sk_index ];
-         m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset;
-         glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms, skele->sk.bone_count, 0,
-                               (const GLfloat *)skinning_data );
+         sb->defer = 1;
+         return 0;
       }
-
-      for( u32 j=0; j<mesh->submesh_count; j ++ )
+      else
       {
-         mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
-         VG_ASSERT( sm->material_id );
-
-         if( sm->material_id != material_id )
-         {
-            mdl_material *m = &mdl->materials[ sm->material_id-1 ];
-            VG_ASSERT( m->shader == k_shader_standard );
-
-            struct shader_props_standard *props = m->props.compiled;
-            VG_ASSERT( props->tex_diffuse );
-
-            mdl_texture *tex = &mdl->textures[ props->tex_diffuse-1 ];
-            glBindTexture( GL_TEXTURE_2D, tex->glname );
-
-            if( props->render_flags & k_material_render_additive )
-            {
-               using_additive = 1;
-               glDepthMask(GL_FALSE);
-               glEnable(GL_BLEND);
-               glBlendFunc(GL_ONE, GL_ONE);
-               glBlendEquation(GL_FUNC_ADD);
-               glDisable( GL_CULL_FACE );
-               shader_model_character_view_uShadeless( 1 );
-            }
-            else
-            {
-               if( using_additive )
-               {
-                  using_additive = 0;
-                  glDepthMask(GL_TRUE);
-                  glDisable(GL_BLEND);
-                  glEnable( GL_CULL_FACE );
-                  shader_model_character_view_uShadeless( 0 );
-               }
-            }
-         }
-
-         mdl_draw_submesh( sm );
+         sb->defer = 0;
+         return 1;
       }
    }
-
-   if( using_additive )
-   {
-      shader_model_character_view_uShadeless( 0 );
-      glDepthMask(GL_TRUE);
-      glDisable(GL_BLEND);
-   }
-}
-
-#define CS_LOCATION 0
-#define CS_ANGLES 4
-#define CS_FOV 8
-
-struct cs_link_info
-{
-   f32 *target;
-   u32 semantic_type;
-};
-
-static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath, struct cs_link_info *out_link )
-{
-   if( asoc->entity_type != k_ent_camera )
+   else if( type == k_anim_apply_deffered_only )
    {
-      vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
-      VG_ASSERT( 0 );
-   }
-   ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc->entity_index );
-
-   struct
-   {
-      const char *prefix;
-      f32 *arr;
-      u32 semantic;
-   }
-   reference[] =
-   {
-      { "location:", cam->co, CS_LOCATION },
-      { "rotation_euler:", cam->r, CS_ANGLES },
-      { "lens:", &cam->fov, CS_FOV }
-   };
-
-   for( u32 i=0; i<VG_ARRAY_LEN(reference); i ++ )
-   {
-      u32 len = strlen( reference[i].prefix );
-      if( !strncmp( reference[i].prefix, datapath, len ) )
-      {
-         i32 offset = atoi( datapath + len );
-         out_link->target = reference[i].arr + offset;
-         out_link->semantic_type = reference[i].semantic + offset;
-
-         vg_info( "Linked %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+      if( sb->defer )
          return 1;
-      }
+      else
+         return 0;
    }
 
-   vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
-   return 0;
-}
-
-ent_camera *_cutscene_active_camera(void)
-{
-   return _cutscene.active_camera;
+   return 1;
 }
 
-void cutscene_update( f32 delta )
+/*
+ * Apply block of keyframes to skeletons final pose
+ */
+void skeleton_apply_pose( ms_skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx )
 {
-   if( _cutscene.state == k_cutscene_state_unloading )
+   if( passtype == k_anim_apply_absolute )
    {
-      // NOTE: This somestimes still fails!
-      if( !vg_audio_flagged_stopped( AUDIO_FLAG_CUTSCENE ) )
+      for( u32 i=1; i<skele->bone_count; i++ )
       {
-         static u32 ticker = 0;
-         ticker ++;
-         if( ticker > 50 )
-         {
-            vg_low( "waiting for audio to stop...\n" );
-            ticker = 0;
-         }
-         return;
-      }
-
-      vg_stack_free( &_cutscene.stack );
-      _cutscene.state = k_cutscene_state_none;
-      _cutscene.marker_this_frame = NULL;
-      _cutscene.subtitle = NULL;
-      _cutscene.raiser_entity = 0;
-      vg_info( "Finished unloading cutscene\n" );
-      return;
-   }
-
-   if( _cutscene.state == k_cutscene_state_ready )
-   {
-      _cutscene.player_binding = _cutscene_get_first_model_instance( "models/ch_none" );
-      if( _cutscene.player_binding )
-         _cutscene.player_binding->disable_render = 1;
+         ms_keyframe *kf = &pose[i-1];
 
-      /* start playing */
-      if( _cutscene.freeze_player )
-         localplayer.immobile = 1;
+         v3f *posemtx = final_mtx[i];
 
-      vg_audio_lock();
-      for( u32 j=0; j<af_arrcount( &_cutscene.meta.audios ); j++ )
-      {
-         ent_audio *audio = af_arritm( &_cutscene.meta.audios, j );
-         ent_audio_clip *clip = af_arritm( &_cutscene.meta.audio_clips, audio->clip_start );
-
-         if( audio->flags & AUDIO_FLAG_AUTO_START )
-         {
-            const u16 group = 0xfff1;
-            const u32 flags = AUDIO_FLAG_CUTSCENE;
-
-            if( audio->flags & AUDIO_FLAG_SPACIAL_3D )
-               vg_audio_oneshot_3d( &clip->_.clip, audio->transform.co, audio->transform.s[0], audio->volume, group,flags);
-            else
-               vg_audio_oneshot( &clip->_.clip, 1.0f, 0.0f, group, flags );
-         }
+         q_m3x3( kf->q, posemtx );
+         m3x3_scale( posemtx, kf->s );
+         v3_copy( kf->co, posemtx[3] );
       }
-      vg_audio_unlock();
-
-      _cutscene.state = k_cutscene_state_playing;
-      _world_raise_event( _cutscene.raiser_entity, "start" );
+      return;
    }
 
-   if( _cutscene.state != k_cutscene_state_playing )
-      return; 
+   m4x3_identity( final_mtx[0] );
+   skele->bones[0].defer = 0;
+   skele->bones[0].flags &= ~k_bone_flag_ik;
 
-   _cutscene.marker_this_frame = NULL;
-   _cutscene.time += delta;
-   i32 frame = _cutscene.time * _cutscene.meta.info.framerate;
-
-   /* clear out finished samplers */
-   bool move = 0;
-   u32 j = 0;
-   for( u32 i=0; i<_cutscene.active_samplers; i ++ )
+   for( u32 i=1; i<skele->bone_count; i++ )
    {
-      struct cs_sampler *si = &_cutscene.samplers[i];
-
-      if( frame > (si->strip->offset + (i32)si->strip->strip.length) )
-         move = 1;
-      else
-      {
-         if( move )
-         {
-            struct cs_sampler *sj = &_cutscene.samplers[j];
-            *sj = *si;
-         }
-
-         j ++;
-      }
-   }
-   _cutscene.active_samplers = j;
+      ms_skeleton_bone *sb = &skele->bones[i],
+                           *sp = &skele->bones[sb->parent];
+      if( !should_apply_bone( skele, i, passtype ) )
+         continue;
 
-   /* add new samplers as we get to them */
-   for( u32 i=_cutscene.strip; i<af_arrcount(&_cutscene.meta.strips); i ++ )
-   {
-      ms_strip *strip = af_arritm(&_cutscene.meta.strips, i);
-
-      if( frame < strip->offset )
-         break;
-
-      if( strip->mode & k_ms_strip_mode_animation )
-      {
-         if( frame > strip->offset + (i32)strip->strip.length )
-         {
-            vg_warn( "Skipping?\n" );
-            _cutscene.strip ++;
-            continue;
-         }
-
-         if( _cutscene.skipped == 2 )
-         {
-            _cutscene.strip ++;
-            continue;
-         }
-
-         if( strip->strip.instance_id == 0xffffffff )
-         {
-            const char *strip_name = af_str( &_cutscene.meta.af, strip->strip.pstr_name );
-            vg_info( "+ Strip: '%s' entity: %u\n", strip_name, strip->strip.object_id );
-
-            /* internal link */
-            struct cs_asoc asoc;
-            _cutscene_get_strip_asoc( strip, &asoc );
-
-            if( strip->mode == k_ms_strip_mode_curves )
-            {
-               for( u32 j=0; j<strip->strip.count; j ++ )
-               {
-                  ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->strip.start + j );
-                  const char *datapath = af_str( &_cutscene.meta.af, track->pstr_datapath );
-                  
-                  struct cs_link_info link;
-                  if( !link_internal_datapath( &asoc, datapath, &link ) )
-                     continue;
-                  
-                  VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
-                  struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
-                  samp->strip = strip;
-                  samp->curves.track = track;
-
-                  samp->curves.target = link.target;
-                  samp->curves.semantic = link.semantic_type;
-                  samp->curves.keyframe = 0;
-                  samp->override = asoc.override;
-                  VG_ASSERT( samp->curves.target );
-               }
-            }
-            else VG_ASSERT(0);
-         }
-         else
-         {
-            /* external link */
-            struct cs_instance *ins = &_cutscene.instances[ strip->strip.instance_id ];
-            struct cs_asoc asoc;
-            _cutscene_get_strip_asoc( strip, &asoc );
-            VG_ASSERT( asoc.entity_type == 28 );
-
-            if( strip->mode == k_ms_strip_mode_keyframes )
-            {
-               VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
-
-               struct cs_sampler *samp = &_cutscene.samplers[ _cutscene.active_samplers ++ ];
-               struct model_ref *ref = &_cutscene.refs[ ins->ref_id ];
-               struct cs_skeleton *skele = &ref->skeletons[ asoc.entity_index ];
-
-               samp->strip = strip;
-               samp->skeleton.skinning_data = &ins->skinning_data[ skele->skinning_offset ];
-               samp->skeleton.ref_sk = &skele->sk;
-               samp->override = asoc.override;
-            }
-            else
-            {
-               VG_ASSERT(0);
-            }
-         }
-      }
-      else
-      {
-         if( strip->mode == k_ms_strip_mode_camera )
-         {
-            u32 type = mdl_entity_id_type( strip->camera.entity_id ),
-                index = mdl_entity_id_id( strip->camera.entity_id );
-            VG_ASSERT( type == k_ent_camera );
-            ent_camera *cam = af_arritm( &_cutscene.meta.cameras, index );
-            _cutscene.active_camera = cam;
-         }
-
-         if( strip->mode == k_ms_strip_mode_fadeout )
-         {
-            _cutscene.fadeout = 1;
-            _cutscene.fadeout_start = _cutscene.time;
-         }
-
-         if( strip->mode == k_ms_strip_mode_subtitle )
-         {
-            // FIXME: COLOURS
-            _cutscene.subtitle = af_str( &_cutscene.meta.af, strip->subtitle.pstr_en );
-         }
-
-         if( strip->mode == k_ms_strip_mode_event )
-         {
-            const char *str = af_str( &_cutscene.meta.af, strip->event.pstr_string );
-            vg_info( "cutscene event: %s\n", str );
-            _world_raise_event( _cutscene.raiser_entity, str );
-         }
-      }
+      sb->defer = 0;
 
-      _cutscene.strip ++;
-   }
+      /* process pose */
+      m4x3f posemtx;
 
-   /* sample da samplers */
-   for( u32 i=0; i<_cutscene.active_samplers && (_cutscene.skipped != 2); i ++ )
-   {
-      struct cs_sampler *samp = &_cutscene.samplers[ i ];
+      v3f temp_delta;
+      v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
 
-      if( samp->strip->mode == k_ms_strip_mode_keyframes )
-      {
-         struct skeleton_anim temp_anim = 
-         {
-            .strip = samp->strip,
-            .framerate = _cutscene.meta.info.framerate,
-            .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->strip.start )
-         };
-
-         f32 t  = _cutscene.time;
-             t -= (f32)samp->strip->offset / _cutscene.meta.info.framerate;
-
-         struct skeleton *ref_sk = samp->skeleton.ref_sk;
-         m4x3f *final_mtx = samp->skeleton.skinning_data;
-
-         ms_keyframe pose[32];
-         skeleton_sample_anim_clamped( ref_sk, &temp_anim, t, pose );
-
-         skeleton_apply_pose( ref_sk, pose, k_anim_apply_defer_ik, final_mtx );
-         skeleton_apply_ik_pass( ref_sk, final_mtx );
-         skeleton_apply_pose( ref_sk, pose, k_anim_apply_deffered_only, final_mtx );
-         skeleton_apply_inverses( ref_sk, final_mtx );
-
-         if( samp->override )
-         {
-            m4x3f mmdl;
-            mdl_transform_m4x3( &samp->override->transform, mmdl );
-            skeleton_apply_transform( ref_sk, mmdl, final_mtx );
-         }
-
-         skeleton_debug( ref_sk, final_mtx );
-      }
-      else
-      {
-         f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
-             t = (f32)(scene_t - samp->strip->offset) + samp->strip->strip.timing_offset;
-
-         ms_curve_keyframe *kl = af_arritm( &_cutscene.meta.curves, 
-                  samp->curves.track->keyframe_start + samp->curves.keyframe ),
-                           *kr = NULL;
-
-         if( t > kl->co[0] )
-         {
-            if( samp->curves.track->keyframe_count > 1 )
-            {
-               for( u32 j=samp->curves.keyframe+1; j<samp->curves.track->keyframe_count; j ++ )
-               {
-                  kr = af_arritm( &_cutscene.meta.curves, samp->curves.track->keyframe_start + j );
-                  if( kr->co[0] <= t )
-                  {
-                     kl = kr;
-                     kr = NULL;
-                     samp->curves.keyframe = j;
-                  }
-                  else break;
-               }
-            }
-         }
-
-         if( kl && kr )
-            *samp->curves.target = explicit_bezier( kl->co, kl->r, kr->l, kr->co, t );
-         else
-            *samp->curves.target = kl->co[1];
-
-         if( samp->curves.semantic == CS_FOV )
-         {
-            f32 mm  = *samp->curves.target,
-                fov = 2.0f * 57.2957795f * atanf( (36.0f*0.5f) / mm );
-            *samp->curves.target = fov;
-         }
-      }
-   }
+      /* pose matrix */
+      ms_keyframe *kf = &pose[i-1];
+      q_m3x3( kf->q, posemtx );
+      m3x3_scale( posemtx, kf->s );
+      v3_copy( kf->co, posemtx[3] );
+      v3_add( temp_delta, posemtx[3], posemtx[3] );
 
-   for( u32 i=0; i<af_arrcount( &_cutscene.meta.cameras ); i ++ )
-   {
-      ent_camera *cam = af_arritm( &_cutscene.meta.cameras, i );
-      vg_line_cross( cam->co, VG__RED, 0.2f );
+      /* final matrix */
+      m4x3_mul( final_mtx[ sb->parent ], posemtx, final_mtx[i] );
    }
+}
 
-   f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
-       end_t   = _cutscene.meta.info.end_frame;
-
-   if( scene_t >= end_t )
+/* 
+ * Take the final matrices and decompose it into an absolute positioned anim
+ */
+void skeleton_decompose_mtx_absolute( ms_skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx )
+{
+   for( u32 i=1; i<skele->bone_count; i++ )
    {
-      if( _cutscene.strip != af_arrcount(&_cutscene.meta.strips) )
-      {
-         _cutscene.time = 9999999.9f;
-         _cutscene.skipped = 2; /* signal we can ignore animation strips, just want events for correctness */
-         return;
-      }
-      _world_raise_event( _cutscene.raiser_entity, "end" );
-
-      if( _cutscene.freeze_player )
-         localplayer.immobile = 0;
-
-      _cutscene_unload();
+      ms_skeleton_bone *sb = &skele->bones[i];
+      ms_keyframe *kf = &anim[i-1];
+      m4x3_decompose( final_mtx[i], kf->co, kf->q, kf->s );
    }
 }
 
-void cutscene_render_fadeout(void)
+/* 
+ * creates the reference inverse matrix for an IK bone, as it has an initial 
+ * intrisic rotation based on the direction that the IK is setup..
+ */
+void skeleton_inverse_for_ik( ms_skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse )
 {
-   bool render = 0;
-   f32 render_alpha = 0.0f;
+   v3_copy( ivaxis, inverse[0] );
+   v3_copy( skele->bones[id].end, inverse[1] );
+   v3_normalize( inverse[1] );
+   v3_cross( inverse[0], inverse[1], inverse[2] );
+   m3x3_transpose( inverse, inverse );
+}
 
-   if( _cutscene.state >= k_cutscene_state_ready )
-   {
-      if( _cutscene.fadeout )
-      {
-         f32 l = ((f32)_cutscene.meta.info.end_frame/(f32)_cutscene.meta.info.framerate) - _cutscene.fadeout_start,
-             t = (_cutscene.time - _cutscene.fadeout_start) / l;
-         render = 1;
-         render_alpha = t;
-         _cutscene.fadeout_cooldown = 1.0f;
-      }
-   }
-   else
-   {
-      if( _cutscene.fadeout_cooldown > 0.0f )
-      {
-         render = 1;
-         render_alpha = _cutscene.fadeout_cooldown;
-         _cutscene.fadeout_cooldown -= vg.time_delta;
-      }
+/*
+ * Creates inverse rotation matrices which the IK system uses.
+ */
+void skeleton_create_inverses( ms_skeleton *skele )
+{
+   /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
+   for( u32 i=0; i<skele->ik_count; i++ )
+   {
+      ms_skeleton_ik *ik = &skele->ik[i];
+      m4x3f inverse;
+      v3f iv0, iv1, ivaxis;
+      v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 );
+      v3_sub( skele->bones[ik->pole].co,   skele->bones[ik->lower].co, iv1 );
+      v3_cross( iv0, iv1, ivaxis );
+      v3_normalize( ivaxis );
+
+      skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
+      skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
    }
+}
 
-   if( render )
+/*
+ * Apply a model matrix to all bones, should be done last
+ */
+void skeleton_apply_transform( ms_skeleton *skele, m4x3f transform, m4x3f *final_mtx )
+{
+   for( u32 i=0; i<skele->bone_count; i++ )
    {
-      glEnable(GL_BLEND);
-      glDisable(GL_DEPTH_TEST);
-      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-      glBlendEquation(GL_FUNC_ADD);
-
-      shader_blitcolour_use();
-      shader_blitcolour_uColour( (v4f){ 0.04f, 0.02f, 0.03f, vg_clampf( render_alpha, 0.0f, 1.0f ) } );
-      render_fsquad();
+      ms_skeleton_bone *sb = &skele->bones[i];
+      m4x3_mul( transform, final_mtx[i], final_mtx[i] );
    }
 }
 
-void cutscene_render( world_instance *world, vg_camera *cam )
+/*
+ * Apply an inverse matrix to all bones which maps vertices from bind space into
+ * bone relative positions
+ */
+void skeleton_apply_inverses( ms_skeleton *skele, m4x3f *final_mtx )
 {
-   if( _cutscene.state >= k_cutscene_state_ready )
+   for( u32 i=0; i<skele->bone_count; i++ )
    {
-      for( u32 i=0; i<_cutscene.instance_count; i ++ )
-         cutscene_render_instance( &_cutscene.instances[i], world, cam );
+      ms_skeleton_bone *sb = &skele->bones[i];
+      m4x3f inverse;
+      m3x3_identity( inverse );
+      v3_negate( sb->co, inverse[3] );
+      m4x3_mul( final_mtx[i], inverse, final_mtx[i] );
    }
 }
 
-void _cutscene_gui( ui_context *ctx )
+/*
+ * Apply all IK modifiers (2 bone ik reference from blender is supported)
+ */
+void skeleton_apply_ik_pass( ms_skeleton *skele, m4x3f *final_mtx )
 {
-   if( _cutscene.subtitle )
-   {
-      ctx->font = &vgf_default_small;
-      ctx->kern[1] = 16;
-      ui_px scale = 2;
-      ui_rect box = { 0,0, 1000, 80*2 };
-      ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, box );
-      box[1] = vg.window_y - (box[3] + 8);
-
-      i32 lines = 1;
-      
-      const char *_c = _cutscene.subtitle;
-      u8 c;
-
-      i32 length = 0;
-      ui_px y = box[1];
-
-      while(1) 
-      {
-         c = *(_c ++);
-
-         /* TODO: This is pasted straight from vg_ui, maybe create a vg_ui_text_iter() ...? */
-         if( c == '\x1B' )
-         {
-            while( (c = *(_c ++)) )
-            {
-               if( c == 'm' ) 
-                  break;
-            } 
-           
-            if( c == 0 ) 
-               break;
-            else 
-               continue;
-         }
-
-         if( c >= 32 ) 
-            length ++;
-         else if( c == '\n' || c == '\0' ) 
-         {
-            ui_px w = length * ctx->font->sx*scale + 16;
-            ui_rect background_rect = { vg.window_x/2 - w/2, y-8, w, ctx->font->sy*scale+16 };
-
-            ui_fill( ctx, background_rect, ui_opacity( GUI_COL_DARK, 0.75f ) );
-            y += (ctx->font->sy)*scale + 16;
-            length = 0;
-            lines ++;
-         }
-         
-         if( c == '\0' )
-            break;
-      }
-
-      ui_text( ctx, box, _cutscene.subtitle, scale, k_ui_align_center, 0 );
-      ctx->font = &vgf_default_small;
-      ctx->kern[1] = 0;
+   for( u32 i=0; i<skele->ik_count; i++ )
+   {
+      ms_skeleton_ik *ik = &skele->ik[i];
+      v3f v0, /* base -> target */
+          v1, /* base -> pole */
+          vaxis;
+
+      v3f co_base,
+          co_target,
+          co_pole;
+
+      v3_copy( final_mtx[ik->lower][3], co_base );
+      v3_copy( final_mtx[ik->target][3], co_target );
+      v3_copy( final_mtx[ik->pole][3], co_pole );
+
+      v3_sub( co_target, co_base, v0 );
+      v3_sub( co_pole, co_base, v1 );
+      v3_cross( v0, v1, vaxis );
+      v3_normalize( vaxis );
+      v3_normalize( v0 );
+      v3_cross( vaxis, v0, v1 );
+
+      /* localize problem into [x:v0,y:v1] 2d plane */
+      v2f base = { v3_dot( v0, co_base   ), v3_dot( v1, co_base   ) },
+          end  = { v3_dot( v0, co_target ), v3_dot( v1, co_target ) },
+          knee;
+
+      /* Compute angles (basic trig)*/
+      v2f delta;
+      v2_sub( end, base, delta );
+
+      f32 l1 = v3_length( skele->bones[ik->lower].end ),
+          l2 = v3_length( skele->bones[ik->upper].end ),
+          d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
+          c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
+          rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
+
+      knee[0] = sinf(-rot) * l1;
+      knee[1] = cosf(-rot) * l1;
+
+      m4x3_identity( final_mtx[ik->lower] );
+      m4x3_identity( final_mtx[ik->upper] );
+
+      /* create rotation matrix */
+      v3f co_knee;
+      v3_muladds( co_base, v0, knee[0], co_knee );
+      v3_muladds( co_knee, v1, knee[1], co_knee );
+      vg_line( co_base, co_knee, 0xff00ff00 );
+
+      m4x3f transform;
+      v3_copy( vaxis, transform[0] );
+      v3_muls( v0, knee[0], transform[1] );
+      v3_muladds( transform[1], v1, knee[1], transform[1] );
+      v3_normalize( transform[1] );
+      v3_cross( transform[0], transform[1], transform[2] );
+      v3_copy( co_base, transform[3] );
+
+      m3x3_mul( transform, ik->ia, transform );
+      m4x3_copy( transform, final_mtx[ik->lower] );
+
+      /* upper/knee bone */
+      v3_copy( vaxis, transform[0] );
+      v3_sub( co_target, co_knee, transform[1] );
+      v3_normalize( transform[1] );
+      v3_cross( transform[0], transform[1], transform[2] );
+      v3_copy( co_knee, transform[3] );
+
+      m3x3_mul( transform, ik->ib, transform );
+      m4x3_copy( transform, final_mtx[ik->upper] );
    }
 }
 
-/* cutscene magi 
- * ----------------------------------------------------------------------------
+/*
+ * Applies the typical operations that you want for an IK rig: 
+ *    Pose, IK, Pose(deferred), Inverses, Transform
  */
+void skeleton_apply_standard( ms_skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx )
+{
+   skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik, final_mtx );
+   skeleton_apply_ik_pass( skele, final_mtx );
+   skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only, final_mtx );
+   skeleton_apply_inverses( skele, final_mtx );
+   skeleton_apply_transform( skele, transform, final_mtx );
+}
 
-static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
+void skeleton_alloc_from( ms_skeleton *skele, vg_stack_allocator *stack, vg_model *model, mdl_armature *armature )
 {
-   if( _cutscene.state == k_cutscene_state_none )
-   {
-      ui_text( ctx, rect, "No cutscene loaded.", 1, k_ui_align_middle_center, 0 );
-      return;
-   }
+   skele->bone_count     = armature->bone_count+1;
+   skele->ik_count       = 0;
+   skele->collider_count = 0;
 
-   if( _cutscene.state == k_cutscene_state_loading )
+   for( u32 i=0; i<armature->bone_count; i++ )
    {
-      ui_text( ctx, rect, "Cutscene loading..", 1, k_ui_align_middle_center, 0 );
-      return;
+      mdl_bone *bone = &model->bones[ armature->bone_start+i ];
+      if( bone->flags & k_bone_flag_ik )
+         skele->ik_count ++;
+      if( bone->collider )
+         skele->collider_count ++;
    }
 
-   if( _cutscene.state == k_cutscene_state_unloading )
-   {
-      ui_text( ctx, rect, "Cutscene UN-loading..", 1, k_ui_align_middle_center, 0 );
-      return;
-   }
+   u32 bone_size = sizeof(ms_skeleton_bone) * skele->bone_count,
+       ik_size   = sizeof(ms_skeleton_ik)   * skele->ik_count;
 
-   ms_strip *usage[8];
-   for( u32 i=0; i<VG_ARRAY_LEN(usage); i ++ ) usage[i] = NULL;
+   skele->bones = vg_stack_allocate( stack, bone_size, 8, NULL );
+   skele->ik    = vg_stack_allocate( stack, ik_size, 8, NULL );
 
-   ui_rect panel_l, panel_r;
-   ui_split( rect, k_ui_axis_v, 400, 4, panel_l, panel_r );
+   memset( skele->bones, 0, bone_size );
+   memset( skele->ik, 0, ik_size );
+}
 
-   if( ui_clip( rect, panel_l, panel_l ) )
-   {
-      ui_px root[2] = { panel_l[0]+8, panel_l[1]+8 };
-      ui_rect box = { root[0], root[1], panel_l[2]-16, 16 };
+/* Setup a skeleton from model. mdl's metadata should stick around */
+void skeleton_setup( ms_skeleton *skele, vg_model *model, u32 index, vg_stack_allocator *stack )
+{
+   u32 ik_count = 0, collider_count = 0;
+   skele->bone_count = 0;
+   skele->bones = NULL;
 
-      for( u32 i=0; i<_cutscene.unique_refs; i ++ )
-      {
-         struct model_ref *mref = &_cutscene.refs[i];
+   if( !model->armature_count )
+      vg_fatal_error( "No skeleton in model\n" );
 
-         char inf[128];
-         snprintf( inf, sizeof(inf), "%s (%u references)", mref->name, mref->reference_count );
-         ui_text( ctx, box, inf, 1, k_ui_align_middle_left, 0 );
-         box[1] += 16;
-      }
-   }
+   mdl_armature *armature = &model->armatures[ index ];
+   skeleton_alloc_from( skele, stack, model, armature );
 
-   if( ui_clip( rect, panel_r, panel_r ) )
+   for( u32 i=0; i<armature->bone_count; i++ )
    {
-      ui_px root[2] = { panel_r[0]+8, panel_r[1]+8 };
+      mdl_bone *bone = &model->bones[ armature->bone_start+i ];
+      ms_skeleton_bone *sb = &skele->bones[i+1];
+
+      v3_copy( bone->co, sb->co );
+      v3_copy( bone->end, sb->end );
 
-      for( u32 i=0; i<af_arrcount(&_cutscene.meta.strips); i ++ )
+      sb->parent = bone->parent;
+      sb->name   = af_str( model->packed_strings, bone->pstr_name );
+      sb->flags  = bone->flags;
+      sb->collider = bone->collider;
+      sb->orig_bone = bone;
+
+      if( sb->flags & k_bone_flag_ik )
       {
-         ms_strip *strip = af_arritm(&_cutscene.meta.strips, i );
-
-         if( !(strip->mode & k_ms_strip_mode_animation) )
-         {
-            ui_rect box = { root[0]+strip->offset, root[1], 1, panel_r[3]-16 };
-            ui_fill( ctx, box, 0xff00ff00 );
-
-            box[1] += box[3] -16;
-            box[2] = 200;
-            box[3] = 16;
-
-            if( ui_clip( panel_r, box, box ) )
-            {
-               if( strip->mode == k_ms_strip_mode_camera )
-                  ui_text( ctx, box, "Camera", 1, k_ui_align_middle_left, 0 );
-               if( strip->mode == k_ms_strip_mode_subtitle )
-                  ui_text( ctx, box, "\"", 1, k_ui_align_middle_left, 0 );
-               if( strip->mode == k_ms_strip_mode_fadeout )
-                  ui_text( ctx, box, "\\", 1, k_ui_align_middle_left, 0 );
-            }
-            continue;
-         }
+         skele->bones[ sb->parent ].flags |= k_bone_flag_ik;
          
-         u32 layer = 0;
-         for( u32 k=0; k<VG_ARRAY_LEN(usage); k ++ )
-         {
-            if( usage[k] )
-               if( usage[k]->offset + (i32)usage[k]->strip.length < strip->offset )
-                  usage[k] = NULL;
-
-            if( !usage[k] )
-            {
-               usage[k] = strip;
-               layer = k;
-               break;
-            }
-         }
-
-         ui_rect box = { strip->offset, layer*32, (i32)strip->strip.length, 30 };
-         box[0] += root[0];
-         box[1] += root[1];
-
-         if( ui_clip( panel_r, box, box ) )
-         {
-            u32 colour = af_str_hash( &_cutscene.meta.af, strip->strip.pstr_name );
-            ui_fill( ctx, box, colour | 0xff000000 );
-            ui_text( ctx, box, af_str( &_cutscene.meta.af, strip->strip.pstr_name ), 1, k_ui_align_middle_center, 0 );
-         }
+         if( ik_count == skele->ik_count )
+            vg_fatal_error( "Too many ik bones, corrupt model file\n" );
+
+         ms_skeleton_ik *ik = &skele->ik[ ik_count ++ ];
+         ik->upper = i+1;
+         ik->lower = bone->parent;
+         ik->target = bone->ik_target;
+         ik->pole = bone->ik_pole;
       }
 
-      ui_rect cursor = { (f32)_cutscene.time*_cutscene.meta.info.framerate, 0, 1, VG_ARRAY_LEN(usage)*32 };
-      cursor[0] += root[0];
-      cursor[1] += root[1];
-      if( ui_clip( panel_r, cursor, cursor ) )
-         ui_fill( ctx, cursor, 0xffffffff );
+      box_copy( bone->hitbox, sb->hitbox );
+
+      if( bone->collider )
+      {
+         if( collider_count == skele->collider_count )
+            vg_fatal_error( "Too many collider bones\n" );
+         collider_count ++;
+      }
    }
-}
 
-static int cmd_cutscene_play( int argc, const char *argv[] )
-{
-   if( argc == 1 )
-      _cutscene_load_and_play( argv[0], 0, 0 );
-   return 1;
-}
+   /* fill in implicit root bone */
+   v3_zero( skele->bones[0].co );
+   v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
+   skele->bones[0].parent = 0xffffffff;
+   skele->bones[0].flags = 0;
+   skele->bones[0].name = "[root]";
 
-static int cmd_cutscene_inspector( int argc, const char *argv[] )
-{
-   ui_px w = 800, h = 400;
-   struct vg_magi_panel *magi = _vg_magi_open( w, h, VG_MAGI_ALL );
-   magi->title = "Cutscene Inpsector";
-   magi->data = NULL;
-   magi->ui_cb = cb_cutscene_view;
-   magi->close_cb = NULL;
-   return 1;
+   skeleton_create_inverses( skele );
+   vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
+   vg_success( "                     %u colliders\n", skele->collider_count );
 }
 
-void cutscene_register(void)
+void skeleton_debug( ms_skeleton *skele, m4x3f *final_mtx )
 {
-   vg_console_reg_cmd( "cutscene_play", cmd_cutscene_play, NULL );
-   vg_console_reg_cmd( "cutscene_inspector", cmd_cutscene_inspector, NULL );
+   for( u32 i=1; i<skele->bone_count; i ++ )
+   {
+      ms_skeleton_bone *sb = &skele->bones[i];
+      v3f p0, p1;
+      v3_copy( sb->co, p0 );
+      v3_add( p0, sb->end, p1 );
+
+      m4x3_mulv( final_mtx[i], p0, p0 );
+      m4x3_mulv( final_mtx[i], p1, p1 );
+
+      if( sb->flags & k_bone_flag_deform )
+      {
+         if( sb->flags & k_bone_flag_ik )
+            vg_line( p0, p1, 0xff0000ff );
+         else
+            vg_line( p0, p1, 0xffcccccc );
+      }
+      else
+         vg_line( p0, p1, 0xff00ffff );
+   }
 }
index 4e1211b8079ff5bbe8603b5780ec27aac4663e72..df51d41e063519015f2721194f6c02a0af0e2b7a 100644 (file)
@@ -1,12 +1,12 @@
-#pragma once
-#include "model.h"
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/metascene.c"
+#else
 
 #define MS_VERSION_NR 2
 #define MS_VERSION_MIN 2
 
+typedef struct metascene metascene;
 typedef struct ms_scene_info ms_scene_info;
-typedef struct ms_context ms_context;
 typedef struct ms_instance ms_instance;
 typedef struct ms_override ms_override;
 typedef struct ms_strip ms_strip;
@@ -21,9 +21,9 @@ struct ms_scene_info
    u32 end_frame;
 };
 
-struct ms_context
+struct metascene
 {
-   array_file_context af;
+   const void *packed_strings;
 
    ms_scene_info info;
    struct array_file_ptr infos,
@@ -115,112 +115,85 @@ struct ms_curve_keyframe
    v2f co, l, r;
 };
 
-struct cs_instance 
-{
-   bool disable_render;
-   u32 ref_id;
-   m4x3f *skinning_data;
-};
-
-struct cs_subtitle
-{
-   const char *key, *value;
-};
+/* skeletons 
+ * ------------------------------------------------------------------------------------------------------------------ */
 
-#include "skeleton.h"
+typedef struct ms_skeleton ms_skeleton;
+typedef struct ms_skeleton_bone ms_skeleton_bone;
+typedef struct ms_skeleton_ik ms_skeleton_ik;
 
-struct _cutscene
+struct ms_skeleton
 {
-   ms_context meta;
-   vg_stack_allocator stack;
-
-   enum cutscene_state
+   struct ms_skeleton_bone
    {
-      k_cutscene_state_none,
-      k_cutscene_state_loading,
-      k_cutscene_state_unloading,
-      k_cutscene_state_ready,
-      k_cutscene_state_playing,
-      k_cutscene_state_done,
-   }
-   state;
+      v3f co, end;
+      u32 parent;
 
-   struct model_ref
-   {
-      const char *name;
-      u32 name_hash;
-      u32 reference_count;
+      u32 flags;
+      int defer;
 
-      mdl_context mdl;
-
-      struct cs_skeleton
-      {
-         struct skeleton sk;
-         u32 skinning_offset;
-      }
-      *skeletons;
-      u32 total_skinning_bones;
+      //ms_keyframe kf;
+      mdl_bone *orig_bone;
+      u32 collider;     // TODO: SOA
+      boxf hitbox;      // TODO: SOA
+      const char *name; // TODO: SOA
    }
-   * refs;
-   u32 unique_refs;
-
-   struct cs_instance *instances;
-   u32 instance_count;
+   *bones;
+   u32 bone_count;
 
-   struct cs_sampler
+   struct ms_skeleton_ik
    {
-      ms_strip *strip;
-      ms_override *override;
-      union
-      {
-         struct
-         {
-            ms_track *track;
-            f32 *target;
-            u32 keyframe;
-            u32 semantic;
-         }
-         curves;
-
-         struct
-         {
-            struct skeleton *ref_sk;
-            m4x3f *skinning_data;
-         }
-         skeleton;
-      };
+      u32 lower, upper, target, pole;
+      m3x3f ia, ib;
    }
-   samplers[32];
-   u32 active_samplers;
+   *ik;
+   u32 ik_count;
 
-   ent_camera *active_camera;
-   struct cs_instance *player_binding;
+   u32 collider_count,
+       bindable_count;
+};
 
-   u32 strip;
-   f32 time;
+void metascene_load( metascene *ms, const c8 *path, vg_stack_allocator *stack );
 
-   bool fadeout;
-   u8 skipped;
-   f32 fadeout_start, fadeout_cooldown;
+void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num );
+void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q );
+void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd );
+void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count );
 
-   const char *marker_this_frame;
-   const char *subtitle;
-   bool subtitle_length_warning;
+void skeleton_alloc_from( ms_skeleton *skele, vg_stack_allocator *stack, vg_model *model, mdl_armature *armature );
+u32 skeleton_bone_id( ms_skeleton *skele, const char *name );
+void skeleton_lerp_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd );
+void skeleton_copy_pose( ms_skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd );
 
-   bool freeze_player;
+typedef struct ms_skeletal_animation ms_skeletal_animation;
+struct ms_skeletal_animation
+{
+   ms_strip *strip;
+   ms_keyframe *keyframes_base;
+   f32 framerate;
+};
 
-   u32 raiser_entity;
+void skeleton_sample_anim( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output );
+int skeleton_sample_anim_clamped( ms_skeleton *skele, ms_skeletal_animation *anim, f32 time, ms_keyframe *output );
+
+typedef enum anim_apply
+{
+   k_anim_apply_always,
+   k_anim_apply_defer_ik,
+   k_anim_apply_deffered_only,
+   k_anim_apply_absolute
 }
-extern _cutscene;
-
-void metascene_load( ms_context *ms, const char *path, void *alloc );
-void cutscene_register(void);
-void cutscene_render( world_instance *world, vg_camera *cam );
-void cutscene_render_fadeout(void);
-bool _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity );
-void _cutscene_unload(void);
-void cutscene_update( f32 delta );
-ent_camera *_cutscene_active_camera(void);
-void _cutscene_gui( ui_context *ctx );
-
-struct cs_instance *_cutscene_get_first_model_instance( const char *mdl_name );
+anim_apply;
+
+void skeleton_apply_pose( ms_skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx );
+void skeleton_decompose_mtx_absolute( ms_skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx );
+void skeleton_inverse_for_ik( ms_skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse );
+void skeleton_create_inverses( ms_skeleton *skele );
+void skeleton_apply_transform( ms_skeleton *skele, m4x3f transform, m4x3f *final_mtx );
+void skeleton_apply_inverses( ms_skeleton *skele, m4x3f *final_mtx );
+void skeleton_apply_ik_pass( ms_skeleton *skele, m4x3f *final_mtx );
+void skeleton_apply_standard( ms_skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx );
+void skeleton_setup( ms_skeleton *skele, vg_model *model, u32 index, vg_stack_allocator *stack );
+void skeleton_debug( ms_skeleton *skele, m4x3f *final_mtx );
+
+#endif
index 6345cd28f29f27663e7ab7a4e85d7b1babcc3b7a..187b4911e0bf342bb32906f4a1bca475dc42cce2 100644 (file)
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-
-#include "vg/vg_io.h"
-
-#ifdef VG_3D
-#include "vg/vg_tex.h"
-#endif
-
-#include "vg/vg_msg.h"
-#include "vg/vg_string.h"
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "model.h"
-#include "shader_props.h"
-#include "array_file.h"
-
 /*
  * Model implementation
  */
 
-void mdl_fread_pack_file( mdl_context *mdl, mdl_file *info, void *dst )
+VG_TIER_0 vg_stream *vg_model_stream_pack_stream( vg_model_stream_context *ctx, mdl_file *file )
 {
-   if( !info->pack_size )
+   if( !file->pack_size )
    {
-      vg_info( "Packed file is only a header; it is not packed" );
-      vg_info( "path: %s\n", af_str( &mdl->af, info->pstr_path ) );
-      vg_fatal_error( "" );
+      vg_fatal_error( "Packed file is only a header; it is not packed"
+                      "path: %s\n", af_str( &ctx->model->packed_strings, file->pstr_path ) );
    }
-
-   fseek( mdl->af.fp, mdl->pack_base_offset + info->pack_offset, SEEK_SET );
-   u64 l = fread( dst, info->pack_size, 1, mdl->af.fp );
-
-   if( l != 1 )
-   {
-      af_close( &mdl->af );
-      vg_fatal_error( "Pack data corruption\n" );
-   }
-}
-
-void mdl_load_mesh_block( mdl_context *mdl, vg_stack_allocator *stack )
-{
-   struct array_file_ptr ptr;
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_vert, stack );
-   mdl->verts = ptr.data;
-   mdl->vert_count = ptr.count;
-
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_indice, stack );
-   mdl->indices = ptr.data;
-   mdl->indice_count = ptr.count;
+   vg_stream_seek( &ctx->stream, ctx->model->pack_base_offset + file->pack_offset );
+   ctx->stream.byte_limit = ctx->model->pack_base_offset + file->pack_offset + file->pack_size;
+   return &ctx->stream;
 }
 
-void mdl_load_metadata_block( mdl_context *mdl, vg_stack_allocator *stack )
+/* This also compiles them */
+VG_TIER_2 static void vg_model_stream_materials( vg_model_stream_context *ctx, vg_stack_allocator *stack )
 {
-   struct array_file_ptr ptr;
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_mesh, stack );
-   mdl->meshes = ptr.data;
-   mdl->mesh_count = ptr.count;
-
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_submesh, stack );
-   mdl->submeshes = ptr.data;
-   mdl->submesh_count = ptr.count;
-
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_texture, stack );
-   mdl->textures = ptr.data;
-   mdl->texture_count = ptr.count;
+   array_file_ptr mats_ptr;
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &mats_ptr, mdl_material, stack );
+   ctx->model->materials = mats_ptr.data;
+   ctx->model->material_count = mats_ptr.count;
+
+   u32 size = sizeof(union shader_props) * mats_ptr.count;
+   ctx->model->shader_props = vg_stack_allocate( stack, size, 8, "Compiled shader properties" );
+
+   /* 
+    * Step 0:
+    *  Acquiring the data source
+    *
+    * Step 1:
+    *  Converting into formal KV structure
+    *  We have 3 different modes;
+    *    v101+: old simple binary structures, requires 'generating' correct kvs
+    *    v106+: deprecated 'vg_msg' similar to kvs, only requires conversion
+    *    v110+: text KV's, direct parsing into vg_kvs
+    *
+    * Step 2:
+    *  Formal KV structure is then compiled into the binary union
+    */
+
+   /* step0 ----------------------------- */
+   u32 temp_frame = _vg_start_temp_frame();
+   {
+      array_file_ptr v101_materials;
+      array_file_ptr v106_data;
+      array_file_ptr v110_data;
 
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_armature, stack );
-   mdl->armatures = ptr.data;
-   mdl->armature_count = ptr.count;
+#if (VG_MODEL_VERSION_MIN <= 105)
+      if( ctx->model->version <= 105 )
+         af_load_array( &ctx->af, &v101_materials, "mdl_material", _vg_temp_stack(), sizeof(struct mdl_material_v101) );
+      else
+#endif
+      if( ctx->model->version <= 109 )
+         af_load_array( &ctx->af, &v106_data, "shader_data", _vg_temp_stack(), 1 );
+      else
+         af_load_array( &ctx->af, &v110_data, "shader_props", _vg_temp_stack(), 1 );
 
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &ptr, mdl_bone, stack );
-   mdl->bones = ptr.data;
-   mdl->bone_count = ptr.count;
+      vg_kvs kvs;
+      vg_kvs_init( &kvs, _vg_temp_stack() );
 
-   mdl_load_materials( mdl, stack );
-}
+      /* step1 ----------------------------- */
+#if (VG_MODEL_VERSION_MIN <= 105)
+      if( ctx->model->version <= 105 )
+      {
+         for( u32 i=0; i<ctx->model->material_count; i ++ )
+         {
+            mdl_material *mat = &ctx->model->materials[ i ];
+            struct mdl_material_v101 *old = af_arritm( &v101_materials, i );
+
+            mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+
+            vg_kv_append( &kvs, mat->props.kv_root, "version", "101" );
+            vg_kv_append_vu32( &kvs, mat->props.kv_root, "tex_diffuse", &old->tex_diffuse, 1 );
+
+            if( mat->shader == k_shader_cubemap )
+            {
+               vg_kv_append_vu32( &kvs, mat->props.kv_root, "cubemap", &old->tex_none0, 1 );
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "tint", old->colour, 4 );
+            }
+            else if( mat->shader == k_shader_terrain_blend )
+            {
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "sand_colour", old->colour, 4 );
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "blend_offset", old->colour1, 2 );
+            }
+            else if( mat->shader == k_shader_standard_vertex_blend )
+            {
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "blend_offset", old->colour1, 2 );
+            }
+            else if( mat->shader == k_shader_water )
+            {
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "shore_colour", old->colour, 4 );
+               vg_kv_append_vf32( &kvs, mat->props.kv_root, "deep_colour", old->colour1, 4 );
+            }
+         }
+      }
 
-static void *mdl_shader_standard( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_standard *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_standard );
-   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
-   vg_msg_getkvintg( msg, "render_flags", k_vg_msg_u32, &props->render_flags, NULL );
-   return props;
-}
+      else
+#endif
 
-static void *mdl_shader_terrain( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_terrain *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_terrain );
-   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
-   vg_msg_getkvvecf( msg, "sand_colour", k_vg_msg_v4f, props->sand_colour, (v4f){ 0.79, 0.63, 0.48, 1.0 } );
-   vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f, props->blend_offset, (v2f){ 0.5, 0.0 } );
+      if( ctx->model->version <= 109 )
+      {
+         for( u32 i=0; i<ctx->model->material_count; i ++ )
+         {
+            mdl_material *mat = &ctx->model->materials[ i ];
+            mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+            vg_kv_append( &kvs, mat->props.kv_root, "version", "106" );
 
-   return props;
-}
+            void *buffer = NULL;
+            if( v106_data.data )
+               buffer = v106_data.data + mat->props.kvs.offset;
 
-static void *mdl_shader_vertex_blend( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_vertex_blend *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_vertex_blend );
-   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
-   vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f, props->blend_offset, (v2f){ 0.5, 0.0 } );
-   return props;
-}
+            vg_kvs_append_from_legacy_msg2( &kvs, mat->props.kv_root, buffer, mat->props.kvs.size );
+         }
+      }
+      else
+      {
+         for( u32 i=0; i<ctx->model->material_count; i ++ )
+         {
+            mdl_material *mat = &ctx->model->materials[ i ];
+            mat->props.kv_root = vg_kv_append( &kvs, 0, NULL, NULL );
+            vg_kv_append( &kvs, mat->props.kv_root, "version", "110" );
 
-static void *mdl_shader_water( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_water *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_water );
-   vg_msg_getkvvecf( msg, "shore_colour", k_vg_msg_v4f, props->shore_colour, (v4f){0.03,0.32,0.61,1.0} );
-   vg_msg_getkvvecf( msg, "deep_colour", k_vg_msg_v4f, props->deep_colour, (v4f){0.0,0.006,0.03,1.0} );
-   vg_msg_getkvintg( msg, "fog_scale", k_vg_msg_f32, &props->fog_scale, (f32[]){0.04} );
-   vg_msg_getkvintg( msg, "fresnel", k_vg_msg_f32, &props->fresnel, (f32[]){5.0} );
-   vg_msg_getkvintg( msg, "water_scale", k_vg_msg_f32, &props->water_sale, (f32[]){ 0.008 } );
-   vg_msg_getkvvecf( msg, "wave_speed", k_vg_msg_v4f, props->wave_speed, (v4f){0.008,0.006,0.003,0.03} );
-   return props;
-}
+            const c8 *buffer = NULL;
+            if( v110_data.data )
+               buffer = v110_data.data + mat->props.kvs.offset;
 
-void *mdl_shader_cubemapped( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_cubemapped *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_cubemapped );
-   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
-   vg_msg_getkvintg( msg, "cubemap_entity", k_vg_msg_u32, &props->cubemap_entity, NULL );
-   vg_msg_getkvvecf( msg, "tint", k_vg_msg_v4f, props->tint, (v4f){1.0,1.0,1.0,1.0} );
-   return props;
-}
+            vg_stream kv_stream;
+            vg_buffer_stream_open( &kv_stream, buffer, mat->props.kvs.size, VG_STREAM_READ );
 
-// TODO: Shitty place for this to be
-const char *_shader_prop_workshop_keys[] =
-{
-   [k_workshop_shader_part_truck1  ] = "truck1",
-   [k_workshop_shader_part_truck2  ] = "truck2",
-   [k_workshop_shader_part_wheel1  ] = "wheel1",
-   [k_workshop_shader_part_wheel2  ] = "wheel2",
-   [k_workshop_shader_part_wheel3  ] = "wheel3",
-   [k_workshop_shader_part_wheel4  ] = "wheel4",
-   [k_workshop_shader_part_edge    ] = "edge",
-   [k_workshop_shader_part_griptape] = "griptape",
-   [k_workshop_shader_part_deck    ] = "deck"
-};
+            vg_kv_parser parser;
+            vg_kv_parser_init( &parser, &kvs, mat->props.kv_root );
+            vg_kv_parse_stream( &parser, &kv_stream );
+         }
+      }
 
-void *mdl_shader_workshop( vg_msg *msg, vg_stack_allocator *stack )
-{
-   struct shader_props_workshop *props = VG_STACK_ALLOCATE_STRUCT( stack, struct shader_props_workshop );
-   for( u32 i=0; i<k_workshop_shader_part_max; i ++ )
-      vg_msg_getkvintg( msg, _shader_prop_workshop_keys[i], k_vg_msg_u32, &props->tex_all[i], NULL );
+      vg_kv_write wtest = { .fp = stdout, .depth = 0 };
+      vg_kv_print_tree( &wtest, &kvs, 0 );
 
-   return props;
+      /* step2 ----------------------------- */
+      for( u32 i=0; i<ctx->model->material_count; i ++ )
+      {
+         mdl_material *mat = &ctx->model->materials[ i ];
+         u32 root = mat->props.kv_root;
+         union shader_props *props = &ctx->model->shader_props[ i ];
+
+         if( mat->shader == k_shader_standard || 
+             mat->shader == k_shader_standard_cutout || 
+             mat->shader == k_shader_foliage ||
+             mat->shader == k_shader_fxglow )
+         {
+            vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->standard.tex_diffuse, 1 );
+            vg_kv_read_vu32( &kvs, root, "render_flags", (u32[]){0}, &props->standard.render_flags, 1 );
+         }
+         else if( mat->shader == k_shader_standard_vertex_blend )
+         {
+            vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->vertex_blend.tex_diffuse, 1 );
+            vg_kv_read_vf32( &kvs, root, "blend_offset", (v2f){ 0.5, 0.0 }, props->vertex_blend.blend_offset, 2 );
+         }
+         else if( mat->shader == k_shader_cubemap )
+         {
+            vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->cubemapped.tex_diffuse, 1 );
+            vg_kv_read_vu32( &kvs, root, "cubemap_entity", (u32[]){0}, &props->cubemapped.cubemap_entity, 1 );
+            vg_kv_read_vf32( &kvs, root, "tint", (v4f){1.0,1.0,1.0,1.0}, props->cubemapped.tint, 4 );
+         }
+         else if( mat->shader == k_shader_terrain_blend )
+         {
+            vg_kv_read_vu32( &kvs, root, "tex_diffuse", (u32[]){0}, &props->terrain.tex_diffuse, 1 );
+            vg_kv_read_vf32( &kvs, root, "sand_colour", (v4f){ 0.79, 0.63, 0.48, 1.0 }, props->terrain.sand_colour, 4 );
+            vg_kv_read_vf32( &kvs, root, "blend_offset", (v2f){ 0.5, 0.0 }, props->terrain.blend_offset, 2 );
+         }
+         else if( mat->shader == k_shader_water )
+         {
+            vg_kv_read_vf32( &kvs, root, "shore_colour", (v4f){0.03,0.32,0.61,1.0}, props->water.shore_colour, 4 );
+            vg_kv_read_vf32( &kvs, root, "deep_colour", (v4f){0.0,0.006,0.03,1.0}, props->water.deep_colour, 4 );
+            vg_kv_read_vf32( &kvs, root, "fog_scale", (f32[]){0.04}, &props->water.fog_scale, 1 );
+            vg_kv_read_vf32( &kvs, root, "fresnel", (f32[]){5.0}, &props->water.fresnel, 1 );
+            vg_kv_read_vf32( &kvs, root, "water_scale", (f32[]){ 0.008 }, &props->water.water_sale, 1 );
+            vg_kv_read_vf32( &kvs, root, "wave_speed", (v4f){0.008,0.006,0.003,0.03}, props->water.wave_speed, 4 );
+         }
+         else if( mat->shader == k_shader_workshop )
+         {
+            const c8 *_shader_prop_workshop_keys[] =
+            {
+               [k_workshop_shader_part_truck1  ] = "truck1",
+               [k_workshop_shader_part_truck2  ] = "truck2",
+               [k_workshop_shader_part_wheel1  ] = "wheel1",
+               [k_workshop_shader_part_wheel2  ] = "wheel2",
+               [k_workshop_shader_part_wheel3  ] = "wheel3",
+               [k_workshop_shader_part_wheel4  ] = "wheel4",
+               [k_workshop_shader_part_edge    ] = "edge",
+               [k_workshop_shader_part_griptape] = "griptape",
+               [k_workshop_shader_part_deck    ] = "deck"
+            };
+
+            for( u32 j=0; j<k_workshop_shader_part_max; j ++ )
+               vg_kv_read_vu32( &kvs, root, _shader_prop_workshop_keys[j], (u32[]){0}, &props->workshop.tex_all[j], 1 );
+         }
+      }
+   }
+   _vg_end_temp_frame( temp_frame );
 }
 
-static bool mdl_legacy_v105_properties( struct mdl_material_v105 *mat, vg_msg *dst )
+VG_TIER_2 void vg_model_stream_metadata( vg_model_stream_context *ctx, vg_stack_allocator *stack )
 {
-   vg_msg_wkvnum( dst, "tex_diffuse", k_vg_msg_u32, 1, &mat->tex_diffuse );
+   array_file_ptr strings;
+   af_load_array( &ctx->af, &strings, "strings", stack, 1 );
+   ctx->model->packed_strings = strings.data;
+   ctx->model->flags |= VG_MODEL_CPU_METADATA;
 
-   if( mat->shader == k_shader_cubemap )
-   {
-      vg_msg_wkvnum( dst, "cubemap", k_vg_msg_u32, 1, &mat->tex_none0 );
-      vg_msg_wkvnum( dst, "tint", k_vg_msg_f32, 4, mat->colour );
-   }
-   else if( mat->shader == k_shader_terrain_blend )
-   {
-      vg_msg_wkvnum( dst, "sand_colour", k_vg_msg_f32, 4, mat->colour );
-      vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
-   }
-   else if( mat->shader == k_shader_standard_vertex_blend )
-   {
-      vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
-   }
-   else if( mat->shader == k_shader_water )
-   {
-      vg_msg_wkvnum( dst, "shore_colour", k_vg_msg_f32, 4, mat->colour );
-      vg_msg_wkvnum( dst, "deep_colour", k_vg_msg_f32, 4, mat->colour1 );
-   }
+   array_file_meta *pack = af_find_array( &ctx->af, "pack" );
+   if( pack ) ctx->model->pack_base_offset = pack->file_offset;
+   else       ctx->model->pack_base_offset = 0;
 
-   return 1;
-}
+   struct array_file_ptr ptr;
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_mesh, stack );
+   ctx->model->meshes = ptr.data;
+   ctx->model->mesh_count = ptr.count;
 
-void mdl_load_materials( mdl_context *mdl, vg_stack_allocator *stack )
-{
-   array_file_ptr mats_ptr;
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &mats_ptr, mdl_material, stack );
-   mdl->materials = mats_ptr.data;
-   mdl->material_count = mats_ptr.count;
-
-#if (MDL_VERSION_MIN <= 105)
-   array_file_ptr legacy_materials;
-   if( mdl->version <= 105 )
-      af_load_array( &mdl->af, &legacy_materials, "mdl_material", stack, sizeof(struct mdl_material_v105) );
-#endif
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_submesh, stack );
+   ctx->model->submeshes = ptr.data;
+   ctx->model->submesh_count = ptr.count;
 
-   array_file_ptr data;
-   af_load_array( &mdl->af, &data, "shader_data", stack, 1 );
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_texture, stack );
+   ctx->model->textures = ptr.data;
+   ctx->model->texture_count = ptr.count;
 
-   for( u32 i=0; i<mdl->material_count; i ++ )
-   {
-      mdl_material *mat = &mdl->materials[ i ];
-      vg_msg msg;
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_armature, stack );
+   ctx->model->armatures = ptr.data;
+   ctx->model->armature_count = ptr.count;
 
-#if (MDL_VERSION_MIN <= 105)
-      u8 legacy_buf[512];
-      if( mdl->version <= 105 )
-      {
-         vg_msg_init( &msg, legacy_buf, sizeof(legacy_buf) );
-         mdl_legacy_v105_properties( af_arritm( &legacy_materials,i ), &msg );
-         vg_msg_init( &msg, legacy_buf, msg.cur.co );
-      }
-      else
-#endif
-      {
-         vg_msg_init( &msg, data.data? (data.data + mat->props.kvs.offset): NULL, mat->props.kvs.size );
-      }
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_bone, stack );
+   ctx->model->bones = ptr.data;
+   ctx->model->bone_count = ptr.count;
 
-      if( mat->shader == k_shader_standard || 
-          mat->shader == k_shader_standard_cutout || 
-          mat->shader == k_shader_foliage ||
-          mat->shader == k_shader_fxglow )
-      {
-         mat->props.compiled = mdl_shader_standard( &msg, stack );
-      }
-      else if( mat->shader == k_shader_standard_vertex_blend )
-      {
-         mat->props.compiled = mdl_shader_vertex_blend( &msg, stack );
-      }
-      else if( mat->shader == k_shader_cubemap )
-      {
-         mat->props.compiled = mdl_shader_cubemapped( &msg, stack );
-      }
-      else if( mat->shader == k_shader_terrain_blend )
-      {
-         mat->props.compiled = mdl_shader_terrain( &msg, stack );
-      }
-      else if( mat->shader == k_shader_water )
-      {
-         mat->props.compiled = mdl_shader_water( &msg, stack );
-      }
-      else if( mat->shader == k_shader_workshop )
-      {
-         mat->props.compiled = mdl_shader_workshop( &msg, stack );
-      }
-      else
-         mat->props.compiled = NULL;
-   }
+   vg_model_stream_materials( ctx, stack );
 }
 
-/*
- * if calling mdl_open, and the file does not exist, the game will fatal quit
- */
-void mdl_open( mdl_context *mdl, const char *path, vg_stack_allocator *stack )
+VG_TIER_2 void vg_model_stream_meshes_cpu( vg_model_stream_context *ctx, vg_stack_allocator *stack )
 {
-   memset( mdl, 0, sizeof( mdl_context ) );
-   af_open( &mdl->af, path, MDL_VERSION_MIN, MDL_VERSION_NR, stack );
-   mdl->version = mdl->af.header.version;
-
-   array_file_meta *pack = af_find_array( &mdl->af, "pack" );
-   if( pack ) 
-      mdl->pack_base_offset = pack->file_offset;
-   else 
-      mdl->pack_base_offset = 0;
-}
+   VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+   ctx->model->flags |= VG_MODEL_CPU_MESHES;
 
-/*
- * close file handle
- */
-void mdl_close( mdl_context *mdl )
-{
-   af_close( &mdl->af );
-}
-
-/* useful things you can do with the model */
+   struct array_file_ptr ptr;
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_vert, stack );
+   ctx->model->verts = ptr.data;
+   ctx->model->vert_count = ptr.count;
 
-void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
-{
-   q_m3x3( transform->q, mtx );
-   v3_muls( mtx[0], transform->s[0], mtx[0] );
-   v3_muls( mtx[1], transform->s[1], mtx[1] );
-   v3_muls( mtx[2], transform->s[2], mtx[2] );
-   v3_copy( transform->co, mtx[3] );
+   AF_LOAD_ARRAY_STRUCT( &ctx->af, &ptr, mdl_indice, stack );
+   ctx->model->indices = ptr.data;
+   ctx->model->indice_count = ptr.count;
 }
 
-/*
- * Simple mesh interface for OpenGL
- * ----------------------------------------------------------------------------
- */
+#if defined( VG_ENGINE )
+struct model_upload_task
+{
+   vg_model *model;
+   mdl_vert *vert_buffer;
+   u32 *indice_buffer;
+};
 
-#ifdef VG_3D
-static void mesh_upload( glmesh *mesh, mdl_vert *verts, u32 vert_count, u32 *indices, u32 indice_count )
+VG_TIER_0 static void vg_model_upload_task( struct model_upload_task *in_args )
 {
-   glGenVertexArrays( 1, &mesh->vao );
-   glGenBuffers( 1, &mesh->vbo );
-   glGenBuffers( 1, &mesh->ebo );
-   glBindVertexArray( mesh->vao );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
-   size_t stride = sizeof(mdl_vert);
+   glGenVertexArrays( 1, &in_args->model->vao );
+   glBindVertexArray( in_args->model->vao );
+   glGenBuffers( 1, &in_args->model->vbo );
+   glGenBuffers( 1, &in_args->model->ebo );
 
-   glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
-   glBufferData( GL_ARRAY_BUFFER, vert_count*stride, verts, GL_STATIC_DRAW );
+   u32 stride = sizeof(mdl_vert);
+   glBindBuffer( GL_ARRAY_BUFFER, in_args->model->vbo );
+   glBufferData( GL_ARRAY_BUFFER, in_args->model->vert_count*stride, in_args->vert_buffer, GL_STATIC_DRAW );
 
-   glBindVertexArray( mesh->vao );
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, indice_count*sizeof(u32), indices, GL_STATIC_DRAW );
+   glBindVertexArray( in_args->model->vao );
+   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, in_args->model->ebo );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, in_args->model->indice_count*sizeof(u32), 
+                                          in_args->indice_buffer, GL_STATIC_DRAW );
    
    /* 0: coordinates */
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
@@ -324,119 +301,45 @@ static void mesh_upload( glmesh *mesh, mdl_vert *verts, u32 vert_count, u32 *ind
    /* 5: groups */
    glVertexAttribIPointer( 5, 4, GL_UNSIGNED_BYTE, stride, (void *)offsetof(mdl_vert, groups) );
    glEnableVertexAttribArray( 5 );
-
-   mesh->indice_count = indice_count;
-   mesh->loaded = 1;
-}
-
-void mesh_bind( glmesh *mesh )
-{
-   glBindVertexArray( mesh->vao );
-}
-
-void mesh_drawn( u32 start, u32 count )
-{
-   glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) );
-}
-
-void mesh_draw( glmesh *mesh )
-{
-   mesh_drawn( 0, mesh->indice_count );
-}
-
-void mesh_free( glmesh *mesh )
-{
-   if( mesh->loaded )
-   {
-      glDeleteVertexArrays( 1, &mesh->vao );
-      glDeleteBuffers( 1, &mesh->ebo );
-      glDeleteBuffers( 1, &mesh->vbo );
-      mesh->loaded = 0;
-   }
-}
-
-void mdl_draw_submesh( mdl_submesh *sm )
-{
-   mesh_drawn( sm->indice_start, sm->indice_count );
 }
 #endif
 
-i32 mdl_get_mesh_index( mdl_context *mdl, const char *name )
+#if defined( VG_ENGINE )
+VG_TIER_2 void vg_model_stream_meshes_gpu( vg_model_stream_context *ctx, u32 *fixup_table )
 {
-   u32 hash = vg_strdjb2( name );
-   for( u32 i=0; i<mdl->mesh_count; i++ )
-   {
-      mdl_mesh *mesh = &mdl->meshes[ i ];
-      if( af_str_eq( &mdl->af, mesh->pstr_name, name, hash ) ) 
-         return i;
-   }
-   return -1;
-}
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+   ctx->model->flags |= VG_MODEL_GPU_MESHES;
 
-i32 mdl_get_submesh_index( mdl_context *mdl, const char *mesh_name )
-{
-   i32 mesh_index = mdl_get_mesh_index( mdl, mesh_name );
-   if( mesh_index == -1 )
-      return -1;
-
-   mdl_mesh *mesh = &mdl->meshes[ mesh_index ];
-   if( !mesh->submesh_count ) 
-      return -1;
+   /* NOTE: We could check here if we already have CPU meshes and use those buffers. 
+    *       In very rare instances (1 time) we use both paths. */
 
-   return  mesh->submesh_start;
-}
-
-#ifdef VG_3D
-struct payload_glmesh_load
-{
-   mdl_vert *verts;
-   u32 *indices;
-
-   u32 vertex_count,
-       indice_count;
-
-   glmesh *mesh;
-};
-
-static void _sync_mdl_load_glmesh( vg_async_task *task )
-{
-   THREAD_0;
-
-   struct payload_glmesh_load *job = (void *)task->data;
-   mesh_upload( job->mesh, job->verts, job->vertex_count, job->indices, job->indice_count );
-}
-
-void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
-{
-   THREAD_1;
-
-   array_file_meta *arr_vertices = af_find_array( &mdl->af, "mdl_vert" );
-   array_file_meta *arr_indices = af_find_array( &mdl->af, "mdl_indice" );
+   array_file_meta *arr_vertices = af_find_array( &ctx->af, "mdl_vert" );
+   array_file_meta *arr_indices = af_find_array( &ctx->af, "mdl_indice" );
 
    if( arr_vertices && arr_indices )
    {
       u32 size_verts   = vg_align8(sizeof(mdl_vert)*arr_vertices->item_count),
           size_indices = vg_align8(sizeof(mdl_indice)*arr_indices->item_count),
-          size_hdr     = vg_align8(sizeof(struct payload_glmesh_load)),
+          size_hdr     = vg_align8(sizeof(struct model_upload_task)),
           total        = size_hdr + size_verts + size_indices;
 
-      vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, total, 1 );
-      struct payload_glmesh_load *job = (void *)task->data;
+      struct model_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, total );
+
+      out_args->model = ctx->model;
+      out_args->vert_buffer   = ((void*)out_args) + size_hdr;
+      out_args->indice_buffer = ((void*)out_args) + size_hdr + size_verts;
+      ctx->model->vert_count = arr_vertices->item_count;
+      ctx->model->indice_count = arr_indices->item_count;
 
-      job->mesh = mesh;
-      job->verts = (void*)(task->data + size_hdr);
-      job->indices = (void*)(task->data + size_hdr + size_verts);
-      job->vertex_count = arr_vertices->item_count;
-      job->indice_count = arr_indices->item_count;
-      af_load_array_file_buffer( &mdl->af, arr_vertices, job->verts, sizeof(mdl_vert) );
-      af_load_array_file_buffer( &mdl->af, arr_indices, job->indices, sizeof(mdl_indice) );
+      af_load_array_file_buffer( &ctx->af, arr_vertices, out_args->vert_buffer, sizeof(mdl_vert) );
+      af_load_array_file_buffer( &ctx->af, arr_indices, out_args->indice_buffer, sizeof(mdl_indice) );
 
       if( fixup_table )
       {
-         for( u32 i=0; i<job->vertex_count; i ++ )
+         for( u32 i=0; i<ctx->model->vert_count; i ++ )
          {
-            mdl_vert *vert = &job->verts[i];
-            
+            mdl_vert *vert = &out_args->vert_buffer[i];
             for( u32 j=0; j<4; j++ )
                vert->groups[j] = fixup_table[vert->groups[j]];
          }
@@ -446,16 +349,15 @@ void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
        * Unpack the indices (if there are meshes)
        * ---------------------------------------------------------
        */
-
-      if( mdl->submesh_count )
+      if( ctx->model->submesh_count )
       {
-         mdl_submesh *sm = &mdl->submeshes[ 0 ];
+         mdl_submesh *sm = &ctx->model->submeshes[ 0 ];
          u32 offset = sm->vertex_count;
 
-         for( u32 i=1; i<mdl->submesh_count; i++ )
+         for( u32 i=1; i<ctx->model->submesh_count; i++ )
          {
-            mdl_submesh *sm = &mdl->submeshes[ i ];
-            u32 *indices    = job->indices + sm->indice_start;
+            mdl_submesh *sm = &ctx->model->submeshes[ i ];
+            u32 *indices    = out_args->indice_buffer + sm->indice_start;
 
             for( u32 j=0; j<sm->indice_count; j++ )
                indices[j] += offset;
@@ -464,44 +366,152 @@ void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
          }
       }
 
-      /* 
-       * Dispatch 
-       * -------------------------
-       */
-
-      vg_async_task_dispatch( task, _sync_mdl_load_glmesh );
+      _vg_async_send( out_args, (vg_async_fn)vg_model_upload_task );
    }
    else
       vg_fatal_error( "No vertex/indice data in model file\n" );
 }
 
-/* uploads the glmesh, and textures. everything is saved into the mdl_context */
-void mdl_async_full_load_std( mdl_context *mdl, u32 *fixup_table )
+VG_TIER_2 void vg_model_stream_textures_gpu( vg_model_stream_context *ctx )
 {
-   THREAD_1;
-   mdl_async_load_glmesh( mdl, &mdl->mesh, fixup_table );
-   
-   for( u32 i=0; i<mdl->texture_count; i ++ )
+   VG_ASSERT( ctx->model->flags & VG_MODEL_CPU_METADATA );
+   ctx->model->flags |= VG_MODEL_GPU_TEXTURES;
+   for( u32 i=0; i<ctx->model->texture_count; i ++ )
+   {
+      mdl_texture *tex = &ctx->model->textures[ i ];
+      mdl_file pack_info = tex->file;
+      _vg_tex_load_stream( &tex->tex, vg_model_stream_pack_stream( ctx, &pack_info ), 
+                           VG_TEX_REPEAT | VG_TEX_NEAREST | VG_TEX_NOMIP );
+   }
+}
+#endif
+
+VG_TIER_1 bool vg_model_stream_open( vg_model_stream_context *ctx, vg_model *model, const c8 *path )
+{
+   vg_zero_mem( ctx, sizeof(vg_model_stream_context) );
+   vg_zero_mem( model, sizeof(vg_model) );
+   if( vg_file_stream_open( &ctx->stream, path, VG_STREAM_READ ) )
    {
-      vg_stack_clear( &vg.scratch );
-      mdl_texture *tex = &mdl->textures[ i ];
+      ctx->model = model;
+      ctx->temp_frame = _vg_start_temp_frame();
+      if( !af_open_stream( &ctx->af, &ctx->stream, VG_MODEL_VERSION_MIN, VG_MODEL_VERSION_NR, _vg_temp_stack() ) )
+      {
+         vg_file_stream_close( &ctx->stream );
+         _vg_end_temp_frame( ctx->temp_frame );
+         return 0;
+      }
+      ctx->model->version = ctx->af.header.version;
+      return 1;
+   }
+   else return 0;
+}
+
+VG_TIER_0 void vg_model_stream_close( vg_model_stream_context *ctx )
+{
+   vg_file_stream_close( &ctx->stream );
+   _vg_end_temp_frame( ctx->temp_frame );
+}
+
+VG_TIER_2 bool vg_model_load( vg_model *model, u32 model_flags, const c8 *path, vg_stack_allocator *stack )
+{
+   bool success = 0;
+   model_flags |= VG_MODEL_CPU_METADATA;
+
+   vg_model_stream_context ctx;
+   if( vg_model_stream_open( &ctx, model, path ) )
+   {
+      if( model_flags & VG_MODEL_CPU_METADATA )
+         vg_model_stream_metadata( &ctx, stack );
+
+      if( model_flags & VG_MODEL_CPU_MESHES )
+         vg_model_stream_meshes_cpu( &ctx, stack );
+
+#if defined( VG_ENGINE )
+      VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+      if( model_flags & VG_MODEL_GPU_MESHES )
+         vg_model_stream_meshes_gpu( &ctx, NULL );
+
+      if( model_flags & VG_MODEL_GPU_TEXTURES )
+         vg_model_stream_textures_gpu( &ctx );
+#endif
 
-      void *data = vg_stack_allocate( &vg.scratch, tex->file.pack_size, 8, "MDL Pack Data" );
-      mdl_fread_pack_file( mdl, &tex->file, data );
-      vg_tex2d_load_qoi_async( data, tex->file.pack_size, VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &tex->glname );
+      vg_model_stream_close( &ctx );
+      success = 1;
    }
+   return success;
 }
 
-void mdl_sync_std_unload( mdl_context *mdl )
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_unload_gpu( vg_model *model )
 {
-   mesh_free( &mdl->mesh );
+   if( model->flags & VG_MODEL_GPU_MESHES )
+   {
+      model->flags &= ~(u32)(VG_MODEL_GPU_MESHES);
+      glDeleteVertexArrays( 1, &model->vao );
+      glDeleteBuffers( 1, &model->ebo );
+      glDeleteBuffers( 1, &model->vbo );
+   }
+
+   if( model->flags & VG_MODEL_GPU_TEXTURES )
+      for( u32 i=0; i<model->texture_count; i ++ )
+         vg_tex_delete( &model->textures[i].tex );
+}
+#endif
 
-   for( u32 i=0; i<mdl->texture_count; i ++ )
-      glDeleteTextures( 1, &mdl->textures[i].glname );
+VG_TIER_0 void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
+{
+   q_m3x3( transform->q, mtx );
+   v3_muls( mtx[0], transform->s[0], mtx[0] );
+   v3_muls( mtx[1], transform->s[1], mtx[1] );
+   v3_muls( mtx[2], transform->s[2], mtx[2] );
+   v3_copy( transform->co, mtx[3] );
+}
+
+#if defined( VG_ENGINE )
+
+VG_TIER_0 void vg_model_bind_mesh( vg_model *model )
+{
+   glBindVertexArray( model->vao );
+}
+
+VG_TIER_0 void vg_model_draw_elements( u32 start, u32 count )
+{
+   glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) );
+}
+
+VG_TIER_0 void vg_model_draw_submesh( mdl_submesh *sm )
+{
+   vg_model_draw_elements( sm->indice_start, sm->indice_count );
 }
 
 #endif
 
+VG_TIER_0 i32 vg_model_get_mesh_index( vg_model *model, const c8 *name )
+{
+   u32 hash = vg_strdjb2( name );
+   for( u32 i=0; i<model->mesh_count; i++ )
+   {
+      mdl_mesh *mesh = &model->meshes[ i ];
+      if( af_str_eq( model->packed_strings, mesh->pstr_name, name, hash ) ) 
+         return i;
+   }
+   return -1;
+}
+
+VG_TIER_0 i32 vg_model_get_submesh_index( vg_model *model, const c8 *mesh_name )
+{
+   i32 mesh_index = vg_model_get_mesh_index( model, mesh_name );
+   if( mesh_index == -1 )
+      return -1;
+
+   mdl_mesh *mesh = &model->meshes[ mesh_index ];
+   if( !mesh->submesh_count ) 
+      return -1;
+
+   return  mesh->submesh_start;
+}
+
+#if defined( VG_ENGINE )
 void mdl_compiler_init( mdl_compiler *compiler )
 {
    vg_stack_init( &compiler->stack, NULL, VG_MB(10), "MDL Compiler" );
@@ -612,23 +622,28 @@ u32 mdl_compiler_compile_texture_qoi( mdl_compiler *compiler, const char *name,
    u32 texture_id = compiler->textures->element_count + 1;
 
    mdl_texture *texture = af_compiler_allocate_items( &compiler->af, compiler->textures, 1 )->data;
-   texture->glname = 0;
    mdl_compiler_pack_data( compiler, name, data, data_len, &texture->file );
    return texture_id;
 }
 
-void mdl_compiler_push_shaderdata( mdl_compiler *compiler, u32 shader_id, vg_msg *shader_kvs )
+void mdl_compiler_push_shaderdata( mdl_compiler *compiler, u32 shader_id, vg_kvs *shader_kvs )
 {
    mdl_material *current_material = compiler->materials->last->data;
    current_material->shader = shader_id;
    current_material->props.kvs.offset = compiler->shader_data->element_count;
+
+   // FIXME FIXME FIXME FIXME FIXME NEED TO FLATTEN OUT THE KVS INTO STRINGYMABOB!!!!!!!!!!!!!!!!
+#if 0
    current_material->props.kvs.size = shader_kvs->cur.co;
 
    void *dest = af_compiler_allocate_items( &compiler->af, compiler->shader_data, vg_align8(shader_kvs->cur.co) )->data;
    memcpy( dest, shader_kvs->buf, shader_kvs->cur.co );
+#endif
 }
 
 void mdl_compiler_free( mdl_compiler *compiler )
 {
    vg_stack_free( &compiler->stack );
 }
+
+#endif
index f70740df5101e1327afc39d0dee223b4a5298d26..81d829220070c3a38a083e06565e4e35ec327186 100644 (file)
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/model.c"
+#else
 
-#pragma once
+#define VG_MODEL_VERSION_MIN 101
+#define VG_MODEL_VERSION_NR 109
+
+#define VG_MODEL_CPU_METADATA   0x4
+#define VG_MODEL_CPU_MESHES     0x8
+
+#if defined( VG_ENGINE )
+# define VG_MODEL_GPU_TEXTURES   0x1
+# define VG_MODEL_GPU_MESHES     0x2
+# define VG_MODEL_ENGINE_STANDARD (VG_MODEL_CPU_METADATA|VG_MODEL_GPU_TEXTURES|VG_MODEL_GPU_MESHES)
+# define VG_MODEL_ENGINE_PROCEDURAL_SOURCE (VG_MODEL_CPU_METADATA|VG_MODEL_GPU_TEXTURES|VG_MODEL_CPU_MESHES)
+#endif
+
+typedef u32 mdl_indice;
+typedef struct mdl_vert mdl_vert;
+typedef struct mdl_transform mdl_transform;
+typedef struct mdl_submesh mdl_submesh;
+typedef struct mdl_material mdl_material;
+typedef struct mdl_bone mdl_bone;
+typedef struct mdl_armature mdl_armature;
+typedef struct mdl_animation mdl_animation;
+typedef struct mdl_mesh mdl_mesh;
+typedef struct mdl_file mdl_file;
+typedef union mdl_texture mdl_texture;
+typedef struct mdl_header mdl_header;
+
+typedef struct vg_model vg_model;
+typedef struct vg_model_stream_context vg_model_stream_context;
+
+
+/* Load model the easy way */
+VG_TIER_2 bool vg_model_load( vg_model *model, u32 model_flags, const c8 *path, vg_stack_allocator *stack );
+
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_unload_gpu( vg_model *model );
+#endif
+
+/* Sub functions for each part of the load process
+ * ---------------------------------------------------------------------------------------------------------------  */
+struct vg_model_stream_context
+{
+   vg_stream stream;
+   array_file_context af;
+   vg_model *model;
+
+   u32 temp_frame;
+};
+
+VG_TIER_1 bool vg_model_stream_open( vg_model_stream_context *ctx, vg_model *model, const c8 *path );
+VG_TIER_0 void vg_model_stream_close( vg_model_stream_context *ctx );
+
+/* Parts which you might want (currently they all require metadata to be explicitly loaded) */
+VG_TIER_2 void vg_model_stream_metadata( vg_model_stream_context *ctx, vg_stack_allocator *stack );
+VG_TIER_2 void vg_model_stream_meshes_cpu( vg_model_stream_context *ctx, vg_stack_allocator *stack );
+
+#if defined( VG_ENGINE )
+VG_TIER_2 void vg_model_stream_meshes_gpu( vg_model_stream_context *ctx, u32 *fixup_table );
+VG_TIER_2 void vg_model_stream_textures_gpu( vg_model_stream_context *ctx );
+#endif
+
+VG_TIER_0 vg_stream *vg_model_stream_pack_stream( vg_model_stream_context *ctx, mdl_file *file );
 
-#define MDL_VERSION_MIN 101
-#define MDL_VERSION_NR 109
 
-#include "array_file.h"
+
+/* Rendering operations
+ * ----------------------------------------------------------------------------------------------------------------- */
+#if defined( VG_ENGINE )
+VG_TIER_0 void vg_model_bind_mesh( vg_model *model );
+VG_TIER_0 void vg_model_draw_elements( u32 start, u32 count );
+VG_TIER_0 void vg_model_draw_submesh( mdl_submesh *sm );
+#endif
+
+VG_TIER_0 i32 vg_model_get_mesh_index( vg_model *model, const c8 *name );
+VG_TIER_0 i32 vg_model_get_submesh_index( vg_model *model, const c8 *mesh_name );
+
+VG_TIER_0 void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx );
+
+
+
+/* model compiler 
+ * -----------------------------------------------------------------------------------------------------------------  */
+#if defined( VG_ENGINE )
+typedef struct mdl_compiler mdl_compiler;
+struct mdl_compiler
+{
+   af_compiler af;
+   af_compiler_index *meshes,
+                     *submeshes,
+                     *vertices,
+                     *indices,
+                     *bones,
+                     *materials,
+                     *shader_data,
+                     *armatures,
+                     *textures,
+                     *pack_data;
+   vg_stack_allocator stack;
+};
+#endif
 
 enum mdl_shader{
    k_shader_standard                = 0,
@@ -67,56 +160,32 @@ struct mdl_vert
 
 #pragma pack(pop)
 
-typedef u32 mdl_indice;
-
-typedef struct mdl_context mdl_context;
-typedef struct mdl_vert mdl_vert;
-typedef struct mdl_transform mdl_transform;
-typedef struct mdl_submesh mdl_submesh;
-typedef struct mdl_material mdl_material;
-typedef struct mdl_bone mdl_bone;
-typedef struct mdl_armature mdl_armature;
-typedef struct mdl_animation mdl_animation;
-typedef struct mdl_mesh mdl_mesh;
-typedef struct mdl_file mdl_file;
-typedef struct mdl_texture mdl_texture;
-typedef struct mdl_header mdl_header;
-
-typedef struct glmesh glmesh;
-struct glmesh
-{
-   u32 vao, vbo, ebo;
-   u32 indice_count;
-   u32 loaded;
-};
-
 struct mdl_transform
 {
    v3f co, s;
    v4f q;
 };
 
-static void transform_identity( mdl_transform *transform )
+VG_TIER_0 static inline void transform_identity( mdl_transform *transform )
 {
    v3_zero( transform->co );
    q_identity( transform->q );
    v3_fill( transform->s, 1.0f );
 }
 
-static void mdl_transform_vector( mdl_transform *transform, v3f vec, v3f dest )
+VG_TIER_0 static inline void mdl_transform_vector( mdl_transform *transform, v3f vec, v3f dest )
 {
    v3_mul( transform->s, vec, dest );
    q_mulv( transform->q, dest, dest );
 }
 
-static void mdl_transform_point( mdl_transform *transform, v3f co, v3f dest )
+VG_TIER_0 static inline void mdl_transform_point( mdl_transform *transform, v3f co, v3f dest )
 {
    mdl_transform_vector( transform, co, dest );
    v3_add( transform->co, dest, dest );
 }
 
-static void mdl_transform_mul( mdl_transform *a, mdl_transform *b, 
-                               mdl_transform *d )
+VG_TIER_0 static inline void mdl_transform_mul( mdl_transform *a, mdl_transform *b, mdl_transform *d )
 {
    mdl_transform_point( a, b->co, d->co );
    q_mul( a->q, b->q, d->q );
@@ -124,15 +193,8 @@ static void mdl_transform_mul( mdl_transform *a, mdl_transform *b,
    v3_mul( a->s, b->s, d->s );
 }
 
-struct mdl_file
-{
-   u32 pstr_path,
-       pack_offset,
-       pack_size;
-};
-
-#if (MDL_VERSION_MIN <= 105)
-struct mdl_material_v105
+#if (VG_MODEL_VERSION_MIN <= 105)
+struct mdl_material_v101
 {
    u32 pstr_name,
        shader,
@@ -163,7 +225,7 @@ struct mdl_material
          /* -> vg_msg containing KV properties */
       }
       kvs;
-      void *compiled;  /* -> shader specific structure for render */
+      u32 kv_root;
    } 
    props;
 };
@@ -208,14 +270,6 @@ struct mdl_armature
        pstr_name; // v107+
 };
 
-// struct mdl_animation
-// {
-//    u32 pstr_name,
-//        length;
-//    float rate;
-//    u32 offset;
-// };
-
 struct mdl_submesh
 {
    u32 indice_start,
@@ -243,16 +297,27 @@ struct mdl_mesh
        armature_id;
 };
 
-struct mdl_texture
+struct mdl_file
+{
+   u32 pstr_path,
+       pack_offset,
+       pack_size;
+};
+
+union mdl_texture
 {
    mdl_file file;
-   u32 glname;
+   vg_tex tex;
 };
 
-struct mdl_context
+struct vg_model
 {
-   array_file_context af;
    u32 version;
+   u32 flags;
+
+   /* VG_MODEL_CPU_METADATA ---------------------- */
+   const void *packed_strings;
+   union shader_props *shader_props;
 
    mdl_mesh *meshes;
    u32 mesh_count;
@@ -272,66 +337,18 @@ struct mdl_context
    mdl_bone *bones;
    u32 bone_count;
 
+   /* VG_MODEL_CPU_MESHES ---------------------- */
    mdl_vert *verts;
    u32 vert_count;
-
    u32 *indices;
    u32 indice_count;
 
    u32 pack_base_offset;
 
-   /* runtime */
-   glmesh mesh;
+   /* VG_MODEL_GPU_MESHES ----------------------- */
+#if defined( VG_ENGINE )
+   GLuint vao, vbo, ebo;
+#endif
 };
 
-void mesh_bind( glmesh *mesh );
-void mesh_drawn( u32 start, u32 count );
-void mesh_draw( glmesh *mesh );
-void mesh_free( glmesh *mesh );
-
-/* file context management */
-void mdl_open( mdl_context *mdl, const char *path, vg_stack_allocator *stack );
-void mdl_close( mdl_context *mdl );
-
-/* pack access */
-void mdl_fread_pack_file( mdl_context *mdl, mdl_file *info, void *dst );
-
-/* standard array groups */
-void mdl_load_metadata_block( mdl_context *mdl, vg_stack_allocator *stack );
-void mdl_load_mesh_block( mdl_context *mdl, vg_stack_allocator *stack );
-void mdl_load_materials( mdl_context *mdl, vg_stack_allocator *stack );
-
-/* load mesh */
-void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table );
-
-/* load textures and mesh */
-void mdl_async_full_load_std( mdl_context *mdl, u32 *fixup_table );
-void mdl_sync_std_unload( mdl_context *mdl );
-
-/* rendering */
-void mdl_draw_submesh( mdl_submesh *sm );
-i32 mdl_get_mesh_index( mdl_context *mdl, const char *name );
-i32 mdl_get_submesh_index( mdl_context *mdl, const char *mesh_name );
-
-void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx );
-
-/* model compiler 
- * --------------------------------- */
-
-typedef struct mdl_compiler mdl_compiler;
-struct mdl_compiler
-{
-   af_compiler af;
-   af_compiler_index *meshes,
-                     *submeshes,
-                     *vertices,
-                     *indices,
-                     *bones,
-                     *materials,
-                     *shader_data,
-                     *armatures,
-                     *textures,
-                     *pack_data;
-
-   vg_stack_allocator stack;
-};
+#endif
index 830413ebe906317273044fd84eaca324ab20918b..7675a3a0f67c96728b9646d97bff93542a971038 100644 (file)
@@ -1,28 +1,3 @@
-#include "skaterift.h"
-#include "vg/vg_steam2.h"
-#include "player.h"
-#include "network.h"
-#include "network_msg.h"
-#include "network_common.h"
-#include "player_remote.h"
-#include "world.h"
-#include "world_sfd.h"
-#include "world_routes.h"
-#include "vg/vg_ui/imgui.h"
-#include "gui.h"
-#include "ent_region.h"
-#include "vg/vg_loader.h"
-#include "network_requests.h"
-
-#ifdef _WIN32
- #include <winsock2.h>
- #include <ws2tcpip.h>
-#else
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netdb.h>
-#endif
-
 struct network_client network_client =
 {
    .auth_mode = eServerModeAuthentication,
@@ -159,7 +134,7 @@ static void network_disconnect(void)
 
 void network_status_string( vg_str *str, u32 *colour )
 {
-   if( g_client.demo_mode )
+   if( _is_running_demo() )
    {
       vg_strcat( str, "Unavailible in demo" );
       *colour = 0xff0000a0;
@@ -180,18 +155,24 @@ void network_status_string( vg_str *str, u32 *colour )
             vg_strcat( str, "No Connection" );
          else if( state == k_ESteamNetworkingConnectionState_Connecting )
          {
-            vg_strcatf( str, "Connecting... %s", network_client.host_adress );
+            if( network_client.resolve_state == k_resolve_state_resolving )
+               vg_strcatf( str, "Connecting... <resolving>" );
+            else
+               vg_strcatf( str, "Connecting... %s", network_client.adress );
 
             if( network_client.retries )
             {
                vg_strcat( str, "\n(" );
-               vg_strcati32( str, network_client.retries );
+               vg_strcati64( str, network_client.retries, 10 );
                vg_strcat( str, " retries)" );
             }
          }
          else if( state == k_ESteamNetworkingConnectionState_Connected )
          {
-            vg_strcatf( str, "Connected to:\n%s", network_client.host_adress );
+            if( network_client.resolve_state == k_resolve_state_resolving ) // Should this ever happen? No I dont think so
+               vg_strcatf( str, "Connected to: <resolving>" );
+            else
+               vg_strcatf( str, "Connected to: %s", network_client.adress );
             *colour = 0xff00a020;
          }
          else if( state == k_ESteamNetworkingConnectionState_ClosedByPeer )
@@ -239,8 +220,7 @@ void render_server_status_gui(void)
    ui_fill( ctx, r, bg );
    ui_text( ctx, r, buf, 1, k_ui_align_center, 0 );
    ui_flush( ctx, k_ui_shader_colour, NULL );
-   
-   skaterift.rt_textures[ k_skaterift_rt_server_status ] = g_render.fb_network_status->attachments[0].id;
+   skaterift.rt_textures[ k_skaterift_rt_server_status ] = &g_render.fb_network_status->attachments[0].tex;
 }
 
 void cb_skaterift_connection_changed( SteamNetConnectionStatusChangedCallback_t *info )
@@ -300,8 +280,6 @@ void cb_skaterift_persona_changed( PersonaStateChange_t *info )
    if( !network_connected() )
       return;
 
-   vg_info( "User: " PRINTF_U64 ", change: %u\n", info->m_ulSteamID, info->m_nChangeFlags );
-
    if( info->m_ulSteamID == SteamAPI_ISteamUser_GetSteamID( _steam_api.pSteamUser ) )
       if( info->m_nChangeFlags & k_EPersonaChangeName )
          network_send_username();
@@ -317,25 +295,27 @@ void cb_skaterift_persona_changed( PersonaStateChange_t *info )
    }
 }
 
-void network_set_host( const char *host_str, const char *port_str )
+void network_set_host( const c8 *host_str, const c8 *port_str )
 {
-   vg_strncpy( host_str, network_client.host_adress, sizeof(network_client.host_adress), k_strncpy_overflow_fatal );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   VG_ASSERT( network_client.resolve_state != k_resolve_state_resolving );
+   vg_strncpy( host_str, network_client.adress, sizeof(network_client.adress), k_strncpy_overflow_fatal );
 
    memset( &network_client.ip, 0, sizeof(network_client.ip) );
    network_client.resolve_state = k_resolve_state_no;
 
    if( port_str )
    {
-      vg_strncpy( port_str, network_client.host_port, sizeof(network_client.host_port), k_strncpy_overflow_fatal );
+      vg_strncpy( port_str, network_client.port, sizeof(network_client.port), k_strncpy_overflow_fatal );
    }
    else
    {
       vg_str str;
-      vg_strnull( &str, network_client.host_port, sizeof(network_client.host_port) );
-      vg_strcati32( &str, NETWORK_PORT );
+      vg_strnull( &str, network_client.port, sizeof(network_client.port) );
+      vg_strcati64( &str, NETWORK_PORT, 10 );
    }
 
-   network_client.ip.m_port = atoi( network_client.host_port );
+   network_client.ip.m_port = atoi( network_client.port );
 }
 
 static void network_connect(void)
@@ -416,143 +396,100 @@ static void poll_remote_connection(void){
    }
 }
 
-struct resolve_info
+static void _network_resolve_numeric(void)
 {
-   enum resolve_opt
-   {
-      k_resolve_opt_resolve,
-      k_resolve_opt_parse_numeric,
-      k_resolve_opt_ipv6,
-      k_resolve_opt_fail
-   }
-   opt;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   SteamAPI_SteamNetworkingIPAddr_ParseString( &network_client.ip, network_client.adress );
+   network_client.ip.m_port = atoi( network_client.port );
+   network_client.resolve_state = k_resolve_state_resolved;
+}
 
-   union
-   {
-      struct
-      {
-         char port[8], adress[256];
-      }
-      host;
-      struct addrinfo *ipv6;
-   }
-   alias;
+struct network_resolved_info
+{
+   bool ok;
+   bool needs_numeric_conversion;
 };
-static void _network_resolve_host( vg_async_task *co_task )
+static void _network_resolve_complete( struct network_resolved_info *in_args, vg_async_info *async )
 {
-   if( co_task )
+   if( in_args->ok )
    {
-      struct resolve_info *co_info = (void *)co_task->data;
-      if( co_info->opt == k_resolve_opt_resolve )
-      {
-         THREAD_1;
+      if( in_args->needs_numeric_conversion )
+         _network_resolve_numeric();
+      network_client.resolve_state = k_resolve_state_resolved;
+   }
+   else
+      network_client.resolve_state = k_resolve_state_no;
+}
 
-         vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct resolve_info), 1 );
-         struct resolve_info *info = (void *)task->data;
-         vg_info( "Resolving host.. %s (:%s)\n", co_info->alias.host.adress, co_info->alias.host.port );
+static void _network_resolve_host_async( void *_, vg_async_info *async )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
-         /* Obtain address(es) matching host/port. */
+   /* Obtain address(es) matching host/port. */
+   struct addrinfo  hints;
+   memset( &hints, 0, sizeof(hints) );
+   hints.ai_family = AF_INET6;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
+   hints.ai_protocol = 0;
 
-         struct addrinfo  hints;
-         memset( &hints, 0, sizeof(hints) );
-         hints.ai_family = AF_INET6;
-         hints.ai_socktype = SOCK_DGRAM;
-         hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
-         hints.ai_protocol = 0;
+   bool ok = 0, needs_numeric_conversion = 0;
 
-         int s = getaddrinfo( co_info->alias.host.adress, co_info->alias.host.port, &hints, &info->alias.ipv6 );
-         if( s != 0 ) 
-         {
+   struct addrinfo *ipv6;
+   int s = getaddrinfo( network_client.adress, network_client.port, &hints, &ipv6 );
+   if( s != 0 ) 
+   {
 #ifndef _WIN32
-            vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
+      vg_error( "getaddrinfo: %s\n", gai_strerror(s) );
 #endif
-            if( !strcmp( co_info->alias.host.adress, "skaterift.com" ) )
-            {
-               vg_warn( "getaddrinfo failed for skaterift.com;\n "
-                        "falling back to a hardcoded IPv4. This might be wrong.\n" );
-
-               strcpy( info->alias.host.adress, "46.101.34.155" );
-               strcpy( info->alias.host.port, "27408" );
-               info->opt = k_resolve_opt_parse_numeric;
-               vg_async_task_dispatch( task, _network_resolve_host );
-               return;
-            }
-            else
-            {
-               info->opt = k_resolve_opt_fail;
-               vg_async_task_dispatch( task, _network_resolve_host );
-               return;
-            }
-         }
-         else
-         {
-            info->opt = k_resolve_opt_ipv6;
-            vg_async_task_dispatch( task, _network_resolve_host );
-            return;
-         }
-      }
-      else
+      if( !strcmp( network_client.adress, "skaterift.com" ) )
       {
-         THREAD_0;
+         vg_warn( "getaddrinfo failed for skaterift.com;\n "
+                  "falling back to a hardcoded IPv4. This might be wrong.\n" );
 
-         if( co_info->opt == k_resolve_opt_fail )
-         {
-            network_client.resolve_state = k_resolve_state_no;
-            return;
-         }
-         else if( co_info->opt == k_resolve_opt_ipv6 )
-         {
-            struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)co_info->alias.ipv6->ai_addr;
-            memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
-            freeaddrinfo( co_info->alias.ipv6 );
-            network_client.resolve_state = k_resolve_state_resolved;
-            return;
-         }
-         else if( co_info->opt == k_resolve_opt_parse_numeric )
-         {
-            strcpy( network_client.host_adress, co_info->alias.host.adress );
-            strcpy( network_client.host_port, co_info->alias.host.port );
-            goto parse_numeric;
-         }
+         strcpy( network_client.adress, "46.101.34.155" );
+         strcpy( network_client.port, "27408" );
+         ok = 1;
+         needs_numeric_conversion = 1;
       }
    }
    else
    {
-      THREAD_0;
-      if( (network_client.host_adress[0] >= '0') && (network_client.host_adress[0] <= '9') )
-         goto parse_numeric;
-      else
-      {
-         network_client.resolve_state = k_resolve_state_resolving;
-         vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct resolve_info), 1 );
-         struct resolve_info *info = (void *)task->data;
-         info->opt = k_resolve_opt_resolve;
-         strcpy( info->alias.host.port, network_client.host_port );
-         strcpy( info->alias.host.adress, network_client.host_adress );
-         vg_async_task_dispatch( task, _network_resolve_host );
-         return;
-      }
+      struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)ipv6->ai_addr;
+      memcpy( network_client.ip.m_ipv6, &inaddr->sin6_addr, 16 );
+      freeaddrinfo( ipv6 );
+      ok = 1;
    }
 
-   VG_ASSERT(0);
-parse_numeric:
+   struct network_resolved_info *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct network_resolved_info) );
+   out_args->ok = ok;
+   out_args->needs_numeric_conversion = needs_numeric_conversion;
+   _vg_async_send( out_args, (vg_async_fn)_network_resolve_complete );
+}
 
-   THREAD_0;
-   SteamAPI_SteamNetworkingIPAddr_ParseString( &network_client.ip, network_client.host_adress );
-   network_client.ip.m_port = atoi( network_client.host_port );
-   network_client.resolve_state = k_resolve_state_resolved;
+static void _network_resolve_host(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   VG_ASSERT( network_client.resolve_state == k_resolve_state_no );
+
+   if( (network_client.adress[0] >= '0') && (network_client.adress[0] <= '9') )
+      _network_resolve_numeric();
+   else
+   {
+      network_client.resolve_state = k_resolve_state_resolving;
+      _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_network_resolve_host_async );
+   }
 }
 
-void network_update(void)
+VG_API void _network_update(void)
 {
    if( _steam_api.disabled )
       return;
 
-   if( g_client.demo_mode )
+   if( _is_running_demo() )
       return;
 
    ESteamNetworkingConnectionState state = network_client.state;
-
    if( network_client.user_intent == k_server_intent_offline )
    {
       if( state != k_ESteamNetworkingConnectionState_None )
@@ -598,7 +535,7 @@ void network_update(void)
             return;
 
          if( network_client.resolve_state == k_resolve_state_no )
-            _network_resolve_host(NULL);
+            _network_resolve_host();
          else if( network_client.resolve_state == k_resolve_state_resolved )
             network_connect();
          
@@ -641,20 +578,14 @@ static int cmd_network_send_rcon( int argc, const char *argv[] )
    return 0;
 }
 
-void network_register(void)
+VG_API void _network_register(void)
 {
    vg_console_reg_var( "auto_connect", &network_client.auto_connect, k_var_dtype_i32, VG_VAR_PERSISTENT );
    vg_console_reg_cmd( "rcon", cmd_network_send_rcon, NULL );
 }
 
-void network_init(void)
+static void _network_end(void)
 {
-   _net_requests_init();
-}
-
-void network_end(void)
-{
-   /* TODO: Send buffered highscores that were not already */
    if( (network_client.state == k_ESteamNetworkingConnectionState_Connected) ||
        (network_client.state == k_ESteamNetworkingConnectionState_Connecting) )
    {
@@ -663,4 +594,9 @@ void network_end(void)
    }
 }
 
-#include "network_requests.c"
+VG_API void _network_init(void)
+{
+   _vg_add_exit_function( _network_end );
+   _net_requests_init();
+   render_server_status_gui();
+}
index 00d54f8c5fbd987d9494412fd6df752f8e20afd1..366862172cfa6fe3d5c2e8a2077b1ad9be42dc41 100644 (file)
@@ -1,16 +1,6 @@
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- * All trademarks are property of their respective owners
- */
-
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_mem_pool.h"
-#include "vg/vg_msg.h"
-#include "network_common.h"
-#include "network_msg.h"
-#include "addon_types.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/network.c"
+#else
 
 /* 
  * Interface
@@ -21,15 +11,9 @@ void on_server_connect_status( CallbackMsg_t *msg );
 void on_persona_state_change( CallbackMsg_t *msg );
 void request_auth_ticket(void);
 
-/* Call it at start; Connects us to the gameserver */
-void network_register(void);
-void network_init(void);
-
-/* Run this from main loop */
-void network_update(void);
-
-/* Call it at shutdown */
-void network_end(void);
+VG_API void _network_register(void);
+VG_API void _network_init(void);
+VG_API void _network_update(void);
 
 /* 
  * Can buffer up a bunch of these by calling many times, they will be
@@ -56,7 +40,7 @@ struct network_client
    i32 auto_connect;
 
    SteamNetworkingIPAddr ip;
-   char host_port[8], host_adress[256];
+   c8 port[8], adress[256];
 
    enum resolve_state
    {
@@ -94,3 +78,5 @@ static inline int network_connected(void)
 
 void cb_skaterift_connection_changed( SteamNetConnectionStatusChangedCallback_t *info );
 void cb_skaterift_persona_changed( PersonaStateChange_t *info );
+
+#endif
index 67c3e998c95066fe5d9d6930e7fe255ed777ef0d..4e2b921fb99a1bbaa302403f48babf2c5e8c7f7e 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_string.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_common.c"
+#else
 
 #define NETWORK_USERNAME_MAX 32
 #define NETWORK_MAX_PLAYERS 20
@@ -17,8 +17,6 @@
 #define NETWORK_PORT 27408
 #define NETWORK_PORT_STR(STR, X) STR #X
 
-#include "addon_types.h"
-
 static u32 network_msgstring( const char *src, u32 m_cbSize, u32 base_size, char *buf, u32 buf_size )
 {
    u32 string_len = VG_MIN( m_cbSize - base_size, buf_size );
@@ -37,3 +35,5 @@ static u32 network_pair_index( u32 _a, u32 _b )
 
    return ((N-a)*((N-a)-1))/2 - b + a;
 }
+
+#endif
index 8af4eac5b99d580a5ff39ef862aee37875667ba8..c5c1465d7c422110042834e160fc805d42a733e1 100644 (file)
@@ -1,8 +1,6 @@
-#ifndef NETWORK_COMPRESSION_H
-#define NETWORK_COMPRESSION_H
-
-#include "vg/vg_platform.h"
-#include "vg/vg_m.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_compression.c"
+#else
 
 typedef struct bitpack_ctx bitpack_ctx;
 struct bitpack_ctx {
@@ -116,4 +114,4 @@ static void bitpack_qquat( bitpack_ctx *ctx, v4f quat )
    }
 }
 
-#endif /* NETWORK_COMPRESSION_H */
+#endif
index d9cb3e39a27ca3652755b2b4d87895dad78a7ac0..e3267d89c5b54497e65c33a076e783b1730fc75c 100644 (file)
@@ -1,13 +1,6 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef NETWORK_MSG_H
-#define NETWORK_MSG_H
-
-#include "world_info.h"
-#include "vg/vg_platform.h"
-;
+#if defined( SR_IMPLEMENTATION )
+//# include "src/network_msg.c"
+#else
 
 #pragma pack(push,1)
 
index db32796d208bfaac9c5805152936f154c19b8685..772f02f325df2d2925f6aa03c1dd956cbbcef762 100644 (file)
@@ -1,5 +1,3 @@
-#include "network_requests.h"
-
 struct _net_requests _net_requests;
 
 const char *request_status_string( enum request_status status )
@@ -62,22 +60,13 @@ static void log_request_status( u16 request_id, const char *comment )
       vg_low( "req[%s%s##%hu" KWHT "] State: %s\n", colour, associated_username, request_id, request_state_str );
 }
 
-void network_send_request( netmsg_request *packet, vg_msg *body,
+void network_send_request( const c8 *body, u32 body_length,
                            void (*callback)( void *data, u32 data_size, u64 userdata, enum request_status status ),
                            u64 userdata )
 {
-   u32 len = 0;
-   if( body )
-   {
-      len = body->cur.co;
-      vg_msg_print( body, len );
-
-      if( body->error != k_vg_msg_error_OK )
-      {
-         vg_error( "Body not OK\n" );
-         return;
-      }
-   }
+   VG_ASSERT( body_length <= 512 );
+   netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
+   packet->inetmsg_id = k_inetmsg_request;
 
    if( callback )
    {
@@ -108,12 +97,14 @@ void network_send_request( netmsg_request *packet, vg_msg *body,
       packet->uid = 0;
 
    SteamAPI_ISteamNetworkingSockets_SendMessageToConnection( _steam_api.pSteamNetworkingSockets, network_client.remote, 
-                                                             packet, sizeof(netmsg_request)+len,
+                                                             packet, sizeof(netmsg_request) + body_length,
                                                              k_nSteamNetworkingSend_Reliable, NULL );
 }
 
 static void network_scoreboard_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
 {
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
    if( status == k_request_status_ok )
    {
       vg_msg msg;
@@ -126,6 +117,7 @@ static void network_scoreboard_callback( void *data, u32 data_size, u64 userdata
    }
    else
       world_routes_recv_scoreboard( &_world.main, NULL, userdata, status );
+#endif
 }
 
 /* mod_uid: world mod uid,
@@ -142,6 +134,8 @@ void network_request_scoreboard( const char *mod_uid, const char *route_uid, u32
    if( !network_connected() ) 
       return;
 
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
    netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
    packet->inetmsg_id = k_inetmsg_request;
 
@@ -152,6 +146,8 @@ void network_request_scoreboard( const char *mod_uid, const char *route_uid, u32
    vg_msg_wkvstr( &data, "route", route_uid );
    vg_msg_wkvnum( &data, "week", k_vg_msg_u32, 1, &week );
    network_send_request( packet, &data, network_scoreboard_callback, userdata );
+#endif
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
 }
 
 void network_publish_laptime( const char *mod_uid, const char *route_uid, f64 lap_time )
@@ -164,6 +160,8 @@ void network_publish_laptime( const char *mod_uid, const char *route_uid, f64 la
 
    i32 time_centiseconds = lap_time * 100.0;
 
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
    netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
    packet->inetmsg_id = k_inetmsg_request;
 
@@ -177,6 +175,8 @@ void network_publish_laptime( const char *mod_uid, const char *route_uid, f64 la
    f64 time_real = vg.time_real;
    vg_msg_wkvnum( &data, "end", k_vg_msg_f64, 1, &time_real );
    network_send_request( packet, &data, NULL, 0 );
+#endif
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
 }
 
 static void _delete_request( u16 request_id )
@@ -310,12 +310,12 @@ void _net_handle_response_message( SteamNetworkingMessage_t *msg )
       _net_requests_reset( "Defined server Error (Our end is ok)\n" );
 }
 
-void _net_requests_init(void)
+VG_API void _net_requests_init(void)
 {
    u32 alloc_size = sizeof(net_request)*NETWORK_MAX_REQUESTS;
-   _net_requests.transfer_buffer = vg_stack_allocate( &vg.rtmem, VG_MB(4), 8, "Request transfer data buffer" );
+   _net_requests.transfer_buffer = vg_malloc( VG_MB(4) );
    _net_requests.global_uid = time(NULL) ^ 0x35aa3203;
-   vg_pool_init( &_net_requests.pool, &_net_requests.inactive, NETWORK_MAX_REQUESTS, &vg.rtmem );
+   vg_pool_init( &_net_requests.pool, &_net_requests.inactive, NETWORK_MAX_REQUESTS, NULL );
 }
 
 void _net_requests_update(void)
index 7b4444b9c16c62b07f60ad5c7f61883052b15c9d..f9f61654e064312bb77b0099937826373e800d8b 100644 (file)
@@ -1,5 +1,6 @@
-#pragma once
-#include "network.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/network_requests.c"
+#else
 
 #define TRANSFER_TIMEOUT_SECONDS 5.0f
 #define NETWORK_MAX_REQUESTS 8
@@ -39,10 +40,14 @@ struct _net_requests
 }
 extern _net_requests;
 
-void network_send_request( netmsg_request *req, vg_msg *body,
+VG_API void _net_requests_init(void);
+
+const char *request_status_string( enum request_status status );
+void network_send_request( const c8 *body, u32 body_length,
                            void (*callback)( void *data, u32 data_size, u64 userdata, enum request_status status ),
                            u64 userdata );
 void _net_handle_response_message( SteamNetworkingMessage_t *msg );
-void _net_requests_init(void);
 void _net_requests_deleteall(void);
 void _net_requests_update(void);
+
+#endif
index 5b2539557e7a39c3e5ae4ff8120bad2d34106e79..d43673f8707d68f236de0f5b083064b0643b4574 100644 (file)
@@ -1,7 +1,3 @@
-#include "vg/vg_lines.h"
-#include "particle.h"
-#include "shaders/particle.h"
-
 struct particle_system particles_grind = {
    .scale = 0.02f,
    .velocity_scale = 0.001f,
@@ -13,6 +9,12 @@ particles_env = {
    .width = 0.25f
 };
 
+VG_API void _particles_init( void )
+{
+   particle_system_init( &particles_grind, 300, VG_STACK_USE_HEAP );
+   particle_system_init( &particles_env, 200, VG_STACK_USE_HEAP );
+}
+
 void particle_spawn( particle_system *sys, v3f co, v3f v, f32 lifetime, u32 colour )
 {
    if( sys->alive == sys->max ) 
@@ -70,7 +72,8 @@ iter: if( i == sys->alive ) return;
 
 void particle_system_debug( particle_system *sys )
 {
-   for( u32 i=0; i<sys->alive; i ++ ){
+   for( u32 i=0; i<sys->alive; i ++ )
+   {
       particle *p = &sys->array[i];
       v3f p1;
       v3_muladds( p->co, p->v, 0.2f, p1 );
@@ -78,27 +81,39 @@ void particle_system_debug( particle_system *sys )
    }
 }
 
-struct particle_init_args 
+VG_TIER_2 void particle_system_init( particle_system *sys, u32 max, vg_stack_allocator *stack )
 {
-   particle_system *sys;
-   u16 indices[];
-};
-static void particle_init_task( vg_async_task *task )
-{
-   struct particle_init_args *args = (void *)task->data;
-   particle_system *sys = args->sys;
-
-   glGenVertexArrays( 1, &sys->vao );
-   glGenBuffers( 1, &sys->vbo );
-   glGenBuffers( 1, &sys->ebo );
-   glBindVertexArray( sys->vao );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   u32 stride = sizeof(particle_vert);
 
-   size_t stride = sizeof(particle_vert);
+   sys->max = max;
+   sys->array = vg_stack_allocate( stack, max*sizeof(particle), 8, "Particle array" );
+   sys->vertices = vg_stack_allocate( stack, max*stride*4, 8, "Particle vertices" );
 
-   glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
-   glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
+   u32 temp_frame = _vg_start_temp_frame();
+   {
+      u16 *indices = vg_stack_allocate( _vg_temp_stack(), sizeof(u16) * max * 6, 8, "Temp indices" );
+      for( u32 i=0; i<max; i ++ )
+      {
+         indices[i*6+0] = i*4;
+         indices[i*6+1] = i*4+1;
+         indices[i*6+2] = i*4+2;
+         indices[i*6+3] = i*4;
+         indices[i*6+4] = i*4+2;
+         indices[i*6+5] = i*4+3;
+      }
+
+      glGenVertexArrays( 1, &sys->vao );
+      glGenBuffers( 1, &sys->vbo );
+      glGenBuffers( 1, &sys->ebo );
+      glBindVertexArray( sys->vao );
+
+      glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
+      glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
+      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
+      glBufferData( GL_ELEMENT_ARRAY_BUFFER, max*sizeof(u16)*6, indices, GL_STATIC_DRAW );
+   }
+   _vg_end_temp_frame( temp_frame );
 
    /* 0: coordinates */
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
@@ -109,30 +124,6 @@ static void particle_init_task( vg_async_task *task )
    glEnableVertexAttribArray( 1 );
 }
 
-void particle_alloc( particle_system *sys, u32 max )
-{
-   size_t stride = sizeof(particle_vert);
-
-   sys->max = max;
-   sys->array = vg_stack_allocate( &vg.rtmem, max*sizeof(particle), 8, "Particle array" );
-   sys->vertices = vg_stack_allocate( &vg.rtmem, max*stride*4, 8, "Particle vertices" );
-
-   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(particle_system *) + max*sizeof(u16)*6, 1 );
-   struct particle_init_args *init = (void *)task->data;
-   init->sys = sys;
-
-   for( u32 i=0; i<max; i ++ )
-   {
-      init->indices[i*6+0] = i*4;
-      init->indices[i*6+1] = i*4+1;
-      init->indices[i*6+2] = i*4+2;
-      init->indices[i*6+3] = i*4;
-      init->indices[i*6+4] = i*4+2;
-      init->indices[i*6+5] = i*4+3;
-   }
-   vg_async_task_dispatch( task, particle_init_task );
-}
-
 void particle_system_prerender( particle_system *sys )
 {
    for( u32 i=0; i<sys->alive; i ++ ){
index 6858890522fa7f5d183a632759e8f09498f4e699..85d90d1002a8ae34397a62afa99d7bbcdef42b4a 100644 (file)
@@ -1,5 +1,6 @@
-#pragma once
-#include "skaterift.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/particle.c"
+#else
 
 typedef struct particle_system particle_system;
 typedef struct particle particle;
@@ -29,14 +30,14 @@ struct particle_system {
 }
 extern particles_grind, particles_env;
 
-void particle_alloc( particle_system *sys, u32 max );
+VG_API void _particles_init( void );
+VG_TIER_2 void particle_system_init( particle_system *sys, u32 max, vg_stack_allocator *stack );
+
 void particle_system_update( particle_system *sys, f32 dt );
 void particle_system_debug( particle_system *sys );
 void particle_system_prerender( particle_system *sys );
 void particle_system_render( particle_system *sys, vg_camera *cam );
 
-void particle_spawn( particle_system *sys, 
-                     v3f co, v3f v, f32 lifetime, u32 colour );
-void particle_spawn_cone( particle_system *sys, 
-                          v3f co, v3f dir, f32 angle, f32 speed, 
-                          f32 lifetime, u32 colour );
+void particle_spawn( particle_system *sys, v3f co, v3f v, f32 lifetime, u32 colour );
+void particle_spawn_cone( particle_system *sys, v3f co, v3f dir, f32 angle, f32 speed, f32 lifetime, u32 colour );
+#endif
diff --git a/src/physics_test.h b/src/physics_test.h
deleted file mode 100644 (file)
index 243de36..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef PHYSICS_TEST_H
-#define PHYSICS_TEST_H
-
-#include "rigidbody.h"
-#include "player.h"
-
-rigidbody ground = { .type = k_rb_shape_box,
-                     .bbx = {{-100.0f,-1.0f,-100.0f},{100.0f,0.0f,100.0f}},
-                     .co = {0.0f, 0.0f, 0.0f},
-                     .q = {0.0f,0.0f,0.0f,1.0f},
-                     .is_world = 1 };
-
-rigidbody blocky = 
-   {
-      .type = k_rb_shape_box,
-      .bbx = {{-2.0f,-1.0f,-3.0f},{2.0f,1.0f,2.0f}},
-      .co = {30.0f,2.0f,30.0f},
-      .q = {0.0f,0.0f,0.0f,1.0f},
-      .is_world = 1
-   };
-
-rigidbody marko = 
-{
-   .type = k_rb_shape_box,
-   .bbx = {{-0.5f,-0.5f,-0.5f},{0.5f,0.5f,0.5f}},
-   .co = {-36.0f,8.0f,-36.0f},
-   .q = {0.0f,0.0f,0.0f,1.0f},
-   .is_world = 0
-};
-
-scene epic_scene;
-
-rigidbody epic_scene_rb = 
-{
-   .type = k_rb_shape_scene,
-   .co = {0.0f,0.0f,0.0f},
-   .q = {0.0f,0.0f,0.0f,1.0f},
-   .is_world = 1,
-   .inf.scene = { .pscene = &epic_scene }
-};
-
-rigidbody funnel[4] = {
-   {
-      .type = k_rb_shape_box,
-      .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
-      .co = {-10.0f,5.0f,0.0f},
-      .is_world = 1
-   },
-   {
-      .type = k_rb_shape_box,
-      .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
-      .co = { 10.0f,5.0f,0.0f},
-      .is_world = 1
-   },
-   {
-      .type = k_rb_shape_box,
-      .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
-      .co = { 0.0f,5.0f,10.0f},
-      .is_world = 1
-   },
-   {
-      .type = k_rb_shape_box,
-      .bbx = {{-20.0f,-1.0f,-20.0f},{20.0f,1.0f,20.0f}},
-      .co = {0.0f,5.0f,-10.0f},
-      .is_world = 1
-   }
-};
-
-rigidbody jeff1 = { .type = k_rb_shape_capsule,
-                    .inf.capsule = { .radius = 0.75f, .height = 3.0f },
-                    .co = {30.0f, 4.0f, 30.0f },
-                    .q = {1.0f,0.0f,0.0f,0.0f}
-};
-
-rigidbody ball = { .type = k_rb_shape_sphere,
-                   .inf.sphere = { .radius = 2.0f },
-                   .co = {0.0f,20.0f,2.0f},
-                   .q = {0.0f,0.0f,0.0f,1.0f}},
-
-          ball1= { .type = k_rb_shape_sphere,
-                   .inf.sphere = { .radius = 2.0f },
-                   .co = {0.1f,25.0f,0.2f},
-                   .q = {0.0f,0.0f,0.0f,1.0f}};
-
-rigidbody jeffs[16];
-
-static void reorg_jeffs(void)
-{
-   for( int i=0; i<vg_list_size(jeffs); i++ )
-   {
-      v3_copy( (v3f){ (vg_randf()-0.5f) * 10.0f,
-                      (vg_randf()-0.5f) * 10.0f + 17.0f,
-                      (vg_randf()-0.5f) * 10.0f }, jeffs[i].co );
-      v4_copy( (v4f){ vg_randf(), vg_randf(), vg_randf(), vg_randf() },
-               jeffs[i].q );
-      q_normalize( jeffs[i].q );
-      
-      jeffs[i].type = k_rb_shape_capsule;
-      jeffs[i].inf.capsule.radius = 0.75f;
-      jeffs[i].inf.capsule.height = 3.0f;
-
-      rb_init( &jeffs[i] );
-   }
-}
-
-static void physics_test_start(void)
-{
-   q_axis_angle( funnel[0].q, (v3f){1.0f,0.0f,0.0f},  0.6f );
-   q_axis_angle( funnel[1].q, (v3f){1.0f,0.0f,0.0f}, -0.6f );
-   q_axis_angle( funnel[2].q, (v3f){0.0f,0.0f,1.0f},  0.6f );
-   q_axis_angle( funnel[3].q, (v3f){0.0f,0.0f,1.0f}, -0.6f );
-
-   for( int i=0; i<4; i++ )
-      rb_init( &funnel[i] );
-
-   reorg_jeffs();
-
-   rb_init( &ground );
-   rb_init( &ball );
-   rb_init( &ball1 );
-   rb_init( &jeff1 );
-   rb_init( &blocky );
-
-   scene_init( &epic_scene );
-
-   mdl_header *mdl = mdl_load( "models/epic_scene.mdl" );
-
-   m4x3f transform;
-   m4x3_identity( transform );
-
-   for( int i=0; i<mdl->node_count; i++ )
-   {
-      mdl_node *pnode = mdl_node_from_id( mdl, i );
-
-      for( int j=0; j<pnode->submesh_count; j++ )
-      {
-         mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j );
-         scene_add_submesh( &epic_scene, mdl, sm, transform );
-      }
-   }
-
-   vg_free( mdl );
-   scene_bh_create( &epic_scene );
-
-   rb_init( &epic_scene_rb );
-   rb_init( &marko );
-}
-
-static void physics_test_update(void)
-{
-   player_freecam();
-   player_camera_update();
-
-   for( int i=0; i<4; i++ )
-      rb_debug( &funnel[i], 0xff0060e0 );
-   rb_debug( &ground, 0xff00ff00 );
-   rb_debug( &ball, 0xffe00040 );
-   rb_debug( &ball1, 0xff00e050 );
-
-   rb_debug( &blocky, 0xffcccccc );
-   rb_debug( &jeff1, 0xff00ffff );
-
-   rb_debug( &epic_scene_rb, 0xffcccccc );
-   rb_debug( &marko, 0xffffcc00 );
-
-   {
-
-   rb_solver_reset();
-
-   for( int i=0; i<4; i++ )
-   {
-      rigidbody *fn = &funnel[i];
-      rb_collide( &ball, fn );
-      rb_collide( &ball1, fn );
-      rb_collide( &jeff1, fn );
-
-      for( int i=0; i<vg_list_size(jeffs); i++ )
-         rb_collide( jeffs+i, fn );
-   }
-
-   for( int i=0; i<vg_list_size(jeffs)-1; i++ )
-   {
-      for( int j=i+1; j<vg_list_size(jeffs); j++ )
-      {
-         rb_collide( jeffs+i, jeffs+j );
-      }
-   }
-
-   for( int i=0; i<vg_list_size(jeffs); i++ )
-   {
-      rb_collide( jeffs+i, &ground );
-      rb_collide( jeffs+i, &ball );
-      rb_collide( jeffs+i, &ball1 );
-      rb_collide( jeffs+i, &jeff1 );
-   }
-
-   rb_collide( &jeff1, &ground );
-   rb_collide( &jeff1, &blocky );
-   rb_collide( &jeff1, &ball );
-   rb_collide( &jeff1, &ball1 );
-
-   rb_collide( &ball, &ground );
-   rb_collide( &ball1, &ground );
-   rb_collide( &ball1, &ball );
-   rb_collide( &marko, &epic_scene_rb );
-
-   rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
-   for( int i=0; i<8; i++ )
-      rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-
-
-   /* ITERATE */
-   {
-   for( int i=0; i<vg_list_size(jeffs); i++ )
-   {
-      rb_debug( &jeffs[i], (u32[]){ 0xff0000ff, 0xff00ff00, 0xff00ffff,
-                                   0xffff0000, 0xffff00ff, 0xffffff00,
-                                   }[i%6] );
-      rb_iter( jeffs+i );
-   }
-
-   rb_iter( &ball );
-   rb_iter( &ball1 );
-   rb_iter( &jeff1 );
-   rb_iter( &marko );
-   }
-   
-   /* POSITION OVERRIDE */
-   {
-   if(glfwGetKey( vg.window, GLFW_KEY_L ))
-   {
-      m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, marko.co );
-      v3_zero( marko.v );
-      v3_zero( marko.w );
-   }
-   if(glfwGetKey( vg.window, GLFW_KEY_K ))
-   {
-      m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, ball.co );
-      v3_zero( ball.v );
-      v3_zero( ball.w );
-   }
-   if(glfwGetKey( vg.window, GLFW_KEY_J ))
-   {
-      m4x3_mulv( player.camera, (v3f){0.0f,0.0f,-5.0f}, ball1.co );
-      v3_zero( ball1.v );
-      v3_zero( ball1.w );
-   }
-
-   if(glfwGetKey( vg.window, GLFW_KEY_H ))
-   {
-      reorg_jeffs();
-   }
-   }
-   
-   /* UPDATE TRANSFORMS */
-   for( int i=0; i<vg_list_size(jeffs); i++ )
-   {
-      rb_update_transform(jeffs+i);
-   }
-
-   rb_update_transform( &ball );
-   rb_update_transform( &ball1 );
-   rb_update_transform( &jeff1 );
-   rb_update_transform( &marko );
-
-   }
-}
-
-static void physics_test_render(void)
-{
-   m4x4f world_4x4;
-   m4x3_expand( player.camera_inverse, world_4x4 );
-
-   gpipeline.fov = 60.0f;
-   m4x4_projection( vg_pv, gpipeline.fov, 
-         (float)vg_window_x / (float)vg_window_y, 
-         0.1f, 2100.0f );
-
-   m4x4_mul( vg_pv, world_4x4, vg_pv );
-   glEnable( GL_DEPTH_TEST );
-
-   glDisable( GL_DEPTH_TEST );
-   vg_lines_drawall( (float *)vg_pv );
-}
-
-#endif /* PHYSICS_TEST_H */
index f706eefebb17a8543fb025b2c0099c0fd60da969..41cd904dc059fbad9d078532635a654e84624be6 100644 (file)
@@ -1,25 +1,3 @@
-#include "player.h"
-#include "addon.h"
-#include "player_model.h"
-#include "input.h"
-#include "world.h"
-#include "audio.h"
-#include "network.h"
-#include "network_common.h"
-#include "world_routes.h"
-#include "gui.h"
-
-#include "shaders/model_entity.h"
-#include "shaders/model_character_view.h"
-#include "shaders/model_board_view.h"
-
-#include "player_walk.h"
-#include "player_dead.h"
-#include "player_skate.h"
-#include "player_basic_info.h"
-#include "player_glide.h"
-#include <string.h>
-
 i32 k_invert_y = 0;
 struct localplayer localplayer = 
 {
@@ -63,7 +41,7 @@ int localplayer_cmd_respawn( int argc, const char *argv[] )
    return 1;
 }
 
-void player_register(void)
+VG_API void _player_register(void)
 {
    vg_console_reg_var( "player_battery", &localplayer.has_battery, k_var_dtype_i32, 0 );
    vg_console_reg_cmd( "respawn", localplayer_cmd_respawn, NULL );
@@ -88,15 +66,6 @@ void player_register(void)
    }
 }
 
-void player_init(void)
-{
-   mdl_context *mdl = &localplayer.battery;
-   mdl_open( mdl, "models/battery.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
-   mdl_async_full_load_std( mdl, NULL );
-   mdl_close( mdl );
-}
-
 void player__debugtext( ui_context *ctx, int size, const char *fmt, ... )
 {
        char buffer[ 1024 ];
@@ -120,13 +89,13 @@ void player__use_model( addon_id addon_id )
    localplayer.playermodel.cache_slot = addon_cache_create_viewer( k_addon_type_player, addon_id );
 }
 
-void player__bind(void)
+VG_API void _player_init(void)
 {
    for( u32 i=0; i<k_player_subsystem_max; i++ )
    {
       struct player_subsystem_interface *sys = player_subsystems[i];
-      if( sys && sys->bind ) 
-         sys->bind();
+      if( sys && sys->init )
+         sys->init();
    }
 }
 
@@ -158,7 +127,7 @@ void player__update(void)
       glider_physics( (v2f){0,0} );
    
    
-   if( localplayer.rb.co[1] < _world.main.scene_geo.bbx[0][1] - 40.0f )
+   if( localplayer.rb.co[1] < _world.main.scene_geometry.bbx[0][1] - 40.0f )
    {
       ent_spawn *rp = world_find_closest_spawn( &_world.main, localplayer.rb.co );
       if( rp )
@@ -225,7 +194,8 @@ void player__pass_gate( u32 id )
       _world.copy_of_nonlocal_sender.key = 0;
       _world.copy_of_nonlocal_sender.submesh_start = 0;
       _world.copy_of_nonlocal_sender.submesh_count = 0;
-      vg_strncpy( af_str( &world->meta.af, gate->key ), _world.nonlocal_destination_key, 32, k_strncpy_overflow_fatal );
+      vg_strncpy( af_str( world->meta.packed_strings, gate->key ), _world.nonlocal_destination_key, 
+                  32, k_strncpy_overflow_fatal );
       player__clean_refs();
       skaterift_load_world_start( gate->remote_addon_id, 0 );
       return;
@@ -265,8 +235,8 @@ void player_apply_transport_to_cam( m4x3f transport )
 
    /* we want the regular transform here no the inversion */
    m4x3_expand( transport, transport_4 );
-   m4x4_mul( world_gates.cam.mtx.pv, transport_4, world_gates.cam.mtx.pv );
-   m4x4_mul( world_gates.cam.mtx.v,  transport_4, world_gates.cam.mtx.v );
+   m4x4_mul( _world_gates.cam.mtx.pv, transport_4, _world_gates.cam.mtx.pv );
+   m4x4_mul( _world_gates.cam.mtx.v,  transport_4, _world_gates.cam.mtx.v );
 }
 
 void player__im_gui( ui_context *ctx )
@@ -274,10 +244,10 @@ void player__im_gui( ui_context *ctx )
    if( !k_player_debug_info ) return;
 
    ui_rect box = {
-      vg.window_x - 300,
+      _vg_window.w - 300,
       0, 
       300,
-      vg.window_y
+      _vg_window.h
    };
 
    ui_fill( ctx, box, (ui_colour(ctx, k_ui_bg)&0x00ffffff)|0x50000000 );
@@ -314,7 +284,8 @@ void player__im_gui( ui_context *ctx )
    player__debugtext( ctx, 1, "time_rate: %.4f", skaterift.time_rate );
 
    player__debugtext( ctx, 2, "player" );
-   player__debugtext( ctx, 1, "angles: " PRINTF_v3f( localplayer.cam.angles ) );
+   player__debugtext( ctx, 1, "angles: %.2f %.2f %.2f", 
+            localplayer.cam.angles[0],localplayer.cam.angles[1],localplayer.cam.angles[2] );
 
    if( player_subsystems[ localplayer.subsystem ]->im_gui )
       player_subsystems[ localplayer.subsystem ]->im_gui( ctx );
@@ -332,7 +303,7 @@ void player__setpos( v3f pos )
 
 void player__clean_refs(void)
 {
-   gui_helper_reset( k_gui_helper_mode_clear );
+   _gui_helper_reset( k_gui_helper_mode_clear );
 
    _world.challenge_target = NULL;
    _world.challenge_timer = 0.0f;
index c4ed1d3b4a245329e479b9f942aaf42c6f82bf70..a89e97e51e550a923c021c5fff4a558e8074074d 100644 (file)
@@ -1,37 +1,12 @@
-#pragma once
-#include "vg/vg_platform.h"
-
-struct player_cam_controller {
-   enum camera_mode{
-      k_cam_firstperson = 1,
-      k_cam_thirdperson = 0
-   }
-   camera_mode;
-   f32 camera_type_blend;
-
-   v3f fpv_offset,         /* expressed relative to rigidbody */
-       tpv_offset,
-       tpv_offset_extra,
-       fpv_viewpoint,      /* expressed relative to neck bone inverse final*/
-       fpv_offset_smooth,
-       fpv_viewpoint_smooth,
-       tpv_offset_smooth,
-       tpv_lpf,
-       cam_velocity_smooth;
-};
-
-#include "player_common.h"
-#include "network_compression.h"
-#include "player_effects.h"
-#include "player_api.h"
-#include "player_ragdoll.h"
-#include "player_model.h"
-#include "player_render.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player.c"
+#else
 
 struct player_subsystem_interface
 {
    void(*system_register)(void);
-   void(*bind)(void);
+   void(*init)(void);
+   void(*load_resources)(void);
    void(*pre_update)(void);
    void(*update)(void);
    void(*post_update)(void);
@@ -136,10 +111,10 @@ struct localplayer
    /*
     * Rendering
     */
-   mdl_context skeleton_meta;
-   mdl_context battery;
-   ms_context animations;
-   struct skeleton skeleton;
+   vg_model skeleton_meta;
+   vg_model battery;
+   metascene animations;
+   ms_skeleton skeleton;
    i32 has_battery;
 
    u8 id_hip,
@@ -173,10 +148,10 @@ extern struct player_subsystem_interface *player_subsystems[];
  * ---------------------------------------------------------
  */
 
-void player_register(void);
-void player_init(void);
+VG_API void _player_init(void);
+VG_API void _player_register(void);
+
 void player__debugtext( ui_context *ctx, int size, const char *fmt, ... );
-void player__use_mesh( glmesh *mesh );
 void player__use_model( u16 reg_id );
 
 void player__bind(void);
@@ -196,12 +171,13 @@ void player__reset(void);
 void player__kill(void);
 void player__begin_holdout( v3f offset );
 
-void player_get_anim( skeleton_anim *out_anim, const char *name );
+void player_get_anim( ms_skeletal_animation *out_anim, const char *name );
 int localplayer_cmd_respawn( int argc, const char *argv[] );
 void player_apply_transport_to_cam( m4x3f transport );
 
 void player__clear_sfx_buffer(void);
-void player__networked_sfx( u8 system, u8 priority, u8 id, 
-                            v3f pos, f32 volume );
+void player__networked_sfx( u8 system, u8 priority, u8 id, v3f pos, f32 volume );
 void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx );
 void net_sfx_play( struct net_sfx *sfx );
+
+#endif
index cd8a477b7c29907e74d3819a029e43e21bf637a2..7ee07bece5469744e3d5ea8cb41386ab53036afb 100644 (file)
@@ -1,12 +1,35 @@
-#pragma once
-#include "model.h"
-#include "metascene.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/player_api.c"
+#else
 
 typedef struct player_instance player_instance;
 typedef struct player_pose player_pose;
 
-struct player_pose{
-   enum player_pose_type {
+struct player_cam_controller 
+{
+   enum camera_mode
+   {
+      k_cam_firstperson = 1,
+      k_cam_thirdperson = 0
+   }
+   camera_mode;
+   f32 camera_type_blend;
+
+   v3f fpv_offset,         /* expressed relative to rigidbody */
+       tpv_offset,
+       tpv_offset_extra,
+       fpv_viewpoint,      /* expressed relative to neck bone inverse final*/
+       fpv_offset_smooth,
+       fpv_viewpoint_smooth,
+       tpv_offset_smooth,
+       tpv_lpf,
+       cam_velocity_smooth;
+};
+
+struct player_pose
+{
+   enum player_pose_type 
+   {
       k_player_pose_type_ik,      /* regular IK animation */
       k_player_pose_type_fk_2,
    }
@@ -17,13 +40,15 @@ struct player_pose{
 
    ms_keyframe keyframes[32];
 
-   struct player_board_pose {
+   struct player_board_pose 
+   {
       f32 lean;
    }
    board;
 };
 
-enum player_subsystem{
+enum player_subsystem
+{
    k_player_subsystem_walk = 0,
    k_player_subsystem_skate = 1,
    k_player_subsystem_dead = 2,
@@ -33,3 +58,13 @@ enum player_subsystem{
    k_player_subsystem_max,
    k_player_subsystem_invalid = 255
 };
+
+enum player_die_type 
+{
+   k_player_die_type_generic,
+   k_player_die_type_head,
+   k_player_die_type_feet,
+   k_player_die_type_water
+};
+
+#endif
index ffc7ae0f83ad0cafac580fe03dcd6e7bf86323c0..78689c6e3c4218b9e460f482f218bdab2f1538c8 100644 (file)
@@ -1,6 +1,3 @@
-#include "player_basic_info.h"
-#include "network_compression.h"
-
 struct player_basic_info player_basic_info;
 struct player_subsystem_interface player_subsystem_basic_info = 
 {
index 815be672e0499f8ca9fff3e3729420ab1d2a3209..a49bc26d6e23575cbc7093e800be1641d3249fb5 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_basic_info.c"
+#else
 
 struct player_basic_info 
 {
@@ -16,3 +16,4 @@ extern struct player_subsystem_interface player_subsystem_basic_info;
 void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data);
 void player__basic_info_pose( void *_animator, player_pose *pose );
 
+#endif
index 3f1b66d93482dd089d3431d00ed3d3e48b544999..1fa2fee7efeb3079d3d55095153eebc531fc2de2 100644 (file)
@@ -1,9 +1,3 @@
-#include "ent_skateshop.h"
-#include "player.h"
-#include "input.h"
-#include "menu.h"
-#include "vg/vg_perlin.h"
-
 float player_get_heading_yaw(void)
 {
    v3f xz;
index b32faee6fc6fd1e778e236cb980313c63f1ddaa7..1cbee97560bc1918307cd155d3bf9cdbc1da7708 100644 (file)
@@ -1,5 +1,6 @@
-#pragma once
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_common.c"
+#else
 
 static float
    k_cam_spring            =  20.0f,
@@ -14,3 +15,6 @@ static ui_rect g_player_debugger;
 void player_look( v3f angles, float speed );
 void player__cam_iterate(void);
 f32 player_get_heading_yaw(void);
+void compute_cam_controller_offsets( enum player_subsystem system, struct player_cam_controller *cc );
+
+#endif
index 69418b9b5ebb8244dbf44e9fccd4418953d9470f..8057427bb5583a8cb1dbbb75166bbcf1e22ff432 100644 (file)
@@ -1,7 +1,3 @@
-#include "skaterift.h"
-#include "player_dead.h"
-#include "gui.h"
-
 struct player_dead player_dead;
 struct player_subsystem_interface player_subsystem_dead = {
    .update = player__dead_update,
@@ -10,7 +6,7 @@ struct player_subsystem_interface player_subsystem_dead = {
    .pose = player__dead_pose,
    .post_animate = player__dead_post_animate,
    .im_gui = player__dead_im_gui,
-   .bind = player__dead_bind,
+   .load_resources = player__dead_load_resources,
 
    .animator_data = &player_dead.animator,
    .animator_size = sizeof(player_dead.animator),
@@ -76,7 +72,7 @@ void player__dead_post_update(void)
             }
          }
 
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
       }
    }
    else
@@ -90,7 +86,7 @@ void player__dead_post_update(void)
          {
             localplayer_cmd_respawn(0,NULL);
             srinput.state = k_input_state_resume;
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
    }
@@ -101,7 +97,7 @@ void player__dead_animate(void)
    struct player_dead *d = &player_dead;
    struct player_dead_animator *animator = &d->animator;
    struct player_ragdoll *rd = &localplayer.ragdoll;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    m4x3f transforms[ 32 ];
 
@@ -136,7 +132,7 @@ void player__dead_animate(void)
    /* bones without colliders transforms */
    for( u32 i=1; i<sk->bone_count; i++ )
    {
-      struct skeleton_bone *sb = &sk->bones[i];
+      ms_skeleton_bone *sb = &sk->bones[i];
 
       if( sb->parent && !sb->collider )
       {
@@ -155,7 +151,7 @@ void player__dead_animate(void)
    /* measurements */
    for( u32 i=1; i<sk->bone_count; i++ )
    {
-      struct skeleton_bone *sb = &sk->bones[i];
+      ms_skeleton_bone *sb = &sk->bones[i];
 
       v3_zero( animator->transforms[i].co );
       q_identity( animator->transforms[i].q );
@@ -176,7 +172,7 @@ void player__dead_pose( void *_animator, player_pose *pose )
 {
    struct player_dead_animator *animator = _animator;
    struct player_ragdoll *rd = &localplayer.ragdoll;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    pose->type = k_player_pose_type_fk_2;
    pose->board.lean = 0.0f;
@@ -210,7 +206,6 @@ void player__dead_transition( enum player_die_type type )
       return;
 
    localplayer.fell_since_last_gate = 1;
-
    localplayer.subsystem = k_player_subsystem_dead;
    copy_localplayer_to_ragdoll( &localplayer.ragdoll, type );
 
@@ -218,23 +213,18 @@ void player__dead_transition( enum player_die_type type )
    v3_copy( part->rb.co, player_dead.co_lpf );
    v3_copy( part->rb.v,  player_dead.v_lpf );
    v3_copy( part->rb.w,  player_dead.w_lpf );
-
-   gui_helper_reset( k_gui_helper_mode_black_bars );
+   _gui_helper_reset( k_gui_helper_mode_black_bars );
 
    vg_str str;
-   if( (player_dead.helper_getup = gui_new_helper(input_button_list[k_srbind_skate], &str) ))
+   if( (player_dead.helper_getup = _gui_new_helper(input_button_list[k_srbind_skate], &str) ))
    {
       vg_strcat( &str, "Get Up" );
-
       if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
       {
          vg_strcat( &str, " (Exit challenge)" );
-
          struct gui_helper *helper;
-         if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
-         {
+         if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
             vg_strcat( &str, "Retry" );
-         }
       }
 
       player_dead.helper_getup->greyed = 1;
@@ -244,7 +234,6 @@ void player__dead_transition( enum player_die_type type )
 void player__dead_animator_exchange( bitpack_ctx *ctx, void *data )
 {
    struct player_dead_animator *animator = data;
-
    for( u32 i=0; i<localplayer.skeleton.bone_count; i ++ )
    {
       bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->transforms[i].co );
@@ -252,8 +241,8 @@ void player__dead_animator_exchange( bitpack_ctx *ctx, void *data )
    }
 }
 
-void player__dead_bind(void)
+void player__dead_load_resources(void)
 {
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    player_get_anim( &player_dead.anim_bail, "pose_bail_ball" );
 }
index 30d9a72495e85554457dab7b0c3de331d79b3f1d..b4518fa3f984b39c9f8bc1dbe4c3e41397a7c07b 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_dead.c"
+#else
 
 struct player_dead
 {
@@ -15,7 +15,7 @@ struct player_dead
    }
    animator;
 
-   skeleton_anim anim_bail;
+   ms_skeletal_animation anim_bail;
    struct gui_helper *helper_getup;
 }
 extern player_dead;
@@ -27,7 +27,8 @@ void player__dead_animate     (void);
 void player__dead_pose        (void *animator, player_pose *pose);
 void player__dead_post_animate(void);
 void player__dead_im_gui      ( ui_context *ctx );
-void player__dead_bind        (void);
+void player__dead_load_resources(void);
 void player__dead_transition  ( enum player_die_type type );
 void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
 
+#endif
diff --git a/src/player_drive.c b/src/player_drive.c
deleted file mode 100644 (file)
index e55a668..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "player_drive.h"
-#include "input.h"
-
-struct player_drive player_drive;
-struct player_subsystem_interface player_subsystem_drive = 
-{
-   .pre_update = player__drive_pre_update,
-   .update = player__drive_update,
-   .post_update = player__drive_post_update,
-   .animate = player__drive_animate,
-   .pose = player__drive_pose,
-   .post_animate = player__drive_post_animate,
-   .im_gui = player__drive_im_gui,
-   .bind = player__drive_bind,
-
-   .animator_data = NULL,
-   .animator_size = 0,
-   .name = "Drive"
-};
-
-void player__drive_pre_update(void)
-{
-   drivable_vehicle *vehc = player_drive.vehicle;
-
-   v2f steer;
-   joystick_state( k_srjoystick_steer, steer );
-
-   vehc->steer = vg_lerpf( vehc->steer, steer[0] * 0.4f, 
-                           vg.time_fixed_delta * 8.0f );
-   vehc->drive = steer[1];
-}
-
-void player__drive_update(void){}
-
-void player__drive_post_update(void)
-{
-   v3_copy( player_drive.vehicle->rb.co,localplayer.rb.co );
-   v3_copy( player_drive.vehicle->rb.v, localplayer.rb.v );
-   v4_copy( player_drive.vehicle->rb.q, localplayer.rb.q );
-   v3_copy( player_drive.vehicle->rb.w, localplayer.rb.w );
-}
-
-void player__drive_animate(void){}
-
-void player__drive_pose( void *animator, player_pose *pose )
-{
-   struct skeleton *sk = &localplayer.skeleton;
-
-   skeleton_sample_anim( sk, &player_drive.anim_drive, 0.0f, pose->keyframes );
-   v3_copy( localplayer.rb.co, pose->root_co );
-   v4_copy( localplayer.rb.q, pose->root_q );
-}
-
-void player__drive_post_animate(void)
-{
-   if( localplayer.cam_control.camera_mode == k_cam_firstperson )
-      localplayer.cam_velocity_influence = 0.0f;
-   else
-      localplayer.cam_velocity_influence = 1.0f;
-
-   rigidbody *rb = &gzoomer.rb;
-   float yaw = atan2f( -rb->to_world[2][0], rb->to_world[2][2] ),
-       pitch = atan2f
-               ( 
-                   -rb->to_world[2][1], 
-                   sqrtf
-                   (
-                     rb->to_world[2][0]*rb->to_world[2][0] + 
-                     rb->to_world[2][2]*rb->to_world[2][2]
-                   )
-               );
-
-   localplayer.angles[0] = yaw;
-   localplayer.angles[1] = pitch;
-}
-
-void player__drive_im_gui( ui_context *ctx )
-{
-   player__debugtext( ctx, 1, "Nothing here" );
-}
-
-void player__drive_bind(void)
-{
-   struct skeleton *sk = &localplayer.skeleton;
-   player_drive.vehicle = &gzoomer;
-   player_get_anim( &player_drive.anim_drive, "idle_cycle+y" );
-}
diff --git a/src/player_drive.h b/src/player_drive.h
deleted file mode 100644 (file)
index 772a0d3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-#include "player.h"
-#include "vehicle.h"
-
-struct player_drive 
-{
-   drivable_vehicle *vehicle;
-   skeleton_anim anim_drive;
-}
-extern player_drive;
-extern struct player_subsystem_interface player_subsystem_drive;
-
-void player__drive_pre_update(void);
-void player__drive_update(void);
-void player__drive_post_update(void);
-void player__drive_animate(void);
-void player__drive_pose( void *animator, player_pose *pose );
-
-void player__drive_post_animate(void);
-void player__drive_im_gui( ui_context *ctx );
-void player__drive_bind(void);
index 981c23218d905c52bd5fd680353ff9c812755788..b3c2f1082e1e1c7bcc85cfdee63d33aee4566a09 100644 (file)
@@ -1,8 +1,3 @@
-#include "player.h"
-#include "player_effects.h"
-#include "player_render.h"
-#include "particle.h"
-
 void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt )
 {
    if( ef->t < 0.0f ){
index f148dbc3f7a2c31649e9c622082809a378cca772..bd5d1dd5cfc535448cf8622bc0ffd3093fd94b18 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "vg/vg_platform.h"
-#include "player_render.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_effects.c"
+#else
 
 typedef struct effect_blink effect_blink;
 typedef struct effect_spark effect_spark;
@@ -24,3 +24,5 @@ struct player_effects_data
    effect_blink blink;
    effect_spark spark, sand;
 };
+
+#endif
index 2063040e1cb131bbac3f4681a604d34a5a82f603..e6e2176700e1557ec82d8dcd4a1015cf456b89b9 100644 (file)
@@ -1,14 +1,3 @@
-#include "player_glide.h"
-#include "vg/vg_rigidbody.h"
-#include "scene_rigidbody.h"
-#include "shaders/model_board_view.h"
-#include "shaders/model_entity.h"
-#include "input.h"
-#include "skaterift.h"
-
-#include "player_dead.h"
-#include "player_skate.h"
-
 trail_system trails_glider[] = {
    {
       .width = 0.035f,
@@ -63,7 +52,8 @@ struct player_subsystem_interface player_subsystem_glide =
    .post_animate = player_glide_post_animate,
    .network_animator_exchange = player_glide_animator_exchange,
    .im_gui = player_glide_im_gui,
-   .bind = player_glide_bind,
+   .load_resources = player_glide_load_resources,
+   .init = player_glide_init,
    .system_register = player_glide_register,
 
    .animator_data = &player_glide.animator,
@@ -93,8 +83,7 @@ void player_glide_pre_update(void)
       player_skate.state.activity_prev = k_skate_activity_air;
 
       q_mulv( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f}, player_skate.state.cog );
-      v3_add( player_skate.state.cog, localplayer.rb.co, 
-              player_skate.state.cog );
+      v3_add( player_skate.state.cog, localplayer.rb.co, player_skate.state.cog );
       v3_copy( localplayer.rb.v, player_skate.state.cog_v );
 
       player__begin_holdout( (v3f){0.0f,0.0f,0.0f} );
@@ -106,7 +95,8 @@ void player_glide_pre_update(void)
    }
 }
 
-static void massless_accel( rigidbody *rb, v3f delta, v3f impulse ){
+static void massless_accel( rigidbody *rb, v3f delta, v3f impulse )
+{
    /* linear */
    v3_muladds( rb->v, impulse, vg.time_fixed_delta, rb->v );
    
@@ -116,9 +106,8 @@ static void massless_accel( rigidbody *rb, v3f delta, v3f impulse ){
    v3_muladds( rb->w, wa, vg.time_fixed_delta, rb->w );
 }
 
-static void calculate_lift( v3f vl, f32 aoa_bias, 
-                            v3f axis, v3f back, f32 power,
-                            v3f out_force ){
+static void calculate_lift( v3f vl, f32 aoa_bias, v3f axis, v3f back, f32 power, v3f out_force )
+{
    v3f up;
    v3_cross( back, axis, up );
 
@@ -135,11 +124,11 @@ static void calculate_lift( v3f vl, f32 aoa_bias,
    v3_cross( wind, axis, lift_dir );
 
    /* this is where induced drag (from the flappy things) would go */
-   
    v3_muls( lift_dir, L, out_force );
 }
 
-static void calculate_drag( v3f vl, f32 cd, v3f out_force ){
+static void calculate_drag( v3f vl, f32 cd, v3f out_force )
+{
    f32 v2 = v3_length2( vl );
    v3f dir;
    v3_copy( vl, dir );
@@ -160,17 +149,14 @@ bool glider_physics( v2f steer )
    m3x3_mulv( rb->to_local, rb->w, wl );
    
    v3f F, Flift, Fslip, Fdrag, FslipW, FliftW;
-
-   calculate_lift( vl, steer[1]*k_glide_steer, 
-                  (v3f){1,0,0},
+   calculate_lift( vl, steer[1]*k_glide_steer, (v3f){1,0,0},
                   (v3f){0,sinf(k_glide_wing_orient),cosf(k_glide_wing_orient)},
                   k_glide_cl, Flift );
+
    v3_copy( Flift, player_glide.info_lift );
    v3_cross( (v3f){0,0,0}, Flift, FliftW );
    
-   calculate_lift( vl, 0.0f,
-                  (v3f){0,1,0},(v3f){0,0,1},
-                  k_glide_cs, Fslip );
+   calculate_lift( vl, 0.0f, (v3f){0,1,0},(v3f){0,0,1}, k_glide_cs, Fslip );
    v3_copy( Fslip, player_glide.info_slip );
    v3_cross( (v3f){0,k_glide_lift_pitch,k_glide_slip_yaw}, Fslip, FslipW );
 
@@ -180,13 +166,15 @@ bool glider_physics( v2f steer )
    v3f balance = {0.0f,-k_glide_balance,0.0f};
    m3x3_mulv( rb->to_local, balance, balance );
 
-   v3f Fw = {
+   v3f Fw = 
+   {
        steer[1]*k_glide_steer - balance[2],
        0.0f,
       -steer[0]*k_glide_steer + balance[0],
    };
 
-   if( player_glide.ticker ){
+   if( player_glide.ticker )
+   {
       player_glide.ticker --;
       return 0;
    }
@@ -216,51 +204,47 @@ bool glider_physics( v2f steer )
    rigidbody _null = {0};
    _null.inv_mass = 0.0f;
    m3x3_zero( _null.iI );
-   for( u32 i=0; i < VG_ARRAY_LEN(player_glide.parts); i ++ ){
+   for( u32 i=0; i < VG_ARRAY_LEN(player_glide.parts); i ++ )
+   {
       m4x3f mmdl;
       m4x3_mul( rb->to_world, player_glide.parts[i].mdl, mmdl );
 
-      if( player_glide.parts[i].shape == k_rb_shape_capsule ){
-         vg_line_capsule( mmdl,
-                          player_glide.parts[i].inf.r,
-                          player_glide.parts[i].inf.h,
-                          VG__BLACK );
+      if( player_glide.parts[i].shape == k_rb_shape_capsule )
+      {
+         vg_line_capsule( mmdl, player_glide.parts[i].inf.r, player_glide.parts[i].inf.h, VG__BLACK );
       }
-      else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+      else if( player_glide.parts[i].shape == k_rb_shape_sphere )
          vg_line_sphere( mmdl, player_glide.parts[i].r, 0 );
-      }
 
-      if( rb_global_has_space() ){
+      if( rb_global_has_space() )
+      {
          rb_ct *buf = rb_global_buffer();
-
          u32 l = 0;
          
-         if( player_glide.parts[i].shape == k_rb_shape_capsule ){
-            l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf,
-                                   NULL, world->geo_bh, buf, 
+         if( player_glide.parts[i].shape == k_rb_shape_capsule )
+         {
+            l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf, NULL, &world->geometry_bh, buf, 
                                    k_material_flag_ghosts );
          }
-         else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
-            l = rb_sphere__scene( mmdl, player_glide.parts[i].r,
-                                  NULL, world->geo_bh, buf,
+         else if( player_glide.parts[i].shape == k_rb_shape_sphere )
+         {
+            l = rb_sphere__scene( mmdl, player_glide.parts[i].r, NULL, &world->geometry_bh, buf,
                                   k_material_flag_ghosts );
          }
 
-         if( player_glide.parts[i].is_damage && l ){
+         if( player_glide.parts[i].is_damage && l )
             bottom_hit = 1;
-         }
 
-         for( u32 j=0; j<l; j ++ ){
+         for( u32 j=0; j<l; j ++ )
+         {
             buf[j].rba = rb;
             buf[j].rbb = &_null;
          }
-
          rb_contact_count += l;
       }
    }
 
-   rb_presolve_contacts( rb_contact_buffer, 
-                         vg.time_fixed_delta, rb_contact_count );
+   rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
    for( u32 i=0; i<10; i ++ )
       rb_solve_contacts( rb_contact_buffer, rb_contact_count );
    
@@ -304,7 +288,7 @@ void player_glide_animate(void)
 
 void player_glide_pose( void *_animator, player_pose *pose )
 {
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    struct player_glide_animator *animator = _animator;
    pose->type = k_player_pose_type_ik;
    pose->board.lean = 0.0f;
@@ -367,14 +351,16 @@ void player_glide_im_gui( ui_context *ctx )
 
 void player_glide_equip_glider(void)
 {
-   if( !localplayer.have_glider ){
+   if( !localplayer.have_glider )
+   {
       localplayer.have_glider = 1;
       localplayer.glider_orphan = 0;
       player_glide.t = -1.0f;
    }
 }
 
-static int ccmd_player_glider_spawn( int argc, const char *argv[] ){
+static int ccmd_player_glider_spawn( int argc, const char *argv[] )
+{
    if( vg_console.cheats ){
       player_glide_equip_glider();
    }
@@ -399,14 +385,14 @@ void player_glide_register(void)
    vg_console_reg_cmd( "spawn_glider", ccmd_player_glider_spawn, NULL );
 }
 
-void player_glide_bind(void)
+void player_glide_init(void)
 {
-   THREAD_1;
    f32 mass = 0.0f,k_density = 8.0f;
    m3x3f I;
    m3x3_zero( I );
 
-   for( u32 i=0; i<VG_ARRAY_LEN(player_glide.parts); i ++ ){
+   for( u32 i=0; i<VG_ARRAY_LEN(player_glide.parts); i ++ )
+   {
       /* create part transform matrix */
       v4f qp, qy, qr, q;
       q_axis_angle( qp, (v3f){1,0,0}, player_glide.parts[i].euler[0] );
@@ -421,7 +407,8 @@ void player_glide_bind(void)
 
       /* add it to inertia model */
 
-      if( player_glide.parts[i].shape == k_rb_shape_capsule ){
+      if( player_glide.parts[i].shape == k_rb_shape_capsule )
+      {
          f32 r  = player_glide.parts[i].inf.r,
              h  = player_glide.parts[i].inf.h,
              pv = vg_capsule_volume( r, h ),
@@ -435,7 +422,8 @@ void player_glide_bind(void)
          vg_translate_inertia( pI, pm, player_glide.parts[i].co );
          m3x3_add( I, pI, I );
       }
-      else if( player_glide.parts[i].shape == k_rb_shape_sphere ){
+      else if( player_glide.parts[i].shape == k_rb_shape_sphere )
+      {
          f32 r  = player_glide.parts[i].r,
              pv = vg_sphere_volume( r ),
              pm = pv * k_density;
@@ -452,33 +440,36 @@ void player_glide_bind(void)
    m3x3_inv( I, player_glide.rb.iI );
    player_glide.rb.inv_mass = 1.0f / mass;
 
+   /* allocate effects */
+   for( u32 i=0; i<VG_ARRAY_LEN(trails_glider); i ++ )
+      trail_alloc( &trails_glider[i], 200, VG_STACK_USE_HEAP );
+}
+
+void player_glide_load_resources(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
    /* resources */
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    player_get_anim( &player_glide.anim_glide, "glide_pose" );
 
-   mdl_context *mdl = &player_glide.glider;
-
-   mdl_open( mdl, "models/glider.mdl", &vg.rtmem );
-   mdl_load_metadata_block( mdl, &vg.rtmem );
-   mdl_async_full_load_std( mdl, NULL );
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &player_glide.glider, "models/glider.mdl" ) );
+   vg_model_stream_metadata( &ctx, VG_STACK_USE_HEAP );
+   vg_model_stream_meshes_gpu( &ctx, NULL );
+   vg_model_stream_textures_gpu( &ctx );
 
    /* load trail positions */
    array_file_ptr markers;
-   AF_LOAD_ARRAY_STRUCT( &mdl->af, &markers, ent_marker, &vg.scratch );
-   mdl_close( mdl );
-
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &markers, ent_marker, _vg_temp_stack() );
    for( u32 i=0; i<af_arrcount( &markers ); i ++ )
    {
       ent_marker *marker = af_arritm( &markers, i );
       v3_copy( marker->transform.co, player_glide.trail_positions[ player_glide.trail_count ++ ] );
-
       if( player_glide.trail_count == VG_ARRAY_LEN(trails_glider) )
          break;
    }
-
-   /* allocate effects */
-   for( u32 i=0; i<VG_ARRAY_LEN(trails_glider); i ++ )
-      trail_alloc( &trails_glider[i], 200 );
+   vg_model_stream_close( &ctx );
 }
 
 void player_glide_transition(void)
@@ -507,15 +498,14 @@ void player_glide_transition(void)
    player__begin_holdout( (v3f){0,0,0} );
 }
 
-void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, mdl_context *mdl )
+void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, vg_model *model )
 {
    u32 current_mat = 0xffffffff;
-   glActiveTexture( GL_TEXTURE0 );
-   mesh_bind( &mdl->mesh );
+   vg_model_bind_mesh( model );
 
-   for( u32 i=0; i<mdl->mesh_count; i ++ )
+   for( u32 i=0; i<model->mesh_count; i ++ )
    {
-      mdl_mesh *mesh = &mdl->meshes[ i ];
+      mdl_mesh *mesh = &model->meshes[ i ];
 
       m4x3f mmmdl;
       mdl_transform_m4x3( &mesh->transform, mmmdl );
@@ -535,7 +525,7 @@ void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enu
 
       for( u32 j=0; j<mesh->submesh_count; j ++ )
       {
-         mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
+         mdl_submesh *sm = &model->submeshes[ mesh->submesh_start+j ];
          if( !sm->material_id ) 
          {
             vg_error( "Invalid material ID 0\n" );
@@ -544,23 +534,23 @@ void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enu
 
          if( sm->material_id != current_mat )
          {
-            mdl_material *mat = &mdl->materials[ sm->material_id-1 ];
+            mdl_material *mat = &model->materials[ sm->material_id-1 ];
             GLuint tex = vg.tex_missing;
 
             if( mat->shader == k_shader_standard )
             {
-               struct shader_props_standard *props = mat->props.compiled;
-
-               u32 index = props->tex_diffuse-1;
-               mdl_texture *ptex = &mdl->textures[ index ];
-               tex = ptex->glname;
+               union shader_props *props = &model->shader_props[ sm->material_id-1 ];
+               u32 index = props->standard.tex_diffuse-1;
+               mdl_texture *mdl_tex = &model->textures[ index ];
+               vg_tex_bind( GL_TEXTURE_2D, &mdl_tex->tex, 0 );
             }
+            else
+               vg_tex_bind( GL_TEXTURE_2D, NULL, 0 );
 
-            glBindTexture( GL_TEXTURE_2D, tex );
             current_mat = sm->material_id;
          }
 
-         mdl_draw_submesh( sm );
+         vg_model_draw_submesh( sm );
       }
    }
 }
@@ -590,7 +580,7 @@ void player_glide_render( vg_camera *cam, world_instance *world, player_pose *po
       shader_model_board_view_uInverseRatioMain,
       cam );
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_board_view );
+   WORLD_LINK_LIGHTING( world, model_board_view );
 
    ms_keyframe kf_res;
    if( localplayer.glider_orphan )
@@ -613,7 +603,7 @@ void player_glide_render( vg_camera *cam, world_instance *world, player_pose *po
          vg_slewf( &player_glide.t, target, vg.time_frame_delta * 4.0f );
 
       ms_keyframe kf_backpack;
-      struct skeleton *sk = &localplayer.skeleton;
+      ms_skeleton *sk = &localplayer.skeleton;
       m4x3_mulv( localplayer.final_mtx[localplayer.id_chest ], sk->bones[localplayer.id_chest].co, kf_backpack.co );
 
       v4f qyaw, qpitch, qchest, q;
index f189cc69e51f029aa147a97f966320d34fd29884..36ee8a258df1fcceb391d09cd8d04bf6da2a235b 100644 (file)
@@ -1,11 +1,10 @@
-#pragma once
-#include "player.h"
-#include "player_render.h"
-#include "trail.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_glide.c"
+#else
 
 struct player_glide 
 {
-   struct skeleton_anim anim_glide;
+   ms_skeletal_animation anim_glide;
 
    struct player_glide_animator 
    {
@@ -33,11 +32,12 @@ struct player_glide
 
    f32 t;
 
-   struct {
+   struct 
+   {
       v3f co, euler;
       m4x3f mdl;
-      
-      union {
+      union 
+      {
          rb_capsule inf;
          f32 r;
       };
@@ -50,12 +50,15 @@ struct player_glide
    u32 trail_count;
    v3f trail_positions[2];
 
-   mdl_context glider, battery;
+   vg_model glider, battery;
 }
 extern player_glide;
 extern struct player_subsystem_interface player_subsystem_glide;
 
 void player_glide_register(void);
+void player_glide_init(void);
+void player_glide_pre_update(void);
+void player_glide_load_resources(void);
 void player_glide_pre_update(void);
 void player_glide_update(void);
 void player_glide_post_update(void);
@@ -68,10 +71,10 @@ void player_glide_bind(void);
 void player_glide_transition(void);
 bool glider_physics( v2f steer );
 void player_glide_animator_exchange( bitpack_ctx *ctx, void *data );
-void player_glide_render( vg_camera *cam, world_instance *world,
-                          player_pose *pose );
-void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, mdl_context *mdl );
+void player_glide_render( vg_camera *cam, world_instance *world, player_pose *pose );
+void render_glider_model( vg_camera *cam, world_instance *world, m4x3f mmdl, enum board_shader shader, vg_model *model );
 void player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data );
 void player_glide_equip_glider(void);
 void player_glide_render_effects( vg_camera *cam );
 
+#endif
diff --git a/src/player_model.h b/src/player_model.h
deleted file mode 100644 (file)
index 8d5dd80..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "model.h"
-#include "skeleton.h"
-#include "player_ragdoll.h"
-
-#include "shaders/model_character_view.h"
index 5ef3ebdc0e1f9133c8a5b0d69143d702eba6f07e..4e8e481a3086721b8e235df9168228e7b1648942 100644 (file)
@@ -1,13 +1,3 @@
-#pragma once
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-#include "vg/vg_rigidbody_constraints.h"
-#include "scene_rigidbody.h"
-
-#include "player.h"
-#include "player_dead.h"
-#include "audio.h"
-
 static float k_ragdoll_floatyiness = 20.0f,
              k_ragdoll_floatydrag  = 1.0f,
              k_ragdoll_limit_scale = 1.0f,
@@ -57,7 +47,7 @@ static int dev_ragdoll_saveload(int argc, const char *argv[]){
    return 0;
 }
 
-void player_ragdoll_register(void)
+VG_API void _player_ragdoll_register(void)
 {
    VG_VAR_F32( k_ragdoll_active_threshold );
    VG_VAR_F32( k_ragdoll_angular_drag );
@@ -71,8 +61,7 @@ void player_ragdoll_register(void)
    vg_console_reg_cmd( "ragdoll", dev_ragdoll_saveload, NULL );
 }
 
-void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
-                                        struct ragdoll_part *rp )
+void player_init_ragdoll_bone_collider( ms_skeleton_bone *bone, struct ragdoll_part *rp )
 {
    f32 k_density = 8.0f,
        k_inertia_scale = 2.0f;
@@ -157,8 +146,7 @@ u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id )
 /*
  * Setup ragdoll colliders from skeleton
  */
-void setup_ragdoll_from_skeleton( struct skeleton *sk,
-                                  struct player_ragdoll *rd )
+void setup_ragdoll_from_skeleton( ms_skeleton *sk, struct player_ragdoll *rd )
 {
    rd->part_count = 0;
 
@@ -168,8 +156,9 @@ void setup_ragdoll_from_skeleton( struct skeleton *sk,
    rd->position_constraints_count = 0;
    rd->cone_constraints_count = 0;
 
-   for( u32 i=1; i<sk->bone_count; i ++ ){
-      struct skeleton_bone *bone = &sk->bones[i];
+   for( u32 i=1; i<sk->bone_count; i ++ )
+   {
+      ms_skeleton_bone *bone = &sk->bones[i];
 
       /*
        * Bones with colliders
@@ -203,9 +192,9 @@ void setup_ragdoll_from_skeleton( struct skeleton *sk,
 
          struct rb_constr_pos *c = &rd->position_constraints[ conid ];
 
-         struct skeleton_bone *bj = &sk->bones[rp->bone_id];
+         ms_skeleton_bone *bj = &sk->bones[rp->bone_id];
          struct ragdoll_part  *pp = &rd->parts[rp->parent];
-         struct skeleton_bone *bp = &sk->bones[pp->bone_id];
+         ms_skeleton_bone *bp = &sk->bones[pp->bone_id];
          
          rd->constraint_associations[conid][0] = rp->parent;
          rd->constraint_associations[conid][1] = part_id;
@@ -275,10 +264,12 @@ void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd )
                 localplayer.final_mtx[part->bone_id] );
    }
 
-   for( u32 i=1; i<localplayer.skeleton.bone_count; i++ ){
-      struct skeleton_bone *sb = &localplayer.skeleton.bones[i];
+   for( u32 i=1; i<localplayer.skeleton.bone_count; i++ )
+   {
+      ms_skeleton_bone *sb = &localplayer.skeleton.bones[i];
 
-      if( sb->parent && !sb->collider ){
+      if( sb->parent && !sb->collider )
+      {
          v3f delta;
          v3_sub( localplayer.skeleton.bones[i].co, 
                  localplayer.skeleton.bones[sb->parent].co, delta );
@@ -362,36 +353,37 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
 
    rb_solver_reset();
    
-   float contact_velocities[256];
+   f32 contact_velocities[256];
 
    rigidbody _null = {0};
    _null.inv_mass = 0.0f;
    m3x3_zero( _null.iI );
 
-   for( int i=0; i<rd->part_count; i ++ ){
+   for( int i=0; i<rd->part_count; i ++ )
+   {
       v4_copy( rd->parts[i].rb.q, rd->parts[i].prev_q );
       v3_copy( rd->parts[i].rb.co, rd->parts[i].prev_co );
 
-      if( rb_global_has_space() ){
+      if( rb_global_has_space() )
+      {
          rb_ct *buf = rb_global_buffer();
-
          int l;
          
-         if( rd->parts[i].type == k_bone_collider_capsule ){
-            l = rb_capsule__scene( rd->parts[i].rb.to_world,
-                                   &rd->parts[i].inf.capsule,
-                                   NULL, world->geo_bh, buf,
-                                   k_material_flag_ghosts );
+         if( rd->parts[i].type == k_bone_collider_capsule )
+         {
+            l = rb_capsule__scene( rd->parts[i].rb.to_world, &rd->parts[i].inf.capsule,
+                                   NULL, &world->geometry_bh, buf, k_material_flag_ghosts );
          }
-         else if( rd->parts[i].type == k_bone_collider_box ){
-            l = rb_box__scene( rd->parts[i].rb.to_world,
-                               rd->parts[i].inf.box,
-                               NULL, world->geo_bh, buf,
-                               k_material_flag_ghosts );
+         else if( rd->parts[i].type == k_bone_collider_box )
+         {
+            l = rb_box__scene( rd->parts[i].rb.to_world, rd->parts[i].inf.box,
+                               NULL, &world->geometry_bh, buf, k_material_flag_ghosts );
          }
-         else continue;
+         else 
+            continue;
 
-         for( int j=0; j<l; j++ ){
+         for( int j=0; j<l; j++ )
+         {
             buf[j].rba = &rd->parts[i].rb;
             buf[j].rbb = &_null;
          }
@@ -403,9 +395,12 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
    /* 
     * self-collision
     */
-   for( int i=0; i<rd->part_count-1; i ++ ){
-      for( int j=i+1; j<rd->part_count; j ++ ){
-         if( rd->parts[j].parent != i ){
+   for( int i=0; i<rd->part_count-1; i ++ )
+   {
+      for( int j=i+1; j<rd->part_count; j ++ )
+      {
+         if( rd->parts[j].parent != i )
+         {
             if( !rb_global_has_space() )
                break;
 
@@ -423,7 +418,8 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
                                          &rd->parts[j].inf.capsule,
                                          buf );
 
-            for( int k=0; k<l; k++ ){
+            for( int k=0; k<l; k++ )
+            {
                buf[k].rba = &rd->parts[i].rb;
                buf[k].rbb = &rd->parts[j].rb;
             }
@@ -440,93 +436,79 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
          struct ragdoll_part *pj = &rd->parts[j];
 
          if( run_sim )
-         {
-            rb_effect_simple_bouyency( &pj->rb, world->water.plane,
-                                        k_ragdoll_floatyiness,
-                                        k_ragdoll_floatydrag );
-         }
+            rb_effect_simple_bouyency( &pj->rb, world->water.plane, k_ragdoll_floatyiness, k_ragdoll_floatydrag );
       }
    }
 
    /*
     * PRESOLVE
     */
-   for( u32 i=0; i<rb_contact_count; i++ ){
+   for( u32 i=0; i<rb_contact_count; i++ )
+   {
       rb_ct *ct = &rb_contact_buffer[i];
-
       v3f rv, ra, rb;
       v3_sub( ct->co, ct->rba->co, ra );
       v3_sub( ct->co, ct->rbb->co, rb );
       rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
-      float     vn = v3_dot( rv, ct->n );
-
+      f32 vn = v3_dot( rv, ct->n );
       contact_velocities[i] = vn;
    }
 
-   rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, 
-                         rb_contact_count );
-   rb_presolve_swingtwist_constraints( rd->cone_constraints,
-                                       rd->cone_constraints_count );
+   rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
+   rb_presolve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
 
    /* 
     * DEBUG
     */
-   if( k_ragdoll_debug_collider ){
-      for( u32 i=0; i<rd->part_count; i ++ ){
+   if( k_ragdoll_debug_collider )
+   {
+      for( u32 i=0; i<rd->part_count; i ++ )
+      {
          struct ragdoll_part *rp = &rd->parts[i];
 
-         if( rp->type == k_bone_collider_capsule ){
-            vg_line_capsule( rp->rb.to_world, 
-                             rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
-         }
-         else if( rp->type == k_bone_collider_box ){
-            vg_line_boxf_transformed( rp->rb.to_world, 
-                                      rp->inf.box, rp->colour );
-         }
+         if( rp->type == k_bone_collider_capsule )
+            vg_line_capsule( rp->rb.to_world, rp->inf.capsule.r, rp->inf.capsule.h, rp->colour );
+         else if( rp->type == k_bone_collider_box )
+            vg_line_boxf_transformed( rp->rb.to_world, rp->inf.box, rp->colour );
       }
    }
 
-   if( k_ragdoll_debug_constraints ){
-      rb_debug_position_constraints( rd->position_constraints, 
-                                     rd->position_constraints_count );
-
-      rb_debug_swingtwist_constraints( rd->cone_constraints,
-                                       rd->cone_constraints_count );
+   if( k_ragdoll_debug_constraints )
+   {
+      rb_debug_position_constraints( rd->position_constraints, rd->position_constraints_count );
+      rb_debug_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
    }
 
    /*
     * SOLVE CONSTRAINTS  & Integrate
     */
-   if( run_sim ){
+   if( run_sim )
+   {
       /* the solver is not very quickly converging so... */
-      for( int i=0; i<40; i++ ){
-         if( i<20 ){
+      for( int i=0; i<40; i++ )
+      {
+         if( i<20 )
+         {
             rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-            rb_solve_swingtwist_constraints( rd->cone_constraints, 
-                                             rd->cone_constraints_count );
-            rb_postsolve_swingtwist_constraints( rd->cone_constraints, 
-                                                 rd->cone_constraints_count );
+            rb_solve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
+            rb_postsolve_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count );
          }
-         rb_solve_position_constraints( rd->position_constraints, 
-                                        rd->position_constraints_count );
+         rb_solve_position_constraints( rd->position_constraints, rd->position_constraints_count );
       }
 
-      rb_correct_position_constraints( rd->position_constraints,
-                                       rd->position_constraints_count, 
-                                       k_ragdoll_correction * 0.5f );
-      rb_correct_swingtwist_constraints( rd->cone_constraints, 
-                                         rd->cone_constraints_count,
-                                         k_ragdoll_correction * 0.25f );
+      rb_correct_position_constraints( rd->position_constraints, rd->position_constraints_count, k_ragdoll_correction * 0.5f );
+      rb_correct_swingtwist_constraints( rd->cone_constraints, rd->cone_constraints_count, k_ragdoll_correction * 0.25f );
 
-      for( int i=0; i<rd->part_count; i++ ){
+      for( int i=0; i<rd->part_count; i++ )
+      {
          rb_iter( &rd->parts[i].rb );
 
          v3f w;
          v3_copy( rd->parts[i].rb.w, w );
-         if( v3_length2( w ) > 0.00001f ){
+         if( v3_length2( w ) > 0.00001f )
+         {
             v3_normalize( w );
-            v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag,
-                        rd->parts[i].rb.w );
+            v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag, rd->parts[i].rb.w );
          }
       }
 
@@ -535,19 +517,19 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
    }
 
    rb_ct *stress = NULL;
-   float max_stress = 1.0f;
-
-   for( u32 i=0; i<rb_contact_count; i++ ){
+   f32 max_stress = 1.0f;
+   for( u32 i=0; i<rb_contact_count; i++ )
+   {
       rb_ct *ct = &rb_contact_buffer[i];
 
       v3f rv, ra, rb;
       v3_sub( ct->co, ct->rba->co, ra );
       v3_sub( ct->co, ct->rbb->co, rb );
       rb_rcv( ct->rba, ct->rbb, ra, rb, rv );
-      float vn = v3_dot( rv, ct->n );
-
-      float s = fabsf(vn - contact_velocities[i]);
-      if( s > max_stress ){
+      f32 vn = v3_dot( rv, ct->n );
+      f32 s = fabsf(vn - contact_velocities[i]);
+      if( s > max_stress )
+      {
          stress = ct;
          max_stress = s;
       }
@@ -558,14 +540,13 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
    /* 
     * motorized joints 
     */
-   if( run_sim && 
-         (v3_length2(player_dead.v_lpf)>(k_ragdoll_active_threshold*
-                                         k_ragdoll_active_threshold)) ){
+   if( run_sim && (v3_length2(player_dead.v_lpf)>(k_ragdoll_active_threshold*k_ragdoll_active_threshold)) )
+   {
       ms_keyframe anim[32];
-      skeleton_sample_anim( &localplayer.skeleton, &player_dead.anim_bail,
-                            0.0f, anim );
+      skeleton_sample_anim( &localplayer.skeleton, &player_dead.anim_bail, 0.0f, anim );
 
-      for( u32 i=0; i<rd->cone_constraints_count; i ++ ){
+      for( u32 i=0; i<rd->cone_constraints_count; i ++ )
+      {
          rb_constr_swingtwist *st = &rd->cone_constraints[i];
          rb_constr_pos *pc = &rd->position_constraints[i];
 
@@ -615,7 +596,8 @@ void player_ragdoll_iter( struct player_ragdoll *rd )
       }
    }
 
-   if( temp_filter ){
+   if( temp_filter )
+   {
       temp_filter --;
       return;
    }
index b47bdca06feb3124bc78e5167a640eac4527e81c..4dfad904094b6c312d3e1528373444ad02bf950f 100644 (file)
@@ -1,15 +1,6 @@
-#pragma once
-
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * Ragdoll system
- */
-
-#include "player_api.h"
-#include "skeleton.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_constraints.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_ragdoll.c"
+#else
 
 struct player_ragdoll{
    struct ragdoll_part{
@@ -51,22 +42,15 @@ struct player_ragdoll{
    int shoes[2];
 };
 
-enum player_die_type {
-   k_player_die_type_generic,
-   k_player_die_type_head,
-   k_player_die_type_feet,
-   k_player_die_type_water
-};
+VG_API void _player_ragdoll_register(void);
 
-void player_ragdoll_register(void);
-void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
-                                           struct ragdoll_part *rp );
+void player_init_ragdoll_bone_collider( ms_skeleton_bone *bone, struct ragdoll_part *rp );
 u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id );
-void setup_ragdoll_from_skeleton( struct skeleton *sk,
-                                  struct player_ragdoll *rd );
+void setup_ragdoll_from_skeleton( ms_skeleton *sk, struct player_ragdoll *rd );
 void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd );
-void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
-                                  enum player_die_type type );
+void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, enum player_die_type type );
                                    
 void player_debug_ragdoll(void);
 void player_ragdoll_iter( struct player_ragdoll *rd );
+
+#endif
index a72e9701f8a96d82a50c1e0e0bb13ddfb952cb6b..3b3b0b0b7c38ad6a722d7c90ee35852d96ee1668 100644 (file)
@@ -1,16 +1,3 @@
-#include "player_remote.h"
-#include "skeleton.h"
-#include "player_render.h"
-#include "player_api.h"
-#include "network_common.h"
-#include "addon.h"
-#include "font.h"
-#include "gui.h"
-#include "ent_region.h"
-#include "shaders/model_entity.h"
-#include "vg/vg_steam2.h"
-#include "vg/vg_magi.h"
-
 struct global_netplayers netplayers;
 
 static i32 k_show_own_name = 0;
@@ -34,7 +21,7 @@ static void player_remote_clear( u32 player_index )
       {
          menu_close(); /* sets state to default */
          menu_open( k_menu_page_quick );
-         gui_helper_reset( k_gui_helper_mode_clear );
+         _gui_helper_reset( k_gui_helper_mode_clear );
          localplayer.immobile = 0;
       }
    }
@@ -493,7 +480,7 @@ void pose_remote_player( f64 pose_time, struct interp_frame *i0, struct interp_f
                          struct player_effects_data *out_effects, 
                          bool *out_render_glider, vg_camera *out_camera )
 {
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    struct player_subsystem_interface *sys0 = player_subsystems[i0->subsystem],
                                      *sys1 = NULL;
 
@@ -658,7 +645,7 @@ void animate_remote_player( u32 index )
    }
 
    struct network_player *player = &netplayers.list[ index ];
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*index ];
    v3f *glider_mtx = netplayers.glider_mtx[ index ];
    struct player_board_pose *board_pose = &netplayers.board_poses[index];
@@ -724,7 +711,7 @@ void render_remote_players( world_instance *world, vg_camera *cam )
          gliders ++;
    }
 
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    for( u32 j=0; j<draw_list_count; j ++ )
    {
@@ -747,8 +734,7 @@ void render_remote_players( world_instance *world, vg_camera *cam )
    shader_model_entity_uTexMain( 0 );
    shader_model_entity_uCamera( cam->transform[3] );
    shader_model_entity_uPv( cam->mtx.pv );
-   
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+   WORLD_LINK_LIGHTING( world, model_entity );
 
    for( u32 j=0; j<draw_list_count; j ++ )
    {
@@ -822,8 +808,9 @@ void remote_sfx_pre_update(void)
 /*
  * animator->root_co of remote player
  */
-static void remote_player_position( int id, v3f out_co ){
-   struct skeleton *sk = &localplayer.skeleton;
+static void remote_player_position( int id, v3f out_co )
+{
+   ms_skeleton *sk = &localplayer.skeleton;
    m4x3f *final_mtx = &netplayers.final_mtx[ sk->bone_count*id ];
    v3_copy( final_mtx[0][3], out_co );
 }
@@ -851,8 +838,8 @@ static int player_tag_position( m4x4f pv, v3f root_co, ui_point out_point ){
 
       float k_max = 32000.0f;
       
-      out_point[0] = vg_clampf(wpos[0] * vg.window_x, -k_max, k_max );
-      out_point[1] = vg_clampf((1.0f-wpos[1]) * vg.window_y, -k_max, k_max );
+      out_point[0] = vg_clampf(wpos[0] * _vg_window.w, -k_max, k_max );
+      out_point[1] = vg_clampf((1.0f-wpos[1]) * _vg_window.h, -k_max, k_max );
       return 1;
    }
    else
@@ -921,7 +908,7 @@ static void remote_player_nametag( ui_context *ctx, ui_point tag_root,
 #if 0
             vg_strcatch( &str, (char)k_SRglyph_vg_circle );
 #endif
-            vg_strcati32( &str, player->medals[i] );
+            vg_strcati64( &str, player->medals[i], 10 );
 
             ui_text( ctx, col, buf, 1, k_ui_align_middle_center, 
                      ui_colour( ctx, (enum ui_scheme_colour[]){ 
@@ -995,7 +982,7 @@ void remote_players_imgui_lobby( ui_context *ctx )
          return;
 
    ui_px y = 50, width = 200, height = 42, gap = 2,
-         x = vg.window_x - width;
+         x = _vg_window.w - width;
 
    ctx->font = &vgf_default_large;
    ui_text( ctx, (ui_rect){ x, 0, width, height }, "In World", 1, k_ui_align_middle_center, 0 );
@@ -1097,7 +1084,7 @@ void remote_players_chat_imgui( ui_context *ctx )
    if( netplayers.chatting == 1 )
    {
       ui_rect box = { 0, 0, 400, 40 },
-              window = { 0, 0, vg.window_x, vg.window_y };
+              window = { 0, 0, _vg_window.w, _vg_window.h };
       ui_rect_center( window, box );
 
       struct ui_textbox_callbacks callbacks = 
@@ -1243,14 +1230,14 @@ static int cmd_network_info( int argc, const char *argv[] )
    return 1;
 }
 
-void remote_players_register(void)
+VG_API void _remote_players_register(void)
 {
    vg_console_reg_cmd( "network_info", cmd_network_info, NULL );
    vg_console_reg_cmd( "add_test_players", remote_players_randomize, NULL );
    vg_console_reg_var( "k_show_own_name", &k_show_own_name, k_var_dtype_i32, 0 );
 }
 
-void remote_players_init(void)
+VG_API void _remote_players_init(void)
 {
    for( u32 i=0; i<NETWORK_SFX_QUEUE_LENGTH; i ++ )
       netplayers.sfx_queue[i].system = k_player_subsystem_invalid;
@@ -1264,7 +1251,7 @@ void _network_get_spectate_cam( vg_camera *cam )
    struct network_player *player = &netplayers.list[ netplayers.spectate_index ];
    if( !player->active || !player->same_world )
    {
-      gui_helper_reset( k_gui_helper_mode_clear );
+      _gui_helper_reset( k_gui_helper_mode_clear );
       localplayer.immobile = 0;
       skaterift.activity = k_skaterift_default;
       return;
index d411978153d97c8c705df724f8f8c1a2a5a526d7..125cc0ebf4beb7babcd036c1617e9da5dbfb381f 100644 (file)
@@ -1,16 +1,6 @@
-#pragma once
-#include "player.h"
-#include "network.h"
-#include "network_common.h"
-#include "player_render.h"
-#include "player_effects.h"
-#include "player_api.h"
-
-#include "player_skate.h"
-#include "player_walk.h"
-#include "player_dead.h"
-#include "player_basic_info.h"
-#include "player_glide.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_remote.c"
+#else
 
 #define NETWORK_SFX_QUEUE_LENGTH 12
 
@@ -51,7 +41,8 @@ struct global_netplayers
    u32 spectate_index;
    vg_camera spectate_camera;
 
-   struct interp_buffer {
+   struct interp_buffer 
+   {
       /* collect the most recent 6 frames of animation data */
       struct interp_frame 
       {
@@ -96,6 +87,9 @@ struct global_netplayers
 }
 extern netplayers;
 
+VG_API void _remote_players_register(void);
+VG_API void _remote_players_init(void);
+
 void player_remote_rx_200_300( SteamNetworkingMessage_t *msg );
 void remote_player_debug_update(void);
 void remote_player_send_playerframe(void);
@@ -104,8 +98,6 @@ void animate_remote_players(void);
 void render_remote_players( world_instance *world, vg_camera *cam );
 void relink_all_remote_player_worlds(void);
 void player_remote_update_friendflags( struct network_player *remote );
-void remote_players_register(void);
-void remote_players_init(void);
 void remote_sfx_pre_update(void);
 void remote_players_imgui_world( ui_context *ctx, world_instance *world, m4x4f pv, f32 max_dist, int geo_cull );
 void remote_players_imgui_lobby( ui_context *ctx );
@@ -120,3 +112,5 @@ void pose_remote_player( f64 pose_time, struct interp_frame *f0, struct interp_f
 void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest,
                          struct net_sfx *sfx_buffer, u32 *inout_sfx_buffer_len );
 void _network_get_spectate_cam( vg_camera *cam );
+
+#endif
index 62d2cfd70f332d587efa6fbb1d037557a13b744d..28e5319acadceb29c72652db0a92b2ac093a3320 100644 (file)
@@ -1,58 +1,10 @@
-#include "player.h"
-#include "player_render.h"
-#include "vg/vg_camera.h"
-#include "player_model.h"
-#include "ent_skateshop.h"
-#include "audio.h"
-#include "input.h"
-
-#include "shaders/model_character_view.h"
-#include "shaders/model_board_view.h"
-#include "shaders/model_entity.h"
-#include "shaders/model_board_view.h"
-#include "depth_compare.h"
-
-#include "network.h"
-#include "player_remote.h"
-#include "player_glide.h"
-#include "metascene.h"
-
-void player_load_animations( const char *path )
+static void _player_render_load_content_async( void *_, vg_async_info *async )
 {
-   metascene_load( &localplayer.animations, path, &vg.rtmem );
-}
-
-void player_get_anim( skeleton_anim *out_anim, const char *name )
-{
-   ms_context *ms = &localplayer.animations;
-   u32 hash = vg_strdjb2( name );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
-   for( u32 i=0; i<af_arrcount( &ms->strips ); i ++ )
-   {
-      ms_strip *strip = af_arritm( &ms->strips, i );
-      if( strip->mode != k_ms_strip_mode_keyframes )
-         continue;
-
-      if( af_str_eq( &ms->af, strip->strip.pstr_name, name, hash ) )
-      {
-         out_anim->strip = strip;
-         out_anim->framerate = localplayer.animations.info.framerate;
-         out_anim->keyframes_base = af_arritm( &localplayer.animations.keyframes, strip->strip.start );
-         return;
-      }
-   }
-   vg_fatal_error( "Failed to find animation '%s' in metascene.\n", name );
-}
-
-void player_load_animation_reference( const char *path )
-{
-   mdl_context *meta = &localplayer.skeleton_meta;
-   mdl_open( meta, path, &vg.rtmem );
-   mdl_load_metadata_block( meta, &vg.rtmem );
-   mdl_close( meta );
-
-   struct skeleton *sk = &localplayer.skeleton;
-   skeleton_setup( sk, meta, 0, &vg.rtmem );
+   vg_model_load( &localplayer.skeleton_meta, VG_MODEL_CPU_METADATA, "models/ch_none.mdl", NULL );
+   ms_skeleton *sk = &localplayer.skeleton;
+   skeleton_setup( sk, &localplayer.skeleton_meta, 0, VG_STACK_USE_HEAP );
 
    localplayer.id_world      = skeleton_bone_id( sk, "world" );
    localplayer.id_hip        = skeleton_bone_id( sk, "hips" );
@@ -73,27 +25,29 @@ void player_load_animation_reference( const char *path )
    localplayer.id_ik_knee_r  = skeleton_bone_id( sk, "knee.R" );
    localplayer.id_eyes       = skeleton_bone_id( sk, "eyes" );
 
-   for( i32 i=0; i<sk->bone_count; i ++ ){
+   for( i32 i=0; i<sk->bone_count; i ++ )
       localplayer.skeleton_mirror[i] = 0;
-   }
-
-   for( i32 i=1; i<sk->bone_count-1; i ++ ){
-      struct skeleton_bone *si = &sk->bones[i];
 
+   for( i32 i=1; i<sk->bone_count-1; i ++ )
+   {
+      ms_skeleton_bone *si = &sk->bones[i];
       char tmp[64];
       vg_str str;
       vg_strnull( &str, tmp, 64 );
       vg_strcat( &str, si->name );
 
       char *L = vg_strch( &str, 'L' );
-      if( !L ) continue;
+      if( !L ) 
+         continue;
       u32 len = L-tmp;
 
-      for( i32 j=i+1; j<sk->bone_count; j ++ ){
-         struct skeleton_bone *sj = &sk->bones[j];
-
-         if( !strncmp( si->name, sj->name, len ) ){
-            if( sj->name[len] == 'R' ){
+      for( i32 j=i+1; j<sk->bone_count; j ++ )
+      {
+         ms_skeleton_bone *sj = &sk->bones[j];
+         if( !strncmp( si->name, sj->name, len ) )
+         {
+            if( sj->name[len] == 'R' )
+            {
                localplayer.skeleton_mirror[i] = j;
                localplayer.skeleton_mirror[j] = i;
                break;
@@ -101,87 +55,132 @@ void player_load_animation_reference( const char *path )
          }
       }
    }
-
    setup_ragdoll_from_skeleton( sk, &localplayer.ragdoll );
 
-   /* allocate matrix buffers for localplayer and remote players */
+   /* allocate matrix buffers for localplayer and remote players. uh this is a bit crappy? */
    u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
-   localplayer.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Final MTX" );
-   netplayers.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size*NETWORK_MAX_PLAYERS, 8, "Network final MTX" );
-   netplayers.glider_mtx = vg_stack_allocate( &vg.rtmem, sizeof(m4x3f)*NETWORK_MAX_PLAYERS, 8, "Glider MTX" );
+   localplayer.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Final MTX" );
+   netplayers.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size*NETWORK_MAX_PLAYERS, 8, "Network final MTX" );
+   netplayers.glider_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, sizeof(m4x3f)*NETWORK_MAX_PLAYERS, 8, "Glider MTX" );
+   _replay2.final_mtx = vg_stack_allocate( VG_STACK_USE_HEAP, mtx_size, 8, "Replay Final MTX" );
+   metascene_load( &localplayer.animations, "metascenes/skater.ms", NULL );
+
+   player_model_load( &localplayer.fallback_model, "models/ch_none.mdl", VG_STACK_USE_HEAP );
+   player_board_load( &localplayer.fallback_board, "models/board_none.mdl", VG_STACK_USE_HEAP );
+   vg_model_load( &localplayer.battery, VG_MODEL_ENGINE_STANDARD, "models/battery.mdl", VG_STACK_USE_HEAP );
+
+   for( u32 i=0; i<k_player_subsystem_max; i++ )
+   {
+      struct player_subsystem_interface *sys = player_subsystems[i];
+      if( sys && sys->load_resources )
+         sys->load_resources();
+   }
+}
+
+VG_API void _player_render_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_player_render_load_content_async );
+}
+
+void player_get_anim( ms_skeletal_animation *out_anim, const char *name )
+{
+   metascene *ms = &localplayer.animations;
+   u32 hash = vg_strdjb2( name );
+
+   for( u32 i=0; i<af_arrcount( &ms->strips ); i ++ )
+   {
+      ms_strip *strip = af_arritm( &ms->strips, i );
+      if( strip->mode != k_ms_strip_mode_keyframes )
+         continue;
+
+      if( af_str_eq( ms->packed_strings, strip->strip.pstr_name, name, hash ) )
+      {
+         out_anim->strip = strip;
+         out_anim->framerate = localplayer.animations.info.framerate;
+         out_anim->keyframes_base = af_arritm( &localplayer.animations.keyframes, strip->strip.start );
+         return;
+      }
+   }
+   vg_fatal_error( "Failed to find animation '%s' in metascene.\n", name );
 }
 
 /* TODO: allow error handling */
-void player_board_load( player_board *board, const char *path, void *arena )
+void player_board_load( player_board *board, const c8 *path, vg_stack_allocator *stack )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
-   mdl_open( &board->mdl, path, arena );
-   mdl_load_metadata_block( &board->mdl, arena );
-   mdl_async_full_load_std( &board->mdl, NULL );
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &board->model, path ) );
+   vg_model_stream_metadata( &ctx, stack );
+   vg_model_stream_meshes_gpu( &ctx, NULL );
+   vg_model_stream_textures_gpu( &ctx );
 
    array_file_ptr markers;
-   AF_LOAD_ARRAY_STRUCT( &board->mdl.af, &markers, ent_marker, &vg.scratch );
-
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &markers, ent_marker, _vg_temp_stack() );
    for( int i=0; i<4; i++ )
       board->wheels[i].indice_count = 0;
    for( int i=0; i<2; i++ )
       board->trucks[i].indice_count = 0;
    board->board.indice_count = 0;
 
-   for( u32 i=0; i<board->mdl.mesh_count; i++ )
+   for( u32 i=0; i<board->model.mesh_count; i++ )
    {
-      mdl_mesh *mesh = &board->mdl.meshes[ i ];
-
+      mdl_mesh *mesh = &board->model.meshes[ i ];
       if( mdl_entity_id_type( mesh->entity_id ) != k_ent_marker )
          continue;
 
       u32 index = mdl_entity_id_id( mesh->entity_id );
       ent_marker *marker = af_arritm( &markers, index );
-      mdl_submesh *sm0 = &board->mdl.submeshes[ mesh->submesh_start ];
+      mdl_submesh *sm0 = &board->model.submeshes[ mesh->submesh_start ];
       
-      const char *alias = af_str( &board->mdl.af, marker->pstr_alias );
+      const char *alias = af_str( board->model.packed_strings, marker->pstr_alias );
       u32 lr = marker->transform.co[0] > 0.0f? 1: 0,
           fb = marker->transform.co[2] > 0.0f? 0: 1;
 
-      if( !strcmp( alias, "wheel" ) ){
+      if( !strcmp( alias, "wheel" ) )
+      {
          u32 id = fb<<1 | lr;
          board->wheels[ id ] = *sm0;
          v3_copy( marker->transform.co, board->wheel_positions[ id ] );
       }
-      else if( !strcmp( alias, "board" ) ){
+      else if( !strcmp( alias, "board" ) )
+      {
          board->board = *sm0;
          v3_copy( marker->transform.co, board->board_position );
       }
-      else if( !strcmp( alias, "truck" ) ){
+      else if( !strcmp( alias, "truck" ) )
+      {
          board->trucks[ fb ] = *sm0;
          v3_copy( marker->transform.co, board->truck_positions[ fb ] );
       }
    }
 
-   mdl_close( &board->mdl );
+   vg_model_stream_close( &ctx );
 }
 
 void player_board_unload( struct player_board *board )
 {
-   THREAD_0;
-   mdl_sync_std_unload( &board->mdl );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   vg_model_unload_gpu( &board->model );
 }
 
-void player_model_load( player_model *pm, const char *path, void *arena )
+void player_model_load( player_model *pm, const c8 *path, vg_stack_allocator *stack )
 {
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    pm->flags = 0x0;
 
-   mdl_open( &pm->mdl, path, arena );
-   mdl_load_metadata_block( &pm->mdl, arena );
-   AF_LOAD_ARRAY_STRUCT( &pm->mdl.af, &pm->editer_property, editer_property, arena );
-   AF_LOAD_ARRAY_STRUCT( &pm->mdl.af, &pm->editer_item, editer_item, arena );
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &pm->model, path ) );
+   vg_model_stream_metadata( &ctx, stack );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &pm->editer_property, editer_property, stack );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &pm->editer_item, editer_item, stack );
 
    if( af_arrcount( &pm->editer_item ) )
       pm->flags |= PLAYER_MODEL_FLAG_CUSTOMIZABLE;
 
-   VG_ASSERT( pm->mdl.armature_count );
-   mdl_armature *armature = &pm->mdl.armatures[ 0 ];
+   VG_ASSERT( pm->model.armature_count );
+   mdl_armature *armature = &pm->model.armatures[ 0 ];
 
    u32 fixup_table[ armature->bone_count+1 ];
    for( u32 i=0; i<armature->bone_count+1; i ++ )
@@ -189,16 +188,16 @@ void player_model_load( player_model *pm, const char *path, void *arena )
 
    for( u32 i=1; i<localplayer.skeleton.bone_count; i ++ )
    {
-      struct skeleton_bone *sb = &localplayer.skeleton.bones[i];
+      ms_skeleton_bone *sb = &localplayer.skeleton.bones[i];
       u32 hash = vg_strdjb2( sb->name );
 
       bool found = 0;
 
       for( u32 j=1; j<armature->bone_count; j ++ )
       {
-         mdl_bone *bone = &pm->mdl.bones[ armature->bone_start+j ];
+         mdl_bone *bone = &pm->model.bones[ armature->bone_start+j ];
 
-         if( af_str_eq( &pm->mdl.af, bone->pstr_name, sb->name, hash ) )
+         if( af_str_eq( pm->model.packed_strings, bone->pstr_name, sb->name, hash ) )
          {
             fixup_table[j+1] = i;
             found = 1;
@@ -210,34 +209,33 @@ void player_model_load( player_model *pm, const char *path, void *arena )
          vg_low( "Reference skeleton has a bone called '%s', retargetee has no such bone..\n", sb->name );
    }
 
-   mdl_async_full_load_std( &pm->mdl, fixup_table );
-   mdl_close( &pm->mdl );
+   vg_model_stream_meshes_gpu( &ctx, fixup_table );
+   vg_model_stream_close( &ctx );
 }
 
 void player_model_unload( player_model *pm )
 {
-   THREAD_0;
-   mdl_sync_std_unload( &pm->mdl );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   vg_model_unload_gpu( &pm->model );
 }
 
-void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
-                               m4x3f *final_mtx ){
+void apply_full_skeleton_pose( ms_skeleton *sk, player_pose *pose, m4x3f *final_mtx )
+{
    m4x3f transform;
    q_m3x3( pose->root_q, transform );
    v3_copy( pose->root_co, transform[3] );
    
-   if( pose->type == k_player_pose_type_ik ){
-      skeleton_apply_pose( sk, pose->keyframes, 
-                           k_anim_apply_defer_ik, final_mtx );
+   if( pose->type == k_player_pose_type_ik )
+   {
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_defer_ik, final_mtx );
       skeleton_apply_ik_pass( sk, final_mtx );
-      skeleton_apply_pose( sk, pose->keyframes, 
-                           k_anim_apply_deffered_only, final_mtx );
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_deffered_only, final_mtx );
       skeleton_apply_inverses( sk, final_mtx );
       skeleton_apply_transform( sk, transform, final_mtx );
    }
-   else if( pose->type == k_player_pose_type_fk_2 ){
-      skeleton_apply_pose( sk, pose->keyframes, 
-                           k_anim_apply_always, final_mtx );
+   else if( pose->type == k_player_pose_type_fk_2 )
+   {
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_always, final_mtx );
       skeleton_apply_inverses( sk, final_mtx );
       skeleton_apply_transform( sk, transform, final_mtx );
    }
@@ -255,7 +253,7 @@ void player__animate(void)
    player_pose *pose = &localplayer.pose;
    sys->pose( sys->animator_data, pose );
 
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    if( localplayer.holdout_time > 0.0f )
    {
@@ -298,7 +296,7 @@ static void player_copy_frame_animator( replay_frame *frame )
 
 void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed )
 {
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    
    v3_lerp( pose0->root_co, pose1->root_co, t, posed->root_co );
    q_nlerp( pose0->root_q,  pose1->root_q,  t, posed->root_q );
@@ -341,7 +339,7 @@ void player__pre_render(void)
       v3_zero( vp1 );
    }
 
-   struct ub_world_lighting *ubo = &_world.main.ub_lighting;
+   struct ub_world_lighting *ubo = &world_render.ub_lighting;
    v3f *board_mtx = localplayer.final_mtx[ localplayer.id_board ];
    m4x3_mulv( board_mtx, vp0, ubo->g_board_0 );
    m4x3_mulv( board_mtx, vp1, ubo->g_board_1 );
@@ -350,7 +348,7 @@ void player__pre_render(void)
 void render_board( vg_camera *cam, world_instance *world,
                    struct player_board *board, m4x3f root,
                    struct player_board_pose *pose,
-                   enum board_shader shader )
+enum board_shader shader )
 {
    if( !board ) 
       board = &localplayer.fallback_board;
@@ -360,11 +358,8 @@ void render_board( vg_camera *cam, world_instance *world,
     */
 
    v3f inverse;
-
-   VG_ASSERT( board->mdl.texture_count );
-
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, board->mdl.textures[0].glname );
+   VG_ASSERT( board->model.texture_count );
+   vg_tex_bind( GL_TEXTURE_2D, &board->model.textures[0].tex, 0 );
 
    if( shader == k_board_shader_player )
    {
@@ -380,7 +375,7 @@ void render_board( vg_camera *cam, world_instance *world,
          shader_model_board_view_uInverseRatioMain,
          cam );
 
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_board_view );
+      WORLD_LINK_LIGHTING( world, model_board_view );
    }
    else if( shader == k_board_shader_entity )
    {
@@ -389,11 +384,10 @@ void render_board( vg_camera *cam, world_instance *world,
       shader_model_entity_uCamera( cam->transform[3] );
       shader_model_entity_uPv( cam->mtx.pv );
       
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+      WORLD_LINK_LIGHTING( world, model_entity );
    }
 
-   mesh_bind( &board->mdl.mesh );
-
+   vg_model_bind_mesh( &board->model );
    m4x4f m4mdl;
 
    if( board->board.indice_count )
@@ -424,8 +418,7 @@ void render_board( vg_camera *cam, world_instance *world,
       }
       else
          shader_model_board_view_uMdl( mlocal );
-
-      mdl_draw_submesh( &board->board );
+      vg_model_draw_submesh( &board->board );
    }
 
    for( int i=0; i<2; i++ ){
@@ -437,7 +430,8 @@ void render_board( vg_camera *cam, world_instance *world,
       v3_copy( board->truck_positions[i], mlocal[3] );
       m4x3_mul( root, mlocal, mlocal );
 
-      if( shader == k_board_shader_entity ){
+      if( shader == k_board_shader_entity )
+      {
          m4x3_expand( mlocal, m4mdl );
          m4x4_mul( cam->mtx_prev.pv, m4mdl, m4mdl );
          shader_model_entity_uPvmPrev( m4mdl );
@@ -446,7 +440,7 @@ void render_board( vg_camera *cam, world_instance *world,
       else
          shader_model_board_view_uMdl( mlocal );
 
-      mdl_draw_submesh( &board->trucks[i] );
+      vg_model_draw_submesh( &board->trucks[i] );
    }
 
    for( int i=0; i<4; i++ ){
@@ -458,7 +452,8 @@ void render_board( vg_camera *cam, world_instance *world,
       v3_copy( board->wheel_positions[i], mlocal[3] );
       m4x3_mul( root, mlocal, mlocal );
 
-      if( shader == k_board_shader_entity ){
+      if( shader == k_board_shader_entity )
+      {
          m4x3_expand( mlocal, m4mdl );
          m4x4_mul( cam->mtx_prev.pv, m4mdl, m4mdl );
          shader_model_entity_uPvmPrev( m4mdl );
@@ -467,14 +462,14 @@ void render_board( vg_camera *cam, world_instance *world,
       else
          shader_model_board_view_uMdl( mlocal );
 
-      mdl_draw_submesh( &board->wheels[i] );
+      vg_model_draw_submesh( &board->wheels[i] );
    }
 }
 
 void render_playermodel( vg_camera *cam, world_instance *world,
                          int depth_compare,
                          player_model_view *view,
-                         struct skeleton *skeleton,
+                         ms_skeleton *skeleton,
                          m4x3f *final_mtx )
 {
    bool fallback = 0;
@@ -489,9 +484,8 @@ void render_playermodel( vg_camera *cam, world_instance *world,
    
    shader_model_character_view_use();
 
-       glActiveTexture( GL_TEXTURE0 );
-   VG_ASSERT( model->mdl.texture_count );
-   glBindTexture( GL_TEXTURE_2D, model->mdl.textures[0].glname );
+   VG_ASSERT( model->model.texture_count );
+   vg_tex_bind( GL_TEXTURE_2D, &model->model.textures[0].tex, 0 );
 
    shader_model_character_view_uTexMain( 0 );
    shader_model_character_view_uCamera( cam->transform[3] );
@@ -509,15 +503,10 @@ void render_playermodel( vg_camera *cam, world_instance *world,
          cam );
    }
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view );
-
-   glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms,
-                         skeleton->bone_count,
-                         0,
-                         (const GLfloat *)final_mtx );
+   WORLD_LINK_LIGHTING( world, model_character_view );
+   shader_model_character_view_uTransforms( final_mtx, skeleton->bone_count );
    
-   mesh_bind( &model->mdl.mesh );
-
+   vg_model_bind_mesh( &model->model );
    if( !fallback && (model->flags & PLAYER_MODEL_FLAG_CUSTOMIZABLE) )
    {
       if( view->cpart_dirty )
@@ -536,13 +525,23 @@ void render_playermodel( vg_camera *cam, world_instance *world,
             if( (0x1 << j) & item->discard_mask & view->discard )
                continue;
 
-            mdl_submesh *sm = &model->mdl.submeshes[ item->submesh_start + j ];
-            mdl_draw_submesh( sm );
+            mdl_submesh *sm = &model->model.submeshes[ item->submesh_start + j ];
+            vg_model_draw_submesh( sm );
          }
       }
    }
    else
-      mesh_draw( &model->mdl.mesh );
+   {
+      for( u32 i=0; i<model->model.mesh_count; i ++ )
+      {
+         mdl_mesh *mesh = &model->model.meshes[ i ];
+         for( u32 j=0; j<mesh->submesh_count; j ++ )
+         {
+            mdl_submesh *sm = &model->model.submeshes[ mesh->submesh_start+j ];
+            vg_model_draw_submesh( sm );
+         }
+      }
+   }
 }
 
 void player__render( vg_camera *cam )
@@ -560,7 +559,7 @@ void player__render( vg_camera *cam )
    if( localplayer.has_battery )
    {
       ms_keyframe kf_backpack;
-      struct skeleton *sk = &localplayer.skeleton;
+      ms_skeleton *sk = &localplayer.skeleton;
       m4x3_mulv( localplayer.final_mtx[localplayer.id_chest ], sk->bones[localplayer.id_chest].co, kf_backpack.co );
 
       v4f qyaw, qpitch, qchest, q;
@@ -585,8 +584,7 @@ void player__render( vg_camera *cam )
 void player_mirror_pose( ms_keyframe pose[32], ms_keyframe mirrored[32] )
 {
    ms_keyframe temp[32];
-
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    for( u32 i=1; i<sk->bone_count; i ++ )
    {
       ms_keyframe *dest = &temp[i-1];
@@ -660,7 +658,7 @@ void playermodel_create_binary_configuration( player_model_view *view, struct pl
          view->property_values[i]._f32 = ((f32)(c - (u8)'A') / (f32)((u8)'Z' - (u8)'A')) * prop->max._f32;
       else if( prop->ui_type == k_editer_type_selecter )
       {
-         const char *options = af_str( &model->mdl.af, prop->max.pstr_options );
+         const char *options = af_str( model->model.packed_strings, prop->max.pstr_options );
          bool valid = 0;
          for( u32 j=0; options[j]; j ++ )
          {
@@ -686,7 +684,7 @@ void playermodel_create_binary_configuration( player_model_view *view, struct pl
    for( u32 i=0; i<af_arrcount( &model->editer_item ); i ++ )
    {
       editer_item *item = af_arritm( &model->editer_item, i );
-      const char *visibility_string = af_str( &model->mdl.af, item->pstr_visibility );
+      const char *visibility_string = af_str( model->model.packed_strings, item->pstr_visibility );
       bool visible = 1;
 
       u32 hash;
@@ -738,9 +736,9 @@ void playermodel_create_binary_configuration( player_model_view *view, struct pl
                   if( prop->ui_type == k_editer_type_slider )
                      continue;
 
-                  if( af_str_hash( &model->mdl.af, prop->pstr_alias ) == hash )
+                  if( af_str_hash( model->model.packed_strings, prop->pstr_alias ) == hash )
                   {
-                     const char *alias = af_str( &model->mdl.af, prop->pstr_alias );
+                     const c8 *alias = af_str( model->model.packed_strings, prop->pstr_alias );
                      bool matched = 1;
                      for( u32 l=0; l < (j-token_j); l ++ )
                      {
index f3c57acbf0debcc6e8778d2ce21a2529fc219ceb..0d2a75ea2ec6ca7222958d80ca5b6abfa5904f03 100644 (file)
@@ -1,10 +1,6 @@
-#pragma once
-#include "model.h"
-#include "skeleton.h"
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "player_render.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_render.c"
+#else
 
 enum eboard_truck{
    k_board_truck_back = 0,
@@ -21,8 +17,7 @@ enum eboard_wheel{
 typedef struct player_board player_board;
 struct player_board
 {
-   mdl_context mdl;
-
+   vg_model model;
    v4f wheel_positions[4],
        truck_positions[2],
        board_position;
@@ -37,7 +32,7 @@ struct player_board
 typedef struct player_model player_model;
 struct player_model
 {
-   mdl_context mdl;
+   vg_model model;
    u32 flags;
    array_file_ptr editer_property, editer_item;
    u32 list_id_heads;
@@ -75,10 +70,12 @@ enum board_shader{
    k_board_shader_entity
 };
 
-void player_board_load( player_board *board, const char *path, void *arena );
+VG_API void _player_render_init(void);
+
+void player_board_load( player_board *board, const c8 *path, vg_stack_allocator *stack );
 void player_board_unload( player_board *mdl );
 
-void player_model_load( player_model *pm, const char *path, void *arena );
+void player_model_load( player_model *pm, const c8 *path, vg_stack_allocator *stack );
 void player_model_unload( player_model *pm );
 
 void render_board( vg_camera *cam, world_instance *world,
@@ -89,9 +86,9 @@ void render_board( vg_camera *cam, world_instance *world,
 void render_playermodel( vg_camera *cam, world_instance *world,
                          int depth_compare,
                          player_model_view *playermodel,
-                         struct skeleton *skeleton,
+                         ms_skeleton *skeleton,
                          m4x3f *final_mtx );
-void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose, m4x3f *final_mtx );
+void apply_full_skeleton_pose( ms_skeleton *sk, player_pose *pose, m4x3f *final_mtx );
 void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed );
 void player_mirror_pose( ms_keyframe pose[32], ms_keyframe mirrored[32] );
 void player__observe_system( enum player_subsystem id );
@@ -105,3 +102,5 @@ void playermodel_get_cpart( player_model_view *view, struct player_model *model,
 void playermodel_use_cpart( player_model_view *model, const char cpart[ ADDON_CPART_MAX ] );
 void playermodel_create_binary_configuration( player_model_view *view, struct player_model *model );
 void playermodel_set_from_uid( player_model_view *model, const char uid[ ADDON_UID_MAX ] );
+
+#endif
index 29e3b35db44eca93f80b4301f9427194d9407f6f..339ee19a04fc293a808e12d95f3ea01e90cad485 100644 (file)
@@ -1,26 +1,8 @@
-#include "player_skate.h"
-#include "player.h"
-#include "audio.h"
-#include "vg/vg_perlin.h"
-#include "vg/vg_lines.h"
-#include "menu.h"
-#include "ent_skateshop.h"
-#include "addon.h"
-#include "input.h"
-#include "ent_tornado.h"
-
-#include "vg/vg_rigidbody.h"
-#include "scene_rigidbody.h"
-#include "player_glide.h"
-#include "player_dead.h"
-#include "player_walk.h"
-#include <string.h>
-
 struct player_skate player_skate;
 struct player_subsystem_interface player_subsystem_skate = 
 {
    .system_register = player__skate_register,
-   .bind = player__skate_bind,
+   .load_resources = player__skate_load_resources,
    .pre_update = player__skate_pre_update,
    .update = player__skate_update,
    .transport = player__skate_transport,
@@ -40,12 +22,13 @@ struct player_subsystem_interface player_subsystem_skate =
    .name = "Skate"
 };
 
-void player__skate_bind(void){
-   struct skeleton *sk = &localplayer.skeleton;
-   rb_update_matrices( &localplayer.rb );
-
-   struct { struct skeleton_anim *anim; const char *name; }
-   bindings[] = {
+void player__skate_load_resources(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   ms_skeleton *sk = &localplayer.skeleton;
+   struct { ms_skeletal_animation *anim; const char *name; }
+   bindings[] = 
+   {
       { &player_skate.anim_grind,        "pose_grind" },
       { &player_skate.anim_grind_jump,   "pose_grind_jump" },
       { &player_skate.anim_stand,        "pose_stand" },
@@ -64,6 +47,11 @@ void player__skate_bind(void){
       player_get_anim( bindings[i].anim, bindings[i].name );
 }
 
+void player__skate_init(void)
+{
+   rb_update_matrices( &localplayer.rb );
+}
+
 void player__skate_kill_audio(void)
 {
    vg_audio_lock();
@@ -96,17 +84,16 @@ static int skate_collide_smooth( m4x3f mtx, f32 r, rb_ct *man ){
    world_instance *world = &_world.main;
 
    int len = 0;
-   len = rb_sphere__scene( mtx, r, NULL, world->geo_bh, man,
-                           k_material_flag_walking );
-
-   for( int i=0; i<len; i++ ){
+   len = rb_sphere__scene( mtx, r, NULL, &world->geometry_bh, man, k_material_flag_walking );
+   for( int i=0; i<len; i++ )
+   {
       man[i].rba = &localplayer.rb;
       man[i].rbb = NULL;
    }
 
    rb_manifold_filter_coplanar( man, len, 0.03f );
-
-   if( len > 1 ){
+   if( len > 1 )
+   {
       rb_manifold_filter_backface( man, len );
       rb_manifold_filter_joint_edges( man, len, 0.03f );
       rb_manifold_filter_pairs( man, len, 0.03f );
@@ -158,8 +145,9 @@ static int skate_grind_scansq( v3f pos, v3f dir, float r,
    bh_iter_init_box( 0, &it, box );
    i32 idx;
    
-   while( bh_next( world->geo_bh, &it, &idx ) ){
-      u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
+   while( bh_next( &world->geometry_bh, &it, &idx ) )
+   {
+      u32 *ptri = &world->scene_geometry.indice_buffer[ idx*3 ];
       v3f tri[3];
 
       struct world_surface *surf = world_tri_index_surface(world,ptri[0]);
@@ -167,7 +155,7 @@ static int skate_grind_scansq( v3f pos, v3f dir, float r,
          continue;
 
       for( int j=0; j<3; j++ )
-         v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
+         v3_copy( world->scene_geometry.vertex_buffer[ptri[j]].co, tri[j] );
 
       for( int j=0; j<3; j++ ){
          int i0 = j,
@@ -468,7 +456,7 @@ void player__approximate_best_trajectory(void)
          v3f closest={0.0f,0.0f,0.0f};
          if( search_for_grind )
          {
-            if( bh_closest_point(trace_world->geo_bh,co1,closest,1.0f) != -1 )
+            if( bh_closest_point( &trace_world->geometry_bh,co1,closest,1.0f ) != -1 )
             {
                float min_dist = 0.75f;
                      min_dist *= min_dist;
@@ -552,7 +540,7 @@ void player__approximate_best_trajectory(void)
             v3_copy( co, inf->log[ inf->log_length ++ ] ); 
 
             v3_copy( n, inf->n );
-            u32 *tri = &trace_world->scene_geo.arrindices[ idx*3 ];
+            u32 *tri = &trace_world->scene_geometry.indice_buffer[ idx*3 ];
             struct world_surface *surf = 
                world_tri_index_surface( trace_world, tri[0] );
 
@@ -1198,18 +1186,18 @@ static enum trick_type player_skate_trick_input(void){
           (button_press( k_srbind_trick2 )     );
 }
 
-void player__skate_pre_update(void){
+void player__skate_pre_update(void)
+{
    struct player_skate_state *state = &player_skate.state;
 
-   if( state->activity == k_skate_activity_handplant ){
+   if( state->activity == k_skate_activity_handplant )
+   {
       state->handplant_t += vg.time_delta;
       ms_keyframe hpose[32];
 
-      struct skeleton_anim *anim = &player_skate.anim_handplant;
+      ms_skeletal_animation *anim = &player_skate.anim_handplant;
 
-      int end = !skeleton_sample_anim_clamped( 
-               &localplayer.skeleton, anim,
-               state->handplant_t, hpose );
+      int end = !skeleton_sample_anim_clamped( &localplayer.skeleton, anim, state->handplant_t, hpose );
 
       if( state->reverse < 0.0f )
          player_mirror_pose( hpose, hpose );
@@ -1619,14 +1607,14 @@ int skate_compute_surface_alignment( v3f ra, u32 colour,
    else{
       /* fallback: use the closes point to the trucks */
       v3f closest;
-      int idx = bh_closest_point( world->geo_bh, midpoint, closest, 0.1f );
-
-      if( idx != -1 ){
-         u32 *tri = &world->scene_geo.arrindices[ idx * 3 ];
+      int idx = bh_closest_point( &world->geometry_bh, midpoint, closest, 0.1f );
+      if( idx != -1 )
+      {
+         u32 *tri = &world->scene_geometry.indice_buffer[ idx * 3 ];
          v3f verts[3];
 
          for( int j=0; j<3; j++ )
-            v3_copy( world->scene_geo.arrvertices[ tri[j] ].co, verts[j] );
+            v3_copy( world->scene_geometry.vertex_buffer[ tri[j] ].co, verts[j] );
 
          v3f vert0, vert1, n;
          v3_sub( verts[1], verts[0], vert0 );
@@ -1638,8 +1626,7 @@ int skate_compute_surface_alignment( v3f ra, u32 colour,
             return 0;
 
          v3_cross( n, localplayer.rb.to_world[2], v0 );
-         v3_muladds( v0, localplayer.rb.to_world[2],
-                     -v3_dot( localplayer.rb.to_world[2], v0 ), v0 );
+         v3_muladds( v0, localplayer.rb.to_world[2], -v3_dot( localplayer.rb.to_world[2], v0 ), v0 );
          v3_normalize( v0 );
 
          v3f t;
@@ -2325,15 +2312,16 @@ void player__skate_update(void)
 
    float slap = 0.0f;
 
-   if( state->activity <= k_skate_activity_air_to_grind ){
+   if( state->activity <= k_skate_activity_air_to_grind )
+   {
       float min_dist = 0.6f;
-      for( int i=0; i<2; i++ ){
+      for( int i=0; i<2; i++ )
+      {
          v3f wpos, closest;
          m4x3_mulv( localplayer.rb.to_world, wheels[i].pos, wpos );
 
-         if( bh_closest_point( world->geo_bh, wpos, closest, min_dist ) != -1 ){
+         if( bh_closest_point( &world->geometry_bh, wpos, closest, min_dist ) != -1 )
             min_dist = vg_minf( min_dist, v3_dist( closest, wpos ) );
-         }
       }
       min_dist -= 0.2f;
       float vy = vg_maxf( 0.0f, localplayer.rb.v[1] );
@@ -2603,7 +2591,7 @@ begin_collision:;
 
    /* board capsule */
    rb_ct *cman = &manifold[manifold_len];
-   int l = rb_capsule__scene( mtx, &capsule, NULL, world->geo_bh, cman, k_material_flag_walking );
+   int l = rb_capsule__scene( mtx, &capsule, NULL, &world->geometry_bh, cman, k_material_flag_walking );
    /* weld joints */
    for( int i=0; i<l; i ++ )
       cman[l].type = k_contact_type_edge;
@@ -3207,8 +3195,9 @@ void player__skate_animate(void){
    animator->handplant_t = state->handplant_t;
 }
                         
-void player__skate_pose( void *_animator, player_pose *pose ){
-   struct skeleton *sk = &localplayer.skeleton;
+void player__skate_pose( void *_animator, player_pose *pose )
+{
+   ms_skeleton *sk = &localplayer.skeleton;
    struct player_skate_animator *animator = _animator;
 
    pose->type = k_player_pose_type_ik;
@@ -3258,19 +3247,15 @@ void player__skate_pose( void *_animator, player_pose *pose ){
       skeleton_lerp_pose( sk, bpose, mirrored, animator->z, bpose );
       skeleton_lerp_pose( sk, apose, bpose, animator->slide, apose );
 
-      if( animator->reverse > 0.0f ){
-         skeleton_sample_anim( sk, &player_skate.anim_push, animator->push_time, 
-                               bpose );
-      }
-      else{
-         skeleton_sample_anim( sk, &player_skate.anim_push_reverse, 
-                               animator->push_time, bpose );
-      }
+      if( animator->reverse > 0.0f )
+         skeleton_sample_anim( sk, &player_skate.anim_push, animator->push_time, bpose );
+      else
+         skeleton_sample_anim( sk, &player_skate.anim_push_reverse, animator->push_time, bpose );
       skeleton_lerp_pose( sk, apose, bpose, animator->push, apose );
 
-      struct skeleton_anim *jump_anim = animator->jump_dir?
-                                        &player_skate.anim_ollie:
-                                        &player_skate.anim_ollie_reverse;
+      ms_skeletal_animation *jump_anim = animator->jump_dir?
+                                         &player_skate.anim_ollie:
+                                         &player_skate.anim_ollie_reverse;
 
       f32 setup_blend = vg_minf( animator->jump, 1.0f );
       skeleton_sample_anim_clamped( sk, jump_anim, animator->jump_time, bpose );
@@ -3348,7 +3333,7 @@ void player__skate_pose( void *_animator, player_pose *pose ){
 
    if( animator->activity == k_skate_activity_handplant )
    {
-      struct skeleton_anim *anim = &player_skate.anim_handplant;
+      ms_skeletal_animation *anim = &player_skate.anim_handplant;
 
       ms_keyframe hpose[32];
       skeleton_sample_anim_clamped( sk, anim, animator->handplant_t, hpose );
@@ -3537,7 +3522,7 @@ void player__skate_effects( void *_animator, m4x3f *final_mtx,
                                    struct player_board *board,
                                    struct player_effects_data *effect_data )
 {
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    struct player_skate_animator *animator = _animator;
 
    v3f vp0, vp1, vpc;
index 207873cf765da821eb12f067c0a6147496972f14..4b0dc3d017c22cf8d198142d85cc70b1ee99183a 100644 (file)
@@ -1,7 +1,6 @@
-#pragma once
-#include "vg/vg_audio.h"
-#include "player.h"
-#include "player_api.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_skate.c"
+#else
 
 typedef struct jump_info jump_info;
 
@@ -151,12 +150,12 @@ struct player_skate{
 
    /* animation /audio
     * --------------------------------------------------------------*/
-   struct skeleton_anim anim_stand, anim_highg, anim_slide,
-                        anim_air,   anim_grind, anim_grind_jump,
-                        anim_push,  anim_push_reverse,
-                        anim_ollie, anim_ollie_reverse,
-                        anim_grabs, anim_stop,
-                        anim_handplant;
+   ms_skeletal_animation anim_stand, anim_highg, anim_slide,
+                         anim_air,   anim_grind, anim_grind_jump,
+                         anim_push,  anim_push_reverse,
+                         anim_ollie, anim_ollie_reverse,
+                         anim_grabs, anim_stop,
+                         anim_handplant;
 
    /* vectors representing the direction of the axels in localspace */
    v3f truckv0[2];
@@ -305,7 +304,7 @@ static void player__skate_register(void)
    VG_VAR_F32( k_anim_transition,      flags=VG_VAR_CHEAT );
 }
 
-void player__skate_bind         (void);
+void player__skate_load_resources(void);
 void player__skate_pre_update   (void);
 void player__skate_update       (void);
 void player__skate_transport( m4x3f transport );
@@ -325,3 +324,5 @@ void player__skate_reset_animator(void);
 void player__approximate_best_trajectory(void);
 void player__skate_comp_audio( void *animator );
 void player__skate_kill_audio(void);
+
+#endif
index ff43934e5c4ee57be63aa3dde10130fa17cd5323..526660e7e21d3c51f84cb7c0dfc3ee2f8a77c78e 100644 (file)
@@ -1,19 +1,8 @@
-#include "vg/vg_rigidbody_collision.h"
-
-#include "skaterift.h"
-#include "player_walk.h"
-#include "player_skate.h"
-#include "player_dead.h"
-#include "player.h"
-#include "input.h"
-#include "audio.h"
-#include "scene_rigidbody.h"
-
 struct player_walk player_walk;
 struct player_subsystem_interface player_subsystem_walk = 
 {
    .system_register = player__walk_register,
-   .bind = player__walk_bind,
+   .load_resources = player__walk_load_resources,
    .pre_update = player__walk_pre_update,
    .update = player__walk_update,
    .transport = player__walk_transport,
@@ -246,7 +235,7 @@ static int player_walk_scan_for_drop_in(void){
    return 0;
 }
 
-static bool player__preupdate_anim( struct skeleton_anim *anim, f32 *t, f32 speed )
+static bool player__preupdate_anim( ms_skeletal_animation *anim, f32 *t, f32 speed )
 {
    f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate;
    *t += (vg.time_delta * speed) / length;
@@ -502,7 +491,7 @@ static void player_walk_update_generic(void)
     * Collision detection
     */
 
-   len = rb_capsule__scene( mtx, &w->collider, NULL, world->geo_bh, manifold, 0 );
+   len = rb_capsule__scene( mtx, &w->collider, NULL, &world->geometry_bh, manifold, 0 );
 
    for( u32 i=0; i<af_arrcount( &world->ent_prop ); i ++ )
    {
@@ -854,7 +843,7 @@ static void player_walk_animate_drop_in(void)
 {
    struct player_walk *w = &player_walk;
    struct player_walk_animator *animator = &w->animator;
-   struct skeleton_anim *anim = &w->anim_drop_in;
+   ms_skeletal_animation *anim = &w->anim_drop_in;
 
    f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate,
        time   = w->state.transition_t;
@@ -986,7 +975,7 @@ static void player_walk_pose_sit( struct player_walk_animator *animator, player_
    ms_keyframe bpose[32];
 
    struct player_walk *w = &player_walk;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    f32 t  = animator->transition_t,
        st = t * ((f32)(w->anim_sit.strip->strip.length-1)/30.0f);
@@ -1016,14 +1005,14 @@ enum walk_transition_type {
 };
 
 static void player_walk_pose_transition( 
-      struct player_walk_animator *animator, struct skeleton_anim *anim,
+      struct player_walk_animator *animator, ms_skeletal_animation *anim,
       enum walk_transition_type type,
       ms_keyframe apose[32], f32 *mask, player_pose *pose ){
 
    ms_keyframe bpose[32];
 
    struct player_walk *w = &player_walk;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
    
    f32 length   = (f32)(anim->strip->strip.length-1) / anim->framerate,
        t        = animator->transition_t * length,
@@ -1058,7 +1047,7 @@ static void player_walk_pose_transition(
 void player__walk_pose( void *_animator, player_pose *pose ){
    struct player_walk *w = &player_walk;
    struct player_walk_animator *animator = _animator;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    v3_copy( animator->root_co, pose->root_co );
    v4_copy( animator->root_q, pose->root_q );
@@ -1193,10 +1182,10 @@ void player__walk_im_gui( ui_context *ctx )
                                              [w->surface] );
 }
 
-void player__walk_bind(void)
+void player__walk_load_resources(void)
 {
    struct player_walk *w = &player_walk;
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    player_get_anim( &w->anim_idle,        "idle_cycle+y" );
    player_get_anim( &w->anim_walk,        "walk+y" );
index 50c1a7c508e58588f48a85543b508991bbc870be..b315623aed9290647d91b1f779242c69ac6a3f46 100644 (file)
@@ -1,7 +1,6 @@
-#pragma once
-#include "player.h"
-#include "player_api.h"
-#include "vg/vg_rigidbody.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/player_walk.c"
+#else
 
 #define PLAYER_JUMP_EPSILON 0.1     /* 100ms jump allowance */
 
@@ -49,9 +48,9 @@ struct player_walk
    f32 move_speed;
 
    enum mdl_surface_prop surface;
-   struct skeleton_anim anim_walk, anim_run, anim_idle, anim_jump,
-                        anim_jump_to_air, anim_drop_in, anim_intro,
-                        anim_sit, anim_popoff;
+   ms_skeletal_animation anim_walk, anim_run, anim_idle, anim_jump,
+                         anim_jump_to_air, anim_drop_in, anim_intro,
+                         anim_sit, anim_popoff;
 
    struct player_walk_animator {
       v3f root_co;
@@ -106,10 +105,12 @@ void player__walk_animate     (void);
 void player__walk_pose        (void *animator, player_pose *pose);
 void player__walk_post_animate(void);
 void player__walk_im_gui      ( ui_context *ctx );
-void player__walk_bind        (void);
+void player__walk_load_resources(void);
 void player__walk_reset       (void);
 void player__walk_restore     (void);
 void player__walk_animator_exchange( bitpack_ctx *ctx, void *data );
 void player__walk_transition( bool grounded, f32 board_yaw );
 void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume );
 void player__walk_upright(void);
+
+#endif
index 32238354f126b602bbe2121a1e5d0823f891b941..97f8e65798523a70e04c024a929ccb84e2e507c5 100644 (file)
@@ -1,77 +1,17 @@
-#include "render.h"
-#include "vg/vg_engine.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_framebuffer.h"
-
-static void async_render_init( void *userdata )
-{
-   THREAD_0;
-   f32 rh = 0x1p-4f, ih = 0.3f;
-
-   float quad[] = { 
-      0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,    /* fsquad */
-      0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,    
-
-      0.00f,0.00f, 1.00f,rh,     0.00f,rh,    /* fsquad1 */
-      0.00f,0.00f, 1.00f,0.00f,  1.00f,rh,
-      0.00f,1.00f, 0.00f,1.0f-rh,1.00f,1.0f-rh,
-      0.00f,1.00f, 1.00f,1.0f-rh,1.00f,1.0f,   
-
-      /* 9x9 debug grid */
-      /* row0 */
-      0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
-      0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
-      0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
-      0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
-      0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
-      0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
-      /* row1 */
-      0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
-      0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
-      0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
-      0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
-      0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
-      0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
-      /* row2 */
-      0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
-      0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
-      0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
-      0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
-      0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
-      0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
-
-      0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh,    /* fsquad2 */
-      0.00f,ih, 1.00f,ih,    1.00f,ih+rh,
-   };
-
-   glGenVertexArrays( 1, &g_render.fsquad.vao );
-   glGenBuffers( 1, &g_render.fsquad.vbo );
-   glBindVertexArray( g_render.fsquad.vao );
-   glBindBuffer( GL_ARRAY_BUFFER, g_render.fsquad.vbo );
-   glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
-   glBindVertexArray( g_render.fsquad.vao );
-   glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 
-                          sizeof(float)*2, (void*)0 );
-   glEnableVertexAttribArray( 0 );
-
-   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   g_render.ready = 1;
-}
-
-void render_register(void)
+VG_API void _render_register(void)
 {
    vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
    vg_console_reg_var( "cam_height", &k_cam_height, k_var_dtype_f32, VG_VAR_PERSISTENT );
 }
 
-void render_init(void)
+VG_API void _render_init(void)
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    /* 
     * Workshop preview
     */
-   g_render.fb_workshop_preview = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
+   g_render.fb_workshop_preview = _vg_framebuffer_alloc( NULL, 2, 1 );
    g_render.fb_workshop_preview->display_name = "workshop_preview";
    g_render.fb_workshop_preview->resolution_div = 0;
    g_render.fb_workshop_preview->fixed_w = WORKSHOP_PREVIEW_WIDTH;
@@ -90,12 +30,12 @@ void render_init(void)
       .internalformat = GL_DEPTH24_STENCIL8,
       .attachment = GL_DEPTH_STENCIL_ATTACHMENT
    };
-   vg_framebuffer_create( g_render.fb_workshop_preview );
+   vg_framebuffer_init( g_render.fb_workshop_preview );
    
    /*
     * Network status
     */
-   g_render.fb_network_status = vg_framebuffer_allocate( &vg.rtmem, 1, 1 );
+   g_render.fb_network_status = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 1 );
    g_render.fb_network_status->display_name = "network_status_ui";
    g_render.fb_network_status->resolution_div = 0;
    g_render.fb_network_status->fixed_w = 128;
@@ -108,9 +48,9 @@ void render_init(void)
       .type           = GL_UNSIGNED_BYTE,
       .attachment     = GL_COLOR_ATTACHMENT0
    };
-   vg_framebuffer_create( g_render.fb_network_status );
+   vg_framebuffer_init( g_render.fb_network_status );
 
-   g_render.fb_compass = vg_framebuffer_allocate( &vg.rtmem, 1, 1 );
+   g_render.fb_compass = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 1 );
    g_render.fb_compass->display_name = "compass";
    g_render.fb_compass->resolution_div = 0;
    g_render.fb_compass->fixed_w = 800;
@@ -123,28 +63,75 @@ void render_init(void)
       .type           = GL_UNSIGNED_BYTE,
       .attachment     = GL_COLOR_ATTACHMENT0
    };
-   vg_framebuffer_create( g_render.fb_compass );
+   vg_framebuffer_init( g_render.fb_compass );
+
+   f32 rh = 0x1p-4f, ih = 0.3f;
+
+   /* TODO: Is this duplicated with vg_render? */
+   f32 quad[] = 
+   { 
+      0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,    /* fsquad */
+      0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,    
+
+      0.00f,0.00f, 1.00f,rh,     0.00f,rh,    /* fsquad1 */
+      0.00f,0.00f, 1.00f,0.00f,  1.00f,rh,
+      0.00f,1.00f, 0.00f,1.0f-rh,1.00f,1.0f-rh,
+      0.00f,1.00f, 1.00f,1.0f-rh,1.00f,1.0f,   
+
+      /* 9x9 debug grid */
+      /* row0 */
+      0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
+      0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
+      0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
+      0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
+      0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
+      0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
+      /* row1 */
+      0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
+      0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
+      0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
+      0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
+      0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
+      0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
+      /* row2 */
+      0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
+      0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
+      0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
+      0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
+      0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
+      0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
+
+      0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh,    /* fsquad2 */
+      0.00f,ih, 1.00f,ih,    1.00f,ih+rh,
+   };
 
-   vg_async_call( &vg.main_tasks, async_render_init, NULL );
+   glGenVertexArrays( 1, &g_render.fsq_vao );
+   glBindVertexArray( g_render.fsq_vao );
+   glGenBuffers( 1, &g_render.fsq_vbo );
+   glBindBuffer( GL_ARRAY_BUFFER, g_render.fsq_vbo );
+   glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
+   glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, (void*)0 );
+   glEnableVertexAttribArray( 0 );
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
 }
 
 /*
- * Utility
+ * Utility (TODO: ARE THESE DUPED WITH VG CODE???????????????????????)
  */
 void render_fsquad(void)
 {
-   glBindVertexArray( g_render.fsquad.vao );
+   glBindVertexArray( g_render.fsq_vao );
    glDrawArrays( GL_TRIANGLES, 0, 6 );
 }
 
 void render_fsquad1(void)
 {
-   glBindVertexArray( g_render.fsquad.vao );
+   glBindVertexArray( g_render.fsq_vao );
    glDrawArrays( GL_TRIANGLES, 6, 6+6 );
 }
 
 void render_fsquad2(void)
 {
-   glBindVertexArray( g_render.fsquad.vao );
+   glBindVertexArray( g_render.fsq_vao );
    glDrawArrays( GL_TRIANGLES, 66+6,6 );
 }
index 3024f21cc7f0718633254fc797de48b4279cb78f..2607e4604acbc8f051ba395c53dd4ab5ff7d9e8b 100644 (file)
@@ -1,16 +1,6 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-#pragma once
-#include "common.h"
-#include "model.h"
-#include "shader_props.h"
-#include "vg/vg_framebuffer.h"
-#include "vg/vg_camera.h"
-
-#include "shaders/blitblur.h"
-#include "shaders/blitcolour.h"
-#include "shaders/blit_transition.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/render.c"
+#else
 
 #define WORKSHOP_PREVIEW_WIDTH  504
 #define WORKSHOP_PREVIEW_HEIGHT 336
@@ -23,21 +13,22 @@ static f32 k_cam_height    = 0.8f;
  */
 struct pipeline
 {
-   glmesh fsquad;
+   GLuint fsq_vao, fsq_vbo;
 
    vg_framebuffer *fb_workshop_preview,
                   *fb_network_status,
                   *fb_compass;
-   int ready;
-
    v2f blur_override;
    vg_camera cam;
 }
 static g_render;
 
-void render_register(void);
-void render_init(void);
+void _render_register(void);
+VG_API void _render_init(void);
+
 void render_fsquad(void);
 void render_fsquad1(void);
 void render_fsquad2(void);
 void postprocess_to_screen( vg_framebuffer *fb );
+
+#endif
index 9ff3302364c28eee7bd9fda25611057792439e3e..ff9340a7c98975fb7e35b910bb66f29cc486ab7d 100644 (file)
@@ -1,7 +1,115 @@
-#include "replay2.h"
+struct _replay2
+{
+   enum replay_type type;
+
+   vg_queue buffer;
+
+   /* TODO: Modifiers / keyframes lane */
+   
+   u32 cursor_frame_offset;
+   f64 cursor;
+   enum replay_control {
+      k_replay_control_scrub = 0x00,
+      k_replay_control_play  = 0x01,
+      k_replay_control_resume= 0x02
+   }
+   replay_control;
+   f32 track_velocity;
+
+   bool cursor_decoded;
+
+   struct net_sfx sfx_queue[ 8 ];
+   u32 sfx_queue_length;
+   f64 sfx_basetime;
+
+   vg_camera replay_freecam, playback_cam;
+   bool use_freecam;
+   bool hide_ui;
+   v3f freecam_v, freecam_w;
+
+   f64 start_t, end_t;
+   bool highlight;
+   f64 highlight_start, highlight_length;
+
+   bool animation_dirty;
+   addon_cache_id board_cache_id;
+   player_model_view playermodel;
+
+   struct player_effects_data effect_data;
+   bool render_glider;
+   m4x3f *final_mtx, glider_mtx;
+   struct player_board_pose board_pose;
+}
+_replay2;
+
+f32 _replay2_playback_velocity(void)
+{
+   return _replay2.track_velocity;
+}
+
+struct _remote_replay
+{
+   u32 total_chunks,
+       chunks_downloaded;
+
+   u64 steamid;
+   struct remote_replay_chunk
+   {
+      u32 minute;
+      enum chunk_state
+      {
+         k_chunk_state_none,
+         k_chunk_state_cache_check,
+         k_chunk_state_downloading,
+         k_chunk_state_processed,
+         k_chunk_state_broken
+      }
+      state;
+   }
+   chunks[8];
+   f64 min_frame_t;
+
+   enum remote_replay_state
+   {
+      k_remote_replay_state_none,
+
+      k_remote_replay_state_init,
+      k_remote_replay_state_getinfo,
+
+      k_remote_replay_state_waitnext,
+      k_remote_replay_state_downloading,
+      k_remote_replay_state_failed,
+      k_remote_replay_state_ready,
+   }
+   state;
+   i64 last_second;
+   f64 end_offset, start_offset; /* from the download */
+
+   struct interp_frame interp0, interp1;
+   vg_queue buffer;
+}
+_remote_replay;
 
-struct _remote_replay _remote_replay;
-struct _replay2 _replay2;
+void _remote_replay_reset( u32 centiseconds, i64 last_second, u64 steamid )
+{
+   u32 minutes_span = (centiseconds+(200*60)) / (100*60);
+   u32 last_minute = (u32)( last_second / 60 );
+
+   vg_queue_clear( &_remote_replay.buffer );
+   _remote_replay.min_frame_t = 0.0;
+   _remote_replay.total_chunks = minutes_span;
+   _remote_replay.chunks_downloaded = 0;
+   _remote_replay.steamid = steamid;
+   _remote_replay.state = k_remote_replay_state_init;
+   _remote_replay.last_second = last_second;
+   
+   for( u32 i=0; i<minutes_span; i ++ )
+   {
+      struct remote_replay_chunk *chunk = &_remote_replay.chunks[i];
+      chunk->minute = last_minute - minutes_span + 1 + i;
+      chunk->state = k_chunk_state_none;
+   }
+}
 
 static int cmd_replay2_manual_download( int argc, const char *argv[] )
 {
@@ -41,30 +149,23 @@ static int cmd_replay2_manual_download( int argc, const char *argv[] )
       chunk->state = k_chunk_state_none;
    }
 
-   gui_helper_reset( k_gui_helper_mode_clear );
+   _gui_helper_reset( k_gui_helper_mode_clear );
    _replay2_open_player( k_replay_type_network, 0 );
    return 1;
 }
 
-void _replay2_register(void)
+VG_API void _replay2_register(void)
 {
    vg_console_reg_cmd( "replay2_watch", cmd_replay2_manual_download, NULL );
 }
 
-void _replay2_init(void)
+VG_API void _replay2_init(void)
 {
-   u32 MB = 1024*1024,
-       size = 4*MB;
-
-   _remote_replay.buffer.buffer = vg_stack_allocate( &vg.rtmem, size, 8, "Remote replay buffer" );
-   _remote_replay.buffer.size = size;
+   _remote_replay.buffer.buffer = vg_stack_allocate( NULL, VG_MB(4), 8, "Remote replay buffer" );
+   _remote_replay.buffer.size = VG_MB(4);
 
-   _replay2.buffer.buffer = vg_stack_allocate( &vg.rtmem, size*2, 8, "Replay buffer" );
-   _replay2.buffer.size = size*2;
-
-   struct skeleton *sk = &localplayer.skeleton;
-   u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
-   _replay2.final_mtx = vg_stack_allocate( &vg.rtmem, mtx_size, 8, "Replay Final MTX" );
+   _replay2.buffer.buffer = vg_stack_allocate( NULL, VG_MB(8), 8, "Replay buffer" );
+   _replay2.buffer.size = VG_MB(8);
 }
 
 void _replay2_clear_local_buffer(void)
@@ -125,12 +226,29 @@ void replay2_close_player(void)
    localplayer.immobile = 0;
 }
 
+static void replay_file_path( c8 path[1024], u64 steamid, i64 last_second, u32 minute, enum remote_replay_state state )
+{
+   vg_str path_str;
+   vg_strnull( &path_str, path, 1024 );
+   vg_strcat( &path_str, "replaydata/" );
+   vg_strcatu64( &path_str, steamid, 16 );
+   vg_strcat( &path_str, "@" );
+
+   if( state == k_remote_replay_state_getinfo )
+   {
+      vg_strcati64( &path_str, last_second, 16 );
+      vg_strcat( &path_str, ".kv" );
+   }
+   else
+      vg_strcatu64( &path_str, minute, 16 );
+}
+
 /* remote replay downloader 
  * ------------------------------------------------------------------ */
 
 static void replay_download_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    bool is_from_network = userdata;
 
@@ -148,10 +266,9 @@ static void replay_download_callback( void *data, u32 data_size, u64 userdata, e
       {
          char path[1024];
          if( _remote_replay.state == k_remote_replay_state_getinfo )
-            snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@" PRINTF_X64 ".bkv", 
-                      _remote_replay.steamid, _remote_replay.last_second );
+            replay_file_path( path, _remote_replay.steamid, _remote_replay.last_second, 0, _remote_replay.state );
          else
-            snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@%x", _remote_replay.steamid, chunk->minute );
+            replay_file_path( path, _remote_replay.steamid, 0, chunk->minute, _remote_replay.state );
 
          FILE *fp = fopen( path, "wb" );
          if( fp )
@@ -168,40 +285,51 @@ static void replay_download_callback( void *data, u32 data_size, u64 userdata, e
 
       if( _remote_replay.state == k_remote_replay_state_getinfo )
       {
-         vg_msg kvs;
-         vg_msg_init( &kvs, data, data_size );
-         
-         u32 centiseconds = 0;
-         vg_msg_getkvintg( &kvs, "centiseconds", k_vg_msg_u32, &centiseconds, NULL );
-         u32 end_offset_seconds = 0;
-         vg_msg_getkvintg( &kvs, "end_offset", k_vg_msg_u32, &end_offset_seconds, NULL );
-         _remote_replay.end_offset = end_offset_seconds;
-         _remote_replay.start_offset = _remote_replay.end_offset + ((f64)centiseconds / 100.0);
-
-         vg_info( "end_offset: -%f\n", _remote_replay.end_offset );
-         vg_info( "start_offset: -%f\n", _remote_replay.start_offset );
-
-         vg_msg_cursor orig = kvs.cur;
-         if( vg_msg_seekframe( &kvs, "playerinfo" ) )
+         u32 temp_frame = _vg_start_temp_frame();
          {
-            const char *board_str = vg_msg_getkvstr( &kvs, "board" );
-            const char *playermodel_str = vg_msg_getkvstr( &kvs, "player" );
+            /* TODO This is like, totally duplicated code man */
+            vg_stream kv_stream;
+            vg_buffer_stream_open( &kv_stream, data, data_size, VG_STREAM_READ );
+            vg_kvs kvs;
+            vg_kvs_init( &kvs, _vg_temp_stack() );
+            vg_kv_parser parser;
+            vg_kv_parser_init( &parser, &kvs, 0 );
+            vg_kv_parse_stream( &parser, &kv_stream );
 
-            vg_info( "board_str: %s\n", board_str );
-            vg_info( "playermodel_str: %s\n", playermodel_str );
+            u32 centiseconds = 0;
+            vg_kv_read_vu32( &kvs, 0, "centiseconds", NULL, &centiseconds, 1 );
 
-            if( playermodel_str )
-            {
-               addon_cache_unwatch( k_addon_type_player, _replay2.playermodel.cache_slot );
-               playermodel_set_from_uid( &_replay2.playermodel, playermodel_str );
-            }
+            u32 end_offset_seconds = 0;
+            vg_kv_read_vu32( &kvs, 0, "end_offset", NULL, &end_offset_seconds, 1 );
+
+            _remote_replay.end_offset = end_offset_seconds;
+            _remote_replay.start_offset = _remote_replay.end_offset + ((f64)centiseconds / 100.0);
 
-            if( board_str )
+            vg_info( "end_offset: -%f\n", _remote_replay.end_offset );
+            vg_info( "start_offset: -%f\n", _remote_replay.start_offset );
+
+            u32 player_info_block = vg_kv_find( &kvs, 0, "playerinfo" );
+            if( player_info_block )
             {
-               addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
-               _replay2.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
+               const c8 *board_str = vg_kv_value( &kvs, vg_kv_find( &kvs, player_info_block, "board" ), NULL );
+               const c8 *playermodel_str = vg_kv_value( &kvs, vg_kv_find( &kvs, player_info_block, "player" ), NULL );
+               vg_info( "board_str: %s\n", board_str );
+               vg_info( "playermodel_str: %s\n", playermodel_str );
+
+               if( playermodel_str )
+               {
+                  addon_cache_unwatch( k_addon_type_player, _replay2.playermodel.cache_slot );
+                  playermodel_set_from_uid( &_replay2.playermodel, playermodel_str );
+               }
+
+               if( board_str )
+               {
+                  addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
+                  _replay2.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
+               }
             }
          }
+         _vg_end_temp_frame( temp_frame );
 
          _remote_replay.state = k_remote_replay_state_waitnext;
          return;
@@ -238,7 +366,7 @@ static void replay_download_callback( void *data, u32 data_size, u64 userdata, e
             }
             _remote_replay.min_frame_t = playerframe->timestamp;
 
-            replay2_frame *dst_frame = vg_queue_alloc( buffer, sizeof(replay2_frame) + snm->msg_size, NULL );
+            replay2_frame *dst_frame = vg_queue_alloc( buffer, sizeof(replay2_frame) + snm->msg_size );
             if( !dst_frame )
             {
                vg_error( "Out of mem adding frame!\n" );
@@ -319,17 +447,15 @@ struct async_cache_check_result
    u32 data_length;
    u8 data[];
 };
-static void async_cache_check_result( vg_async_task *task )
+static void async_cache_check_result( struct async_cache_check_result *in_args, vg_async_info *async )
 {
-   THREAD_0;
-   struct async_cache_check_result *result = (void *)task->data;
-   
-   if( result->found_in_cache )
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   if( in_args->found_in_cache )
    {
-      if( result->broken )
+      if( in_args->broken )
          replay_download_callback( NULL, 0, 0, k_request_status_not_found );
       else
-         replay_download_callback( result->data, result->data_length, 0, k_request_status_ok );
+         replay_download_callback( in_args->data, in_args->data_length, 0, k_request_status_ok );
    }
    else
    {
@@ -338,6 +464,8 @@ static void async_cache_check_result( vg_async_task *task )
 
       vg_make_directory( "replaydata" );
 
+      // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
       netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
       packet->inetmsg_id = k_inetmsg_request;
 
@@ -354,6 +482,8 @@ static void async_cache_check_result( vg_async_task *task )
       else
          vg_msg_wkvnum( &data, "lastsec", k_vg_msg_i64, 1, &_remote_replay.last_second );
       network_send_request( packet, &data, replay_download_callback, 1 );
+#endif
+      // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
    }
 }
 
@@ -361,43 +491,37 @@ static void async_cache_check_result( vg_async_task *task )
 static const u32 k_download_option_preparing = 0x00;
 static const u32 k_download_option_data = 0x00;
 
-static void _remote_replay_cache_check( void *userdata )
+static void _remote_replay_cache_check( void *_, vg_async_info *async )
 {
    char path[1024];
    if( _remote_replay.state == k_remote_replay_state_getinfo )
-   {
-      snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@" PRINTF_X64 ".bvk", 
-               _remote_replay.steamid, _remote_replay.last_second );
-   }
+      replay_file_path( path, _remote_replay.steamid, _remote_replay.last_second, 0, _remote_replay.state );
    else
    {
       struct remote_replay_chunk *chunk = &_remote_replay.chunks[ _remote_replay.chunks_downloaded ];
-      snprintf( path, sizeof(path), "replaydata/" PRINTF_X64 "@%x", _remote_replay.steamid, chunk->minute );
+      replay_file_path( path, _remote_replay.steamid, 0, chunk->minute, _remote_replay.state );
    }
 
-   vg_async_task *result_task = 
-      vg_allocate_async_task( &vg.main_tasks, sizeof(struct async_cache_check_result) + 8*1024*1024, 1 );
-   struct async_cache_check_result *result = (void *)result_task->data;
-   result->broken = 0;
+   struct async_cache_check_result *out_args = 
+      _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct async_cache_check_result) + 8*1024*1024 );
+   out_args->broken = 0;
 
    FILE *fp = fopen( path, "rb" );
    if( fp )
    {
-      result->found_in_cache = 1;
-      result->data_length = fread( result->data, 1, 20*1024*1024, fp );
-
+      out_args->found_in_cache = 1;
+      out_args->data_length = fread( out_args->data, 1, 20*1024*1024, fp );
       if( !feof( fp ) )
-         result->broken = 1;
-
+         out_args->broken = 1;
       fclose( fp );
    }
    else
    {
-      result->found_in_cache = 0;
-      result->data_length = 0;
+      out_args->found_in_cache = 0;
+      out_args->data_length = 0;
    }
 
-   vg_async_task_dispatch( result_task, async_cache_check_result );
+   _vg_async_send( out_args, (vg_async_fn)async_cache_check_result ); 
 }
 
 static void _remote_replay_pre_update(void)
@@ -405,7 +529,7 @@ static void _remote_replay_pre_update(void)
    if( _remote_replay.state == k_remote_replay_state_init )
    {
       _remote_replay.state = k_remote_replay_state_getinfo;
-      vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_remote_replay_cache_check );
    }
    else if( _remote_replay.state == k_remote_replay_state_waitnext )
    {
@@ -415,7 +539,7 @@ static void _remote_replay_pre_update(void)
       if( chunk->state == k_chunk_state_none )
       {
          chunk->state = k_chunk_state_cache_check;
-         vg_async_call( &vg.loader_tasks, _remote_replay_cache_check, NULL );
+         _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_remote_replay_cache_check );
       }
    }
 }
@@ -503,7 +627,39 @@ void _replay2_pre_update(void)
    }
 
    if( _replay2.use_freecam )
-      freecam_preupdate();
+   {
+      vg_camera *cam = &_replay2.replay_freecam;
+      v3f angles;
+      v3_copy( cam->angles, angles );
+      player_look( angles, 1.0f );
+
+      f32 decay = vg_maxf(0.0f,1.0f-vg.time_frame_delta*10.0f);
+
+      v3f d;
+      v3_sub( angles, cam->angles, d );
+      v3_muladds( _replay2.freecam_w, d, 20.0f, _replay2.freecam_w );
+      v3_muls( _replay2.freecam_w, decay, _replay2.freecam_w );
+      v3_muladds( cam->angles, _replay2.freecam_w, vg.time_frame_delta, cam->angles );
+      cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
+
+      vg_camera_update_transform( cam );
+
+      v3f lookdir = { 0.0f, 0.0f, -1.0f },
+          sidedir = { 1.0f, 0.0f,  0.0f };
+      
+      m3x3_mulv( cam->transform, lookdir, lookdir );
+      m3x3_mulv( cam->transform, sidedir, sidedir );
+
+      v2f input;
+      joystick_state( k_srjoystick_steer, input );
+      v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
+      
+      v3_muladds( _replay2.freecam_v, lookdir, -input[1], _replay2.freecam_v );
+      v3_muladds( _replay2.freecam_v, sidedir, input[0], _replay2.freecam_v );
+
+      v3_muls( _replay2.freecam_v, decay, _replay2.freecam_v );
+      v3_muladds( cam->pos,_replay2.freecam_v, vg.time_frame_delta, cam->pos );
+   }
 
    if( _replay2.animation_dirty )
    {
@@ -633,16 +789,16 @@ void _replay2_pre_update(void)
    }
 }
 
-void _replay2_render_player( world_instance *world, vg_camera *cam )
+void _replay2_render_player( vg_camera *cam )
 {
    if( skaterift.activity != k_skaterift_replay ) 
       return;
 
-   struct skeleton *sk = &localplayer.skeleton;
-   render_playermodel( cam, world, 0, &_replay2.playermodel, sk, _replay2.final_mtx );
+   ms_skeleton *sk = &localplayer.skeleton;
+   render_playermodel( cam, &_world.main, 0, &_replay2.playermodel, sk, _replay2.final_mtx );
 
    struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay2.board_cache_id, 1 );
-   render_board( cam, world, board, _replay2.final_mtx[localplayer.id_board], 
+   render_board( cam, &_world.main, board, _replay2.final_mtx[localplayer.id_board], 
                  &_replay2.board_pose, k_board_shader_player );
 
 #if 0
@@ -654,7 +810,7 @@ void _replay2_render_player( world_instance *world, vg_camera *cam )
    shader_model_entity_uCamera( cam->transform[3] );
    shader_model_entity_uPv( cam->mtx.pv );
    
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+   WORLD_LINK_LIGHTING( world, model_entity );
 
    for( u32 j=0; j<draw_list_count; j ++ )
    {
@@ -804,7 +960,7 @@ void _replay2_imgui( ui_context *ctx )
    {
       if( _remote_replay.state < k_remote_replay_state_ready )
       {
-         ui_rect box = { vg.window_x/2 - 200, vg.window_y/2-80, 400, 160 };
+         ui_rect box = { _vg_window.w/2 - 200, _vg_window.h/2-80, 400, 160 };
          ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.36f ) );
          ui_rect titlebox, boxbox, boxboxline;
          ui_split_ratio( box, k_ui_axis_h, 0.5f, 8, titlebox, boxbox );
@@ -874,7 +1030,7 @@ void _replay2_imgui( ui_context *ctx )
    if( buffer->allocation_count < 2 )
    {
       ctx->font = &vgf_default_large;
-      ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
+      ui_rect box = { _vg_window.w/2 - 200, 40, 400, ctx->font->sy };
       ui_text( ctx, box, KRED "\x06\x02--- Corrupt replay ---", 1, k_ui_align_center, 0 );
       // TODO
       return;
@@ -888,7 +1044,7 @@ void _replay2_imgui( ui_context *ctx )
        cur = (_replay2.cursor - start) / len;
 
    /* mainbar */
-   ui_rect timeline = { 8, vg.window_y-(32+8), vg.window_x-16, 32 };
+   ui_rect timeline = { 8, _vg_window.h-(32+8), _vg_window.w-16, 32 };
    ui_rect start_box;
    ui_split( timeline, k_ui_axis_v, 32, 8, start_box, timeline );
 
@@ -958,7 +1114,7 @@ void _replay2_imgui( ui_context *ctx )
    /* helpers */
    ctx->font = &vgf_default_large;
 
-   ui_rect helper_list_l = { 10, timeline[1] - (ctx->font->sy+8), vg.window_x/2, ctx->font->sy };
+   ui_rect helper_list_l = { 10, timeline[1] - (ctx->font->sy+8), _vg_window.w/2, ctx->font->sy };
    char buf[256];
    vg_str str;
    vg_strnull( &str, buf, sizeof(buf) );
@@ -985,7 +1141,7 @@ void _replay2_imgui( ui_context *ctx )
    ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
    helper_list_l[1] -= helper_list_l[3]+2;
 
-   ui_rect helper_list_r = { vg.window_x/2, timeline[1] - (ctx->font->sy+8), vg.window_x/2-10, ctx->font->sy };
+   ui_rect helper_list_r = { _vg_window.w/2, timeline[1] - (ctx->font->sy+8), _vg_window.w/2-10, ctx->font->sy };
    vg_strnull( &str, buf, sizeof(buf) );
    vg_input_string( &str, input_button_list[k_srbind_mback], 1 );
    vg_strcat( &str, "\x07 Exit Replay" );
@@ -994,7 +1150,7 @@ void _replay2_imgui( ui_context *ctx )
 
    if( _replay2.use_freecam )
    {
-      ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
+      ui_rect box = { _vg_window.w/2 - 200, 40, 400, ctx->font->sy };
       ui_text( ctx, box, KYEL "\x06\x02--- Freecam Enabled ---", 1, k_ui_align_center, 0 );
    }
 
@@ -1047,13 +1203,13 @@ void _replay2_record_local_frame(void)
        sfx_size      = vg_align8( localplayer.local_sfx_buffer_count * sizeof(struct net_sfx) ),
        total_size    = sizeof(replay2_frame) + animator_size + glider_size + sfx_size;
 
-   replay2_frame *dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+   replay2_frame *dest_frame = vg_queue_alloc( buffer, total_size );
    if( !dest_frame )
    {
       while( buffer->allocation_count )
       {
          vg_queue_pop( buffer );
-         dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+         dest_frame = vg_queue_alloc( buffer, total_size );
          if( dest_frame )
             break;
       }
index 872de7e5001c50f16149de3e6aedaab9f6efdcc4..94802d686ed22f8bbe0a7ab4e124589c19318b12 100644 (file)
@@ -1,6 +1,12 @@
-#pragma once
-#include "vg/vg_mem_queue.h"
-#include "player_effects.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/replay2.c"
+#else
+
+enum replay_type
+{
+   k_replay_type_local,
+   k_replay_type_network
+};
 
 typedef struct replay2_frame replay2_frame;
 struct replay2_frame
@@ -35,106 +41,20 @@ struct replay_glider_data
    v4f q;
 };
 
-struct _remote_replay
-{
-   u32 total_chunks,
-       chunks_downloaded;
-
-   u64 steamid;
-   struct remote_replay_chunk
-   {
-      u32 minute;
-      enum chunk_state
-      {
-         k_chunk_state_none,
-         k_chunk_state_cache_check,
-         k_chunk_state_downloading,
-         k_chunk_state_processed,
-         k_chunk_state_broken
-      }
-      state;
-   }
-   chunks[8];
-   f64 min_frame_t;
-
-   enum remote_replay_state
-   {
-      k_remote_replay_state_none,
-
-      k_remote_replay_state_init,
-      k_remote_replay_state_getinfo,
-
-      k_remote_replay_state_waitnext,
-      k_remote_replay_state_downloading,
-      k_remote_replay_state_failed,
-      k_remote_replay_state_ready,
-   }
-   state;
-   i64 last_second;
-   f64 end_offset, start_offset; /* from the download */
+VG_API void _replay2_register(void);
+VG_API void _replay2_init(void);
 
-   struct interp_frame interp0, interp1;
-   vg_queue buffer;
-}
-extern _remote_replay;
+f32 _replay2_playback_velocity(void);
 
-struct _replay2
-{
-   enum replay_type
-   {
-      k_replay_type_local,
-      k_replay_type_network
-   }
-   type;
-
-   vg_queue buffer;
-
-   /* TODO: Modifiers / keyframes lane */
-   
-   u32 cursor_frame_offset;
-   f64 cursor;
-   enum replay_control {
-      k_replay_control_scrub = 0x00,
-      k_replay_control_play  = 0x01,
-      k_replay_control_resume= 0x02
-   }
-   replay_control;
-   f32 track_velocity;
-
-   bool cursor_decoded;
-
-   struct net_sfx sfx_queue[ 8 ];
-   u32 sfx_queue_length;
-   f64 sfx_basetime;
-
-   vg_camera replay_freecam, playback_cam;
-   bool use_freecam;
-   bool hide_ui;
-   v3f freecam_v, freecam_w;
-
-   f64 start_t, end_t;
-   bool highlight;
-   f64 highlight_start, highlight_length;
-
-   bool animation_dirty;
-   addon_cache_id board_cache_id;
-   player_model_view playermodel;
-
-   struct player_effects_data effect_data;
-   bool render_glider;
-   m4x3f *final_mtx, glider_mtx;
-   struct player_board_pose board_pose;
-}
-extern _replay2;
-
-void _replay2_register(void);
-void _replay2_init(void);
+void _remote_replay_reset( u32 centiseconds, i64 last_second, u64 steamid );
 void _replay2_pre_update(void);
 void _replay2_imgui( ui_context *ctx );
 void _replay2_open_player( enum replay_type type, bool end );
-void _replay2_render_player( world_instance *world, vg_camera *cam );
+void _replay2_render_player( vg_camera *cam );
 void _replay2_seek( f64 t, bool play_sounds );
 void _replay2_get_camera( vg_camera *cam );
 void _replay2_decode(void);
 void _replay2_record_local_frame(void);
 void _replay2_clear_local_buffer(void);
+
+#endif
index 15519da0084203586e50c12e14838b530fab5679..8116d5c620245deb281d3bb1ba6eeb6ab4f0a775 100644 (file)
@@ -1,17 +1,9 @@
-#include "skaterift.h"
-#include "save.h"
-#include "addon.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_log.h"
-#include "vg/vg_loader.h"
-#include "world.h"
-#include "player.h"
-
-static const char *str_skaterift_main_save = "save.bkv";
+static const char *str_skaterift_main_save = "save.kv";
 static f64 _last_autosave;
 
 void savedata_file_write( savedata_file *file )
 {
+#if 0
    savedata_file *sav = file;
    FILE *fp = fopen( sav->path, "wb" );
    if( fp )
@@ -22,6 +14,7 @@ void savedata_file_write( savedata_file *file )
    }
    else 
       vg_error( "Error writing savedata (%s)\n", sav->path );
+#endif
 }
 
 static void savedata_file_write_task( vg_async_task *task )
@@ -31,6 +24,8 @@ static void savedata_file_write_task( vg_async_task *task )
 
 void savedata_file_read( savedata_file *file )
 {
+   vg_zero_mem( &file->kvs, sizeof(vg_kvs) );
+#if 0
    FILE *fp = fopen( file->path, "rb" );
    if( fp )
    {
@@ -43,37 +38,45 @@ void savedata_file_read( savedata_file *file )
       vg_msg_init( &file->msg, file->buf, 0 );
       vg_warn( "Error reading savedata (%s)\n", file->path );
    }
+#endif
 }
 
 static void skaterift_write_addon( vg_msg *msg, const char *key, addon_id id )
 {
+#if 0
    char uid[ ADDON_UID_MAX ];
    addon_make_uid( id, uid );
    vg_msg_wkvstr( msg, key, uid );
+#endif
 }
 
 static void skaterift_write_viewslot( vg_msg *msg, const char *key, enum addon_type type, u16 cache_id )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    if( !cache_id ) 
       return;
 
+#if 0
    addon_cache_entry *entry = get_addon_cache_entry( type, cache_id );
 
    char uid[ ADDON_UID_MAX ];
    addon_make_uid_cpart( entry->addon_id, uid, entry->local_cpart );
    vg_msg_wkvstr( msg, key, uid );
+#endif
 }
 
 void init_savefile( savedata_file *file, const char *path )
 {
    memset( file, 0, sizeof(savedata_file) );
    strcpy( file->path, path );
+#if 0
    vg_msg_init( &file->msg, file->buf, sizeof(file->buf) );
+#endif
 }
 
 void write_savefile( savedata_file *file, bool async )
 {
+#if 0
    if( async ) 
    {
       vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(savedata_file), 1 );
@@ -82,10 +85,12 @@ void write_savefile( savedata_file *file, bool async )
    }
    else  
       savedata_file_write( file );
+#endif
 }
 
 void skaterift_write_all_savedata( bool async )
 {
+#if 0
    savedata_file file;
 
    /* main file */
@@ -141,20 +146,25 @@ void skaterift_write_all_savedata( bool async )
       vg_msg_end_frame( &file.msg );
       write_savefile( &file, async );
    }
+#endif
 }
 
 void skaterift_autosave_synchronous(void)
 {
+#if 0
    skaterift_write_all_savedata( 0 );
+#endif
 }
 
 void skaterift_autosave_update( void )
 {
+#if 0
    if( (vg.time - _last_autosave) > 60.0 )
    {
       skaterift_write_all_savedata(1);
       _last_autosave = vg.time;
    }
+#endif
 }
 
 struct equip_saved_items_info
@@ -166,7 +176,7 @@ struct equip_saved_items_info
 };
 static void equip_async( vg_async_task *task )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    struct equip_saved_items_info *info = (void *)task->data;
    localplayer.board_view_slot = addon_cache_create_viewer( k_addon_type_board, info->board_id );
@@ -184,7 +194,9 @@ static void equip_async( vg_async_task *task )
    
 void skaterift_load_mainsave(void)
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+#if 0
 
    savedata_file file;
    strcpy( file.path, str_skaterift_main_save );
@@ -237,4 +249,5 @@ void skaterift_load_mainsave(void)
       vg_info( "Starting new story!\n" );
       _world.load_addon = _addon_mount_from_folder_path( "maps/dev_heaven", k_addon_type_world, ".mdl" );
    }
+#endif
 }
index 8ea303a5362e548d171f45906f9496060efe9c11..e5095f51fa9eebb4a1226eb371ccbe7f28f94e05 100644 (file)
@@ -1,15 +1,13 @@
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_msg.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/save.c"
+#else
 
 typedef struct savedata_file savedata_file;
 
 struct savedata_file 
 {
    char path[256];
-   u8  buf[2048];
-   vg_msg msg;
+   vg_kvs kvs;
 };
 
 void savedata_file_read( savedata_file *file );
@@ -22,3 +20,5 @@ void skaterift_load_mainsave(void);
 
 void init_savefile( savedata_file *file, const char *path );
 void write_savefile( savedata_file *file, bool async );
+
+#endif
diff --git a/src/save2.c b/src/save2.c
new file mode 100644 (file)
index 0000000..ee49a84
--- /dev/null
@@ -0,0 +1,178 @@
+/* How many save files can be 'open' at once */
+#define MAX_SAVE_FILES 3
+
+// In the future
+// #define MAX_SAVE_SLOTS 4
+
+VG_API void _skaterift_autosave_post_update( void )
+{
+   VG_ASSERT(0);
+}
+
+#if 0
+
+struct
+{
+   struct savefile
+   {
+      bool ready;
+      vg_stack_allocator stack;
+      vg_kvs kvs;
+
+      u16 addon_id; /* 0 for main save */
+   }
+   files[ MAX_SAVE_FILES ];
+   vg_pool pool;
+   vg_pool_chain inactive, active;
+}
+_savedata;
+
+void _savedata_init(void)
+{
+   vg_pool_init( &_savedata.pool, &_savedata.inactive, MAX_SAVE_FILES, &vg.rtmem );
+}
+
+
+// Loading 
+while( ... )
+{
+   if( stage == init )
+   {
+      world->savefile = savedata_handle( world->addon );
+      if( world->savefile )
+         stage = read_save;
+   }
+   else if( stage == read_save )
+   {
+      if( savedata_loaded( world->savefile ) )
+      {
+         // read save
+         stage = ready;
+      }
+   }
+}
+
+
+// Game loop
+if( autosave_timer() )
+{
+   world_autosave(); -> savedata_sync( world->savefile );
+}
+
+// Unload
+savedata_sync( world->savefile );
+savedata_release_handle( world->addon );
+
+
+
+
+
+
+
+static u16 _savedata_handle_fork( u16 save_handle )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   if( vg_pool_reference( &_savedata.pool, save_handle, 1 ) == 1 )
+      vg_pool_switch( &_savedata.pool, &_savedata.inactive, &_savedata.active );
+
+   return save_handle;
+}
+
+void _savedata_handle_release( u16 save_handle )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   if( vg_pool_reference( &_savedata.pool, save_handle, 0 ) == 0 )
+      vg_pool_switch( &_savedata.pool, &_savedata.active, &_savedata.inactive );
+}
+
+struct savedata_async_info
+{
+   u16 save_handle;
+};
+static savedata_async( vg_async_queue *queue, void( *fn )(u16), u16 handle )
+{
+   vg_async_task *task = vg_allocate_async_task( queue, sizeof(struct savedata_async_info), 1 );
+   struct savedata_async_info *info = (void *)complete_task->data;
+   info->save_handle = handle;
+   vg_async_task_dispatch( task, savedata_load );
+}
+
+static savedata_task_complete( vg_async_task *task )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   struct savedata_async_info *info = (void *)task->data;
+   struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
+   sf->ready = 1;
+   _savedata_handle_release( info->save_handle );
+}
+
+void savedata_load( vg_async_task *task )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   struct savedata_async_info *info = (void *)task->data;
+   struct savefile *sf = &_savedata.files[ vg_pool_index( &_savedata.pool, info->save_handle ) ];
+
+   vg_stack_clear( &sf->stack );
+   vg_kvs_init( &sf->kvs, &sf->stack );
+   
+   c8 path[ 256 ];
+   addon_make_savedata_path( sf->addon_id, path );
+
+   vg_file file;
+   if( vg_file_stream_open( &file, path ) )
+   {
+      vg_kv_parser parser;
+      vg_kv_parser_init( &parser, &sf->kvs, 0 );
+
+      c8 chunk[ 1024 ];
+read_more:;
+      u32 l = vg_file_stream( &file, chunk, sizeof(chunk) );
+      vg_kv_parse_buffer( &parser, chunk, l );
+
+      if( l == sizeof(chunk) )
+         goto read_more;
+
+      vg_file_stream_close( &file );
+   }
+   else
+      vg_low( "Savefile '%s' did not exist yet. Creating.\n" );
+
+   vg_async_task *complete_task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct savedata_async_info), 1 );
+   struct savedata_async_info *info = (void *)complete_task->data;
+   info->save_handle = info->save
+   vg_async_task_dispatch( load_task, savedata_load );
+}
+
+u16 _savedata_handle( addon_id addon )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
+   u16 save_handle = _savedata.active.head;
+   while( save_handle )
+   {
+      if( _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].addon_id == addon )
+         return _savedata_handle_fork( save_handle );
+
+      save_handle = vg_pool_next( &_savedata.pool, save_handle, 1 );
+   }
+
+   save_handle = _savedata.inactive.tail;
+   if( save_handle )
+   {
+      vg_async_task *load_task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct savedata_async_info), 1 );
+      struct savedata_async_info *info = (void *)load_task->data;
+      info->save_handle = _savedata_handle_fork( save_handle );
+      vg_async_task_dispatch( load_task, savedata_load );
+      return _savedata_handle_fork( save_handle );
+   }
+
+   return 0;
+}
+
+bool _savedata_ready( u16 save_handle )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   return _savedata.files[ vg_pool_index( &_savedata.pool, save_handle ) ].ready;
+}
+
+#endif
diff --git a/src/save2.h b/src/save2.h
new file mode 100644 (file)
index 0000000..9fc2689
--- /dev/null
@@ -0,0 +1,7 @@
+#if defined( SR_IMPLEMENTATION )
+# include "src/save2.c"
+#else
+
+VG_API void _skaterift_autosave_post_update( void );
+
+#endif
index e2040064b85c4aede797f4c9b3c2b14f6c007f8c..5baf15916555921c07a9d5321cee6196417eede4 100644 (file)
@@ -1,37 +1,29 @@
-#include "scene.h"
-
-u32 scene_mem_required( scene_context *ctx )
-{
-   u32 vertex_length = vg_align8(ctx->max_vertices * sizeof(scene_vert)),
-       index_length  = vg_align8(ctx->max_indices  * sizeof(u32));
-
-   return vertex_length + index_length;
-}
-
-void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices )
+VG_TIER_2 void scene_builder_init( scene_builder_context *ctx, u32 max_vertices, u32 max_indices, vg_stack_allocator *stack )
 {
-   ctx->vertex_count = 0;
-   ctx->indice_count = 0;
-   ctx->max_vertices = max_vertices;
-   ctx->max_indices = max_indices;
-   ctx->arrindices = NULL; /* must be filled out by user */
-   ctx->arrvertices = NULL;
-
-   memset( &ctx->submesh, 0, sizeof(mdl_submesh) );
-
-   v3_fill( ctx->bbx[0],  999999.9f );
-   v3_fill( ctx->bbx[1], -999999.9f );
+   vg_zero_mem( ctx, sizeof(scene_builder_context) );
+   u32 vertex_block_size = vg_align8( max_vertices * sizeof(scene_vert) ),
+       indice_block_size = vg_align8( max_indices * sizeof(u32) );
+   ctx->base_buffer_size = vertex_block_size + indice_block_size;
+   ctx->base_buffer = vg_stack_allocate( stack, ctx->base_buffer_size, 8, "Scene data" );
+   vg_stack_init( &ctx->vertex_stack, ctx->base_buffer, vertex_block_size, "Scene vertices" );
+   vg_stack_init( &ctx->indice_stack, ctx->base_buffer + vertex_block_size, indice_block_size, "Scene indices" );
+   v3_fill( ctx->scene.bbx[0],  999999.9f );
+   v3_fill( ctx->scene.bbx[1], -999999.9f );
 }
 
-void scene_supply_buffer( scene_context *ctx, void *buffer )
+VG_TIER_2 void scene_builder_compact_memory( scene_builder_context *ctx, vg_stack_allocator *stack )
 {
-   u32 vertex_length = vg_align8( ctx->max_vertices * sizeof(scene_vert) );
-
-   ctx->arrvertices = buffer;
-   ctx->arrindices  = (u32*)(((u8*)buffer) + vertex_length);
+   void *new_indice_location = ctx->base_buffer + vg_align8( ctx->vertex_stack.offset );
+   memmove( new_indice_location, ctx->indice_stack.data, ctx->indice_stack.offset );
+   ctx->vertex_stack.capacity = ctx->vertex_stack.offset;
+   ctx->indice_stack.capacity = ctx->indice_stack.offset;
+   ctx->indice_stack.data = new_indice_location;
+   u32 new_size = vg_align8( ctx->vertex_stack.capacity ) + vg_align8( ctx->indice_stack.capacity );
+   vg_stack_extend_last( stack, (i32)new_size - (i32)ctx->base_buffer_size );
+   ctx->base_buffer_size = new_size;
 }
 
-void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
+VG_TIER_0 void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
 {
    v3f n;
    v3_muls( norm, 127.0f, n );
@@ -43,35 +35,19 @@ void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
    vert->norm[3] = blend * 127.0f;
 }
 
-/* 
- * Append a model into the scene with a given transform
- */
-void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, 
-                            mdl_submesh *sm, m4x3f transform )
+VG_TIER_0 void scene_builder_add_model_submesh( scene_builder_context *ctx, vg_model *model, mdl_submesh *sm, m4x3f transform )
 {
-   if( ctx->vertex_count + sm->vertex_count > ctx->max_vertices ){
-      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
-                        ctx->vertex_count + sm->vertex_count, 
-                        ctx->max_vertices );
-   }
-
-   if( ctx->indice_count + sm->indice_count > ctx->max_indices ){
-      vg_fatal_error( "Scene index buffer overflow (%u exceeds %u)\n",
-                        ctx->indice_count + sm->indice_count,
-                        ctx->max_indices );
-   }
-
-   mdl_vert   *src_verts = mdl->verts + sm->vertex_start;
-   scene_vert *dst_verts = &ctx->arrvertices[ ctx->vertex_count ];
-
-   u32 *src_indices    = mdl->indices + sm->indice_start,
-       *dst_indices    = &ctx->arrindices[ ctx->indice_count ];
+   VG_ASSERT( model->flags & VG_MODEL_CPU_MESHES );
+   mdl_vert   *src_verts = model->verts + sm->vertex_start;
+   scene_vert *dst_verts = vg_stack_allocate( &ctx->vertex_stack, sizeof(scene_vert)*sm->vertex_count, 1, "Verts (submesh)" );
+   u32 *src_indices    = model->indices + sm->indice_start,
+       *dst_indices    = vg_stack_allocate( &ctx->indice_stack, sizeof(u32)*sm->indice_count, 1, "Indices (submesh)" );
    
    /* Transform and place vertices */
    boxf bbxnew;
    box_init_inf( bbxnew );
    m4x3_expand_aabb_aabb( transform, bbxnew, sm->bbx );
-   box_concat( ctx->bbx, bbxnew );
+   box_concat( ctx->scene.bbx, bbxnew );
 
    m3x3f normal_matrix;
    m3x3_copy( transform, normal_matrix );
@@ -79,124 +55,107 @@ void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl,
    v3_normalize( normal_matrix[1] );
    v3_normalize( normal_matrix[2] );
    
-   for( u32 i=0; i<sm->vertex_count; i++ ){
+   for( u32 i=0; i<sm->vertex_count; i++ )
+   {
       mdl_vert   *src   = &src_verts[i];
       scene_vert *pvert = &dst_verts[i];
-
       m4x3_mulv( transform, src->co, pvert->co );
 
       v3f normal;
       m3x3_mulv( normal_matrix, src->norm, normal );
       scene_vert_pack_norm( pvert, normal, src->colour[0]*(1.0f/255.0f) );
-      
       v2_copy( src->uv, pvert->uv );
    }
 
    u32 real_indices = 0;
-   for( u32 i=0; i<sm->indice_count/3; i++ ){
+   for( u32 i=0; i<sm->indice_count/3; i++ )
+   {
       u32 *src = &src_indices[i*3],
           *dst = &dst_indices[real_indices];
-
       v3f ab, ac, tn;
       v3_sub( src_verts[src[2]].co, src_verts[src[0]].co, ab );
       v3_sub( src_verts[src[1]].co, src_verts[src[0]].co, ac );
       v3_cross( ac, ab, tn );
-
 #if 0
       if( v3_length2( tn ) <= 0.00001f )
          continue;
 #endif
-
-      dst[0] = src[0] + ctx->vertex_count;
-      dst[1] = src[1] + ctx->vertex_count;
-      dst[2] = src[2] + ctx->vertex_count;
+      dst[0] = src[0] + ctx->scene.vertex_count;
+      dst[1] = src[1] + ctx->scene.vertex_count;
+      dst[2] = src[2] + ctx->scene.vertex_count;
 
       real_indices += 3;
    }
-
    if( real_indices != sm->indice_count )
       vg_warn( "Zero area triangles in model\n" );
-
-   ctx->vertex_count += sm->vertex_count;
-   ctx->indice_count += real_indices;
+   ctx->scene.vertex_count += sm->vertex_count;
+   ctx->scene.indice_count += real_indices;
 }
 
 /*
  * One by one adders for simplified access (mostly procedural stuff)
  */
-void scene_push_tri( scene_context *ctx, u32 tri[3] )
+VG_TIER_0 void scene_builder_push_tri( scene_builder_context *ctx, u32 tri[3] )
 {
-   if( ctx->indice_count + 3 > ctx->max_indices )
-      vg_fatal_error( "Scene indice buffer overflow (%u exceeds %u)\n",
-                        ctx->indice_count+3, ctx->max_indices );
-
-   u32 *dst = &ctx->arrindices[ ctx->indice_count ];
-
+   u32 *dst = vg_stack_allocate( &ctx->indice_stack, sizeof(u32)*3, 1, "Indices (single tri)" );
    dst[0] = tri[0];
    dst[1] = tri[1];
    dst[2] = tri[2];
-
-   ctx->indice_count += 3;
+   ctx->scene.indice_count += 3;
 }
 
-void scene_push_vert( scene_context *ctx, scene_vert *v )
+VG_TIER_0 void scene_builder_push_vert( scene_builder_context *ctx, scene_vert *v )
 {
-   if( ctx->vertex_count + 1 > ctx->max_vertices )
-      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
-                        ctx->vertex_count+1, ctx->max_vertices );
-
-   scene_vert *dst = &ctx->arrvertices[ ctx->vertex_count ];
+   scene_vert *dst = vg_stack_allocate( &ctx->vertex_stack, sizeof(scene_vert), 1, "Single vert" );
    *dst = *v;
-
-   ctx->vertex_count ++;
+   ctx->scene.vertex_count ++;
 }
 
-void scene_copy_slice( scene_context *ctx, mdl_submesh *sm )
+VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm )
 {
-   sm->indice_start = ctx->submesh.indice_start;
-   sm->indice_count = ctx->indice_count - sm->indice_start;
-
-   sm->vertex_start = ctx->submesh.vertex_start;
-   sm->vertex_count = ctx->vertex_count - sm->vertex_start;
-   
-   ctx->submesh.indice_start = ctx->indice_count;
-   ctx->submesh.vertex_start = ctx->vertex_count;
+   vg_zero_mem( sm, sizeof(mdl_submesh) );
+   sm->indice_start = ctx->current_submesh.indice_start;
+   sm->indice_count = ctx->scene.indice_count - sm->indice_start;
+   sm->vertex_start = ctx->current_submesh.vertex_start;
+   sm->vertex_count = ctx->scene.vertex_count - sm->vertex_start;
+   ctx->current_submesh.indice_start = ctx->scene.indice_count;
+   ctx->current_submesh.vertex_start = ctx->scene.vertex_count;
 }
 
-void scene_set_vertex_flags( scene_context *ctx, 
-                             u32 start, u32 count, u16 flags )
+VG_TIER_0 void scene_builder_set_vertex_flags( scene_builder_context *ctx, u32 start, u32 count, u16 flags )
 {
+   scene_vert *verts = vg_stack_pointer( &ctx->vertex_stack, sizeof(scene_vert)*start );
    for( u32 i=0; i<count; i++ )
-      ctx->arrvertices[ start + i ].flags = flags;
+      verts[ start + i ].flags = flags;
 }
 
-struct scene_upload_info{
-   scene_context *ctx;
-   glmesh *mesh;
-};
-
-void async_scene_upload( vg_async_task *task )
+VG_TIER_0 void scene_builder_save_scene( scene_builder_context *ctx, vg_scene *out_scene )
 {
-   THREAD_0;
-
-   struct scene_upload_info *info = (void *)task->data;
-   
-   glmesh *mesh = info->mesh;
-   scene_context *ctx = info->ctx;
-
-   glGenVertexArrays( 1, &mesh->vao );
-   glGenBuffers( 1, &mesh->vbo );
-   glGenBuffers( 1, &mesh->ebo );
-   glBindVertexArray( mesh->vao );
-
-   size_t stride = sizeof(scene_vert);
-
-   glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
-   glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, ctx->arrvertices, GL_STATIC_DRAW );
+   *out_scene = ctx->scene;
+   out_scene->vertex_buffer = vg_stack_pointer( &ctx->vertex_stack, 0 );
+   out_scene->indice_buffer = vg_stack_pointer( &ctx->indice_stack, 0 );
+}
 
-   glBindVertexArray( mesh->vao );
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32), ctx->arrindices, GL_STATIC_DRAW );
+struct scene_upload_task
+{
+   vg_scene scene;
+   scene_mesh *out_mesh;
+};
+static void scene_upload_task( struct scene_upload_task *in_args )
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+
+   glGenVertexArrays( 1, &in_args->out_mesh->vao );
+   glBindVertexArray( in_args->out_mesh->vao );
+   glGenBuffers( 1, &in_args->out_mesh->vbo );
+   glGenBuffers( 1, &in_args->out_mesh->ebo );
+
+   u32 stride = sizeof(scene_vert);
+   glBindBuffer( GL_ARRAY_BUFFER, in_args->out_mesh->vbo );
+   glBufferData( GL_ARRAY_BUFFER, in_args->scene.vertex_count*stride, in_args->scene.vertex_buffer, GL_STATIC_DRAW );
+   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, in_args->out_mesh->ebo );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, in_args->scene.indice_count * sizeof(u32), 
+                 in_args->scene.indice_buffer, GL_STATIC_DRAW );
    
    /* 0: coordinates */
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
@@ -210,55 +169,48 @@ void async_scene_upload( vg_async_task *task )
    glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(scene_vert, uv) );
    glEnableVertexAttribArray( 2 );
 
-   mesh->indice_count = ctx->indice_count;
-   mesh->loaded = 1;
-
-   vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
-   vg_info( "   indices:%u\n", ctx->indice_count );
-   vg_info( "   verts:%u\n",   ctx->vertex_count );
+   vg_info( "Scene uploadd ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
+   vg_info( "   indices:%u\n", in_args->scene.indice_count );
+   vg_info( "   verts:%u\n",   in_args->scene.vertex_count );
 }
 
-vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices )
+VG_TIER_2 void scene_builder_upload_async( scene_builder_context *ctx, scene_mesh *out_mesh )
 {
-   THREAD_1;
-
-   scene_init( scene, max_vertices, max_indices );
-   u32 buf_size = scene_mem_required( scene );
-
-   u32 hdr_size = vg_align8(sizeof(struct scene_upload_info));
-   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, hdr_size + buf_size, 1 );
-
-   struct scene_upload_info *info = (void *)task->data;
-
-   info->mesh = mesh;
-   info->ctx = scene;
-   scene_supply_buffer( scene, task->data + hdr_size );
-   return task;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   u32 task_args_size = vg_align8( sizeof(struct scene_upload_task) ),
+       vertex_buffer_size = vg_align8( sizeof(scene_vert) * ctx->scene.vertex_count ),
+       index_buffer_size = vg_align8( sizeof(u32) * ctx->scene.indice_count ),
+       total = task_args_size + vertex_buffer_size + index_buffer_size;
+   struct scene_upload_task *out_args = _vg_async_alloc( VG_THREAD_MAIN_ID, total );
+   out_args->scene.vertex_buffer = ((void *)out_args) + task_args_size;
+   out_args->scene.indice_buffer = ((void *)out_args) + task_args_size + vertex_buffer_size;
+   out_args->scene.vertex_count = ctx->scene.vertex_count;
+   out_args->scene.indice_count = ctx->scene.indice_count;
+   out_args->out_mesh = out_mesh;
+   memcpy( out_args->scene.vertex_buffer, ctx->scene.vertex_buffer, sizeof(scene_vert) * ctx->scene.vertex_count );
+   memcpy( out_args->scene.indice_buffer, ctx->scene.indice_buffer, sizeof(u32) * ctx->scene.indice_count );
+   _vg_async_send( out_args, (vg_async_fn)scene_upload_task );
 }
 
 /*
  * BVH implementation
  */
 
-static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
+static void scene_bh_expand_bound( vg_scene *scene, boxf bound, u32 item_index )
 {
-   scene_context *s = user;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
-              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
-              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
-   
+   scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+              *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+              *pc = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+2] ];
   box_addpt( bound, pa->co );
   box_addpt( bound, pb->co );
   box_addpt( bound, pc->co );
 }
 
-static float scene_bh_centroid( void *user, u32 item_index, int axis )
+static f32 scene_bh_centroid( vg_scene *scene, u32 item_index, i32 axis )
 {
-   scene_context *s = user;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
-              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
-              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
-
+   scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+              *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+              *pc = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+2] ];
    #if 0
 
    float min, max;
@@ -275,12 +227,10 @@ static float scene_bh_centroid( void *user, u32 item_index, int axis )
    #endif
 }
 
-static void scene_bh_swap( void *user, u32 ia, u32 ib )
+static void scene_bh_swap( vg_scene *scene, u32 ia, u32 ib )
 {
-   scene_context *s = user;
-
-   u32 *ti = &s->arrindices[ia*3];
-   u32 *tj = &s->arrindices[ib*3];
+   u32 *ti = &scene->indice_buffer[ia*3];
+   u32 *tj = &scene->indice_buffer[ib*3];
 
    u32 temp[3];
    temp[0] = ti[0];
@@ -296,76 +246,72 @@ static void scene_bh_swap( void *user, u32 ia, u32 ib )
    tj[2] = temp[2];
 }
 
-static void scene_bh_debug( void *user, u32 item_index )
+static void scene_bh_debug( vg_scene *scene, u32 item_index )
 {
-   scene_context *s = user;
    u32 idx = item_index*3;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[ idx+0 ] ],
-              *pb = &s->arrvertices[ s->arrindices[ idx+1 ] ],
-              *pc = &s->arrvertices[ s->arrindices[ idx+2 ] ];
-
+   scene_vert *pa = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+0] ],
+              *pb = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+1] ],
+              *pc = &scene->vertex_buffer[ scene->indice_buffer[item_index*3+2] ];
    vg_line( pa->co, pb->co, 0xff0000ff );
    vg_line( pb->co, pc->co, 0xff0000ff );
    vg_line( pc->co, pa->co, 0xff0000ff );
 }
 
-static void scene_bh_closest( void *user, u32 index, v3f point, v3f closest )
+static void scene_bh_closest( vg_scene *scene, u32 index, v3f point, v3f closest )
 {
-   scene_context *s = user;
-
    v3f positions[3];
-   u32 *tri = &s->arrindices[ index*3 ];
+   u32 *tri = &scene->indice_buffer[ index*3 ];
    for( int i=0; i<3; i++ )
-      v3_copy( s->arrvertices[tri[i]].co, positions[i] );
-
+      v3_copy( scene->vertex_buffer[tri[i]].co, positions[i] );
    closest_on_triangle_1( point, positions, closest );
 }
 
-bh_system bh_system_scene = 
+static bh_system bh_system_scene = 
 {
-   .expand_bound = scene_bh_expand_bound,
-   .item_centroid = scene_bh_centroid,
-   .item_closest = scene_bh_closest,
-   .item_swap = scene_bh_swap,
-   .item_debug = scene_bh_debug,
+   .expand_bound = (bh_expand_fn)scene_bh_expand_bound,
+   .item_centroid = (bh_centroid_fn)scene_bh_centroid,
+   .item_closest = (bh_closest_fn)scene_bh_closest,
+   .item_swap = (bh_swap_fn)scene_bh_swap,
+   .item_debug = (bh_debug_fn)scene_bh_debug,
 };
 
 /*
  * An extra step is added onto the end to calculate the hit normal
  */
-int scene_raycast( scene_context *s, bh_tree *bh, 
-                   v3f co, v3f dir, ray_hit *hit, u16 ignore )
+VG_TIER_0 i32 scene_raycast( vg_scene *scene, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore )
 {
    hit->tri = NULL;
-
    bh_iter it;
    bh_iter_init_ray( 0, &it, co, dir, hit->dist );
    i32 idx;
 
-   while( bh_next( bh, &it, &idx ) ){
-      u32 *tri = &s->arrindices[ idx*3 ];
-
-      if( s->arrvertices[tri[0]].flags & ignore )  continue;
+   while( bh_next( bh, &it, &idx ) )
+   {
+      u32 *tri = &scene->indice_buffer[ idx*3 ];
+      if( scene->vertex_buffer[tri[0]].flags & ignore )  
+         continue;
 
       v3f vs[3];
       for( u32 i=0; i<3; i++ )
-         v3_copy( s->arrvertices[tri[i]].co, vs[i] );
+         v3_copy( scene->vertex_buffer[tri[i]].co, vs[i] );
       
       f32 t;
-      if( ray_tri( vs, co, dir, &t, 0 ) ){
-         if( t < hit->dist ){
+      if( ray_tri( vs, co, dir, &t, 0 ) )
+      {
+         if( t < hit->dist )
+         {
             hit->dist = t;
             hit->tri = tri;
          }
       }
    }
 
-   if( hit->tri ){
+   if( hit->tri )
+   {
       v3f v0, v1;
-      
-      float *pa = s->arrvertices[hit->tri[0]].co,
-            *pb = s->arrvertices[hit->tri[1]].co,
-            *pc = s->arrvertices[hit->tri[2]].co;
+      f32 *pa = scene->vertex_buffer[hit->tri[0]].co,
+          *pb = scene->vertex_buffer[hit->tri[1]].co,
+          *pc = scene->vertex_buffer[hit->tri[2]].co;
 
       v3_sub( pa, pb, v0 );
       v3_sub( pc, pb, v1 );
@@ -377,8 +323,20 @@ int scene_raycast( scene_context *s, bh_tree *bh,
    return hit->tri?1:0;
 }
 
-bh_tree *scene_bh_create( void *lin_alloc, scene_context *s )
+VG_TIER_1 void scene_bh_create( vg_scene *scene, bh_tree *bh, vg_stack_allocator *stack )
+{
+   u32 triangle_count = scene->indice_count / 3;
+   return bh_create( bh, &bh_system_scene, scene, triangle_count, 2, stack );
+}
+
+VG_TIER_0 void scene_mesh_bind( scene_mesh *mesh )
+{
+   glBindVertexArray( mesh->vao );
+}
+
+VG_TIER_0 void scene_mesh_free( scene_mesh *mesh )
 {
-   u32 triangle_count = s->indice_count / 3;
-   return bh_create( lin_alloc, &bh_system_scene, s, triangle_count, 2 );
+   glDeleteVertexArrays( 1, &mesh->vao );
+   glDeleteBuffers( 1, &mesh->ebo );
+   glDeleteBuffers( 1, &mesh->vbo );
 }
index c2ba3a9c7146cbb8f8f44e0900dc79888c7bd703..afe1d9bffdb9973f2ae977ebbe1f0072f15e5a5d 100644 (file)
@@ -1,10 +1,11 @@
-#pragma once
-#include "vg/vg_bvh.h"
-#include "common.h"
-#include "model.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/scene.c"
+#else
 
-typedef struct scene_context scene_context;
+typedef struct scene_builder_context scene_builder_context;
 typedef struct scene_vert scene_vert;
+typedef struct scene_mesh scene_mesh;
+typedef struct vg_scene vg_scene;
 
 #pragma pack(push,1)
 
@@ -21,35 +22,44 @@ struct scene_vert
 
 #pragma pack(pop)
 
-/* 
- * 1. this should probably be a CONTEXT based approach unlike this mess.
- * take a bit of the mdl_context ideas and redo this header. its messed up
- * pretty bad right now.
- */
-
-struct scene_context
+struct vg_scene
 {
-   scene_vert *arrvertices;
-   u32 *arrindices;
+   scene_vert *vertex_buffer;
+   u32 *indice_buffer;
+   u32 vertex_count, indice_count;
+   boxf bbx;
+};
 
-   u32 vertex_count, indice_count,
-       max_vertices, max_indices;
+struct scene_builder_context
+{
+   vg_scene scene;
+   u32 base_buffer_size;
+   void *base_buffer;
+   vg_stack_allocator vertex_stack, indice_stack;
+   mdl_submesh current_submesh;
+};
 
+struct scene_mesh
+{
    boxf bbx;
-   mdl_submesh submesh;
+   GLuint vao, vbo, ebo;
 };
 
-extern bh_system bh_system_scene;
-bh_tree *scene_bh_create( void *lin_alloc, scene_context *s );
-int scene_raycast( scene_context *s, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore );
-vg_async_task *scene_alloc_async( scene_context *scene, glmesh *mesh, u32 max_vertices, u32 max_indices );
-void scene_copy_slice( scene_context *ctx, mdl_submesh *sm );
-void scene_push_vert( scene_context *ctx, scene_vert *v );
-void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
-void scene_push_tri( scene_context *ctx, u32 tri[3] );
-void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, mdl_submesh *sm, m4x3f transform );
-void scene_set_vertex_flags( scene_context *ctx, u32 start, u32 count, u16 flags );
-void scene_supply_buffer( scene_context *ctx, void *buffer );
-void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices );
-u32 scene_mem_required( scene_context *ctx );
-void async_scene_upload( vg_async_task *task );
+VG_TIER_2 void scene_builder_init( scene_builder_context *ctx, u32 max_vertices, u32 max_indices, vg_stack_allocator *stack );
+VG_TIER_2 void scene_builder_compact_memory( scene_builder_context *ctx, vg_stack_allocator *stack );
+VG_TIER_0 void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
+VG_TIER_0 void scene_builder_add_model_submesh( scene_builder_context *ctx, vg_model *model, mdl_submesh *sm, m4x3f transform );
+VG_TIER_0 void scene_builder_push_tri( scene_builder_context *ctx, u32 tri[3] );
+VG_TIER_0 void scene_builder_push_vert( scene_builder_context *ctx, scene_vert *v );
+VG_TIER_0 void scene_builder_get_submesh( scene_builder_context *ctx, mdl_submesh *sm );
+VG_TIER_0 void scene_builder_set_vertex_flags( scene_builder_context *ctx, u32 start, u32 count, u16 flags );
+VG_TIER_2 void scene_builder_upload_async( scene_builder_context *ctx, scene_mesh *out_mesh );
+VG_TIER_0 void scene_builder_save_scene( scene_builder_context *ctx, vg_scene *out_scene );
+
+VG_TIER_0 void scene_mesh_bind( scene_mesh *mesh );
+VG_TIER_0 void scene_mesh_free( scene_mesh *mesh );
+
+VG_TIER_0 i32 scene_raycast( vg_scene *scene, bh_tree *bh, v3f co, v3f dir, ray_hit *hit, u16 ignore );
+VG_TIER_1 void scene_bh_create( vg_scene *scene, bh_tree *bh, vg_stack_allocator *stack );
+
+#endif
diff --git a/src/scene_rigidbody.c b/src/scene_rigidbody.c
new file mode 100644 (file)
index 0000000..d63f778
--- /dev/null
@@ -0,0 +1,245 @@
+VG_TIER_0 i32 rb_sphere__scene( m4x3f mtxA, f32 r, 
+                                m4x3f mtxB, bh_tree *scene_bh, 
+                                rb_ct *buf, u16 ignore )
+{
+   vg_scene *scene = scene_bh->user;
+   i32 count = 0;
+
+   boxf box;
+   v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
+   v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
+
+   bh_iter it;
+   i32 idx;
+   bh_iter_init_box( 0, &it, box );
+   
+   while( bh_next( scene_bh, &it, &idx ) )
+   {
+      u32 *ptri = &scene->indice_buffer[ idx*3 ];
+      v3f tri[3];
+
+      if( scene->vertex_buffer[ptri[0]].flags & ignore ) 
+         continue;
+
+      for( u32 j=0; j<3; j++ )
+         v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+      buf[ count ].element_id = ptri[0];
+
+      vg_line( tri[0],tri[1],0x70ff6000 );
+      vg_line( tri[1],tri[2],0x70ff6000 );
+      vg_line( tri[2],tri[0],0x70ff6000 );
+
+      i32 contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] );
+      count += contact;
+
+      if( count == 16 )
+      {
+         vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" );
+         return count;
+      }
+   }
+   return count;
+}
+
+VG_TIER_0 i32 rb_box__scene( m4x3f mtxA, boxf bbx,
+                             m4x3f mtxB, bh_tree *scene_bh, 
+                             rb_ct *buf, u16 ignore )
+{
+   vg_scene *scene = scene_bh->user;
+   v3f tri[3];
+
+   v3f extent, center;
+   v3_sub( bbx[1], bbx[0], extent );
+   v3_muls( extent, 0.5f, extent );
+   v3_add( bbx[0], extent, center );
+
+   f32 r = v3_length(extent);
+   boxf world_bbx;
+   v3_fill( world_bbx[0], -r );
+   v3_fill( world_bbx[1],  r );
+   for( u32 i=0; i<2; i++ )
+   {
+      v3_add( center, world_bbx[i], world_bbx[i] );
+      v3_add( mtxA[3], world_bbx[i], world_bbx[i] );
+   }
+
+   m4x3f to_local;
+   m4x3_invert_affine( mtxA, to_local );
+
+   bh_iter it;
+   bh_iter_init_box( 0, &it, world_bbx );
+   i32 idx;
+   i32 count = 0;
+
+   vg_line_boxf( world_bbx, VG__RED );
+   
+   while( bh_next( scene_bh, &it, &idx ) )
+   {
+      u32 *ptri = &scene->indice_buffer[ idx*3 ];
+      if( scene->vertex_buffer[ptri[0]].flags & ignore ) 
+         continue;
+
+      for( u32 j=0; j<3; j++ )
+         v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+
+      if( rb_box_triangle_sat( extent, center, to_local, tri ) )
+      {
+         vg_line(tri[0],tri[1],0xff50ff00 );
+         vg_line(tri[1],tri[2],0xff50ff00 );
+         vg_line(tri[2],tri[0],0xff50ff00 );
+      }
+      else
+      {
+         vg_line(tri[0],tri[1],0xff0000ff );
+         vg_line(tri[1],tri[2],0xff0000ff );
+         vg_line(tri[2],tri[0],0xff0000ff );
+         continue;
+      }
+
+      v3f v0,v1,n;
+      v3_sub( tri[1], tri[0], v0 );
+      v3_sub( tri[2], tri[0], v1 );
+      v3_cross( v0, v1, n );
+
+      if( v3_length2( n ) <= 0.00001f )
+      {
+#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
+         vg_error( "Zero area triangle!\n" );
+#endif
+         return 0;
+      }
+      v3_normalize( n );
+
+      /* find best feature */
+      f32 best = v3_dot( mtxA[0], n );
+      i32 axis = 0;
+
+      for( i32 i=1; i<3; i++ )
+      {
+         f32 c = v3_dot( mtxA[i], n );
+         if( fabsf(c) > fabsf(best) )
+         {
+            best = c;
+            axis = i;
+         }
+      }
+
+      v3f manifold[4];
+      if( axis == 0 )
+      {
+         f32 px = best > 0.0f? bbx[0][0]: bbx[1][0];
+         manifold[0][0] = px;
+         manifold[0][1] = bbx[0][1];
+         manifold[0][2] = bbx[0][2];
+         manifold[1][0] = px;
+         manifold[1][1] = bbx[1][1];
+         manifold[1][2] = bbx[0][2];
+         manifold[2][0] = px;
+         manifold[2][1] = bbx[1][1];
+         manifold[2][2] = bbx[1][2];
+         manifold[3][0] = px;
+         manifold[3][1] = bbx[0][1];
+         manifold[3][2] = bbx[1][2];
+      }
+      else if( axis == 1 )
+      {
+         f32 py = best > 0.0f? bbx[0][1]: bbx[1][1];
+         manifold[0][0] = bbx[0][0];
+         manifold[0][1] = py;
+         manifold[0][2] = bbx[0][2];
+         manifold[1][0] = bbx[1][0];
+         manifold[1][1] = py;
+         manifold[1][2] = bbx[0][2];
+         manifold[2][0] = bbx[1][0];
+         manifold[2][1] = py;
+         manifold[2][2] = bbx[1][2];
+         manifold[3][0] = bbx[0][0];
+         manifold[3][1] = py;
+         manifold[3][2] = bbx[1][2];
+      }
+      else
+      {
+         f32 pz = best > 0.0f? bbx[0][2]: bbx[1][2];
+         manifold[0][0] = bbx[0][0];
+         manifold[0][1] = bbx[0][1];
+         manifold[0][2] = pz;
+         manifold[1][0] = bbx[1][0];
+         manifold[1][1] = bbx[0][1];
+         manifold[1][2] = pz;
+         manifold[2][0] = bbx[1][0];
+         manifold[2][1] = bbx[1][1];
+         manifold[2][2] = pz;
+         manifold[3][0] = bbx[0][0];
+         manifold[3][1] = bbx[1][1];
+         manifold[3][2] = pz;
+      }
+   
+      for( u32 j=0; j<4; j++ )
+         m4x3_mulv( mtxA, manifold[j], manifold[j] );
+
+      vg_line( manifold[0], manifold[1], 0xffffffff );
+      vg_line( manifold[1], manifold[2], 0xffffffff );
+      vg_line( manifold[2], manifold[3], 0xffffffff );
+      vg_line( manifold[3], manifold[0], 0xffffffff );
+
+      for( u32 j=0; j<4; j++ )
+      {
+         rb_ct *ct = buf+count;
+         v3_copy( manifold[j], ct->co );
+         v3_copy( n, ct->n );
+
+         f32 l0 = v3_dot( tri[0], n ),
+             l1 = v3_dot( manifold[j], n );
+
+         ct->p = (l0-l1)*0.5f;
+         if( ct->p < 0.0f )
+            continue;
+
+         ct->type = k_contact_type_default;
+         count ++;
+
+         if( count >= 12 )
+            return count;
+      }
+   }
+   return count;
+}
+
+/* mtxB is defined only for tradition; it is not used currently */
+VG_TIER_0 i32 rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
+                                 m4x3f mtxB, bh_tree *scene_bh, 
+                                 rb_ct *buf, u16 ignore )
+{
+   vg_scene *scene = scene_bh->user;
+   i32 count = 0;
+   boxf bbx;
+   v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] );
+   v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] );
+   
+   
+   bh_iter it;
+   bh_iter_init_box( 0, &it, bbx );
+   i32 idx;
+   while( bh_next( scene_bh, &it, &idx ) )
+   {
+      u32 *ptri = &scene->indice_buffer[ idx*3 ];
+      if( scene->vertex_buffer[ptri[0]].flags & ignore ) 
+         continue;
+
+      v3f tri[3];
+      for( u32 j=0; j<3; j++ )
+         v3_copy( scene->vertex_buffer[ptri[j]].co, tri[j] );
+      
+      buf[ count ].element_id = ptri[0];
+      i32 contact = rb_capsule__triangle( mtxA, c, tri, &buf[count] );
+      count += contact;
+
+      if( count >= 16 )
+      {
+         vg_warn("Exceeding capsule_vs_scene capacity. Geometry too dense!\n");
+         return count;
+      }
+   }
+
+   return count;
+}
index 57ff1ffd059ad60e5a5d0cace8c2612bd49a6574..e219255d2978952addf6e25ca0b93e7bdc8251bc 100644 (file)
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/scene_rigidbody.c"
+#else
 
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * Describes intereactions between vg rigidbody objects and skaterift's scene
- * description
- */
+VG_TIER_0 i32 rb_sphere__scene( m4x3f mtxA, f32 r, 
+                                m4x3f mtxB, bh_tree *scene_bh, 
+                                rb_ct *buf, u16 ignore );
 
-#include "scene.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-
-static int rb_sphere__scene( m4x3f mtxA, f32 r,
-                             m4x3f mtxB, bh_tree *scene_bh, rb_ct *buf, 
-                             u16 ignore ){
-   scene_context *sc = scene_bh->user;
-
-   int count = 0;
-
-   boxf box;
-   v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] );
-   v3_add( mtxA[3], (v3f){ r,r,r }, box[1] );
-
-   bh_iter it;
-   i32 idx;
-   bh_iter_init_box( 0, &it, box );
-   
-   while( bh_next( scene_bh, &it, &idx ) ){
-      u32 *ptri = &sc->arrindices[ idx*3 ];
-      v3f tri[3];
-
-      if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
-      for( int j=0; j<3; j++ )
-         v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-      
-      buf[ count ].element_id = ptri[0];
-
-      vg_line( tri[0],tri[1],0x70ff6000 );
-      vg_line( tri[1],tri[2],0x70ff6000 );
-      vg_line( tri[2],tri[0],0x70ff6000 );
-
-      int contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] );
-      count += contact;
-
-      if( count == 16 ){
-         vg_warn( "Exceeding sphere_vs_scene capacity. Geometry too dense!\n" );
-         return count;
-      }
-   }
-
-   return count;
-}
-
-static int rb_box__scene( m4x3f mtxA, boxf bbx,
-                          m4x3f mtxB, bh_tree *scene_bh, 
-                          rb_ct *buf, u16 ignore ){
-   scene_context *sc = scene_bh->user;
-   v3f tri[3];
-
-   v3f extent, center;
-   v3_sub( bbx[1], bbx[0], extent );
-   v3_muls( extent, 0.5f, extent );
-   v3_add( bbx[0], extent, center );
-
-   f32 r = v3_length(extent);
-   boxf world_bbx;
-   v3_fill( world_bbx[0], -r );
-   v3_fill( world_bbx[1],  r );
-   for( int i=0; i<2; i++ ){
-      v3_add( center, world_bbx[i], world_bbx[i] );
-      v3_add( mtxA[3], world_bbx[i], world_bbx[i] );
-   }
-
-   m4x3f to_local;
-   m4x3_invert_affine( mtxA, to_local );
-
-   bh_iter it;
-   bh_iter_init_box( 0, &it, world_bbx );
-   int idx;
-   int count = 0;
-
-   vg_line_boxf( world_bbx, VG__RED );
-   
-   while( bh_next( scene_bh, &it, &idx ) ){
-      u32 *ptri = &sc->arrindices[ idx*3 ];
-      if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
-      for( int j=0; j<3; j++ )
-         v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-
-      if( rb_box_triangle_sat( extent, center, to_local, tri ) ){
-         vg_line(tri[0],tri[1],0xff50ff00 );
-         vg_line(tri[1],tri[2],0xff50ff00 );
-         vg_line(tri[2],tri[0],0xff50ff00 );
-      }
-      else{
-         vg_line(tri[0],tri[1],0xff0000ff );
-         vg_line(tri[1],tri[2],0xff0000ff );
-         vg_line(tri[2],tri[0],0xff0000ff );
-         continue;
-      }
-
-      v3f v0,v1,n;
-      v3_sub( tri[1], tri[0], v0 );
-      v3_sub( tri[2], tri[0], v1 );
-      v3_cross( v0, v1, n );
-
-      if( v3_length2( n ) <= 0.00001f ){
-#ifdef RIGIDBODY_CRY_ABOUT_EVERYTHING
-         vg_error( "Zero area triangle!\n" );
-#endif
-         return 0;
-      }
-
-      v3_normalize( n );
-
-      /* find best feature */
-      f32 best = v3_dot( mtxA[0], n );
-      int axis = 0;
-
-      for( int i=1; i<3; i++ ){
-         f32 c = v3_dot( mtxA[i], n );
-
-         if( fabsf(c) > fabsf(best) ){
-            best = c;
-            axis = i;
-         }
-      }
-
-      v3f manifold[4];
-
-      if( axis == 0 ){
-         f32 px = best > 0.0f? bbx[0][0]: bbx[1][0];
-         manifold[0][0] = px;
-         manifold[0][1] = bbx[0][1];
-         manifold[0][2] = bbx[0][2];
-         manifold[1][0] = px;
-         manifold[1][1] = bbx[1][1];
-         manifold[1][2] = bbx[0][2];
-         manifold[2][0] = px;
-         manifold[2][1] = bbx[1][1];
-         manifold[2][2] = bbx[1][2];
-         manifold[3][0] = px;
-         manifold[3][1] = bbx[0][1];
-         manifold[3][2] = bbx[1][2];
-      }
-      else if( axis == 1 ){
-         f32 py = best > 0.0f? bbx[0][1]: bbx[1][1];
-         manifold[0][0] = bbx[0][0];
-         manifold[0][1] = py;
-         manifold[0][2] = bbx[0][2];
-         manifold[1][0] = bbx[1][0];
-         manifold[1][1] = py;
-         manifold[1][2] = bbx[0][2];
-         manifold[2][0] = bbx[1][0];
-         manifold[2][1] = py;
-         manifold[2][2] = bbx[1][2];
-         manifold[3][0] = bbx[0][0];
-         manifold[3][1] = py;
-         manifold[3][2] = bbx[1][2];
-      }
-      else{
-         f32 pz = best > 0.0f? bbx[0][2]: bbx[1][2];
-         manifold[0][0] = bbx[0][0];
-         manifold[0][1] = bbx[0][1];
-         manifold[0][2] = pz;
-         manifold[1][0] = bbx[1][0];
-         manifold[1][1] = bbx[0][1];
-         manifold[1][2] = pz;
-         manifold[2][0] = bbx[1][0];
-         manifold[2][1] = bbx[1][1];
-         manifold[2][2] = pz;
-         manifold[3][0] = bbx[0][0];
-         manifold[3][1] = bbx[1][1];
-         manifold[3][2] = pz;
-      }
-   
-      for( int j=0; j<4; j++ )
-         m4x3_mulv( mtxA, manifold[j], manifold[j] );
-
-      vg_line( manifold[0], manifold[1], 0xffffffff );
-      vg_line( manifold[1], manifold[2], 0xffffffff );
-      vg_line( manifold[2], manifold[3], 0xffffffff );
-      vg_line( manifold[3], manifold[0], 0xffffffff );
-
-      for( int j=0; j<4; j++ ){
-         rb_ct *ct = buf+count;
-
-         v3_copy( manifold[j], ct->co );
-         v3_copy( n, ct->n );
-
-         f32 l0 = v3_dot( tri[0], n ),
-               l1 = v3_dot( manifold[j], n );
-
-         ct->p = (l0-l1)*0.5f;
-         if( ct->p < 0.0f )
-            continue;
-
-         ct->type = k_contact_type_default;
-         count ++;
-
-         if( count >= 12 )
-            return count;
-      }
-   }
-   return count;
-}
+VG_TIER_0 i32 rb_box__scene( m4x3f mtxA, boxf bbx,
+                             m4x3f mtxB, bh_tree *scene_bh, 
+                             rb_ct *buf, u16 ignore );
 
 /* mtxB is defined only for tradition; it is not used currently */
-static int rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
-                              m4x3f mtxB, bh_tree *scene_bh, 
-                              rb_ct *buf, u16 ignore ){
-   int count = 0;
-
-   boxf bbx;
-   v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] );
-   v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] );
-   
-   scene_context *sc = scene_bh->user;
-   
-   bh_iter it;
-   bh_iter_init_box( 0, &it, bbx );
-   i32 idx;
-   while( bh_next( scene_bh, &it, &idx ) ){
-      u32 *ptri = &sc->arrindices[ idx*3 ];
-      if( sc->arrvertices[ptri[0]].flags & ignore ) continue;
-
-      v3f tri[3];
-      for( int j=0; j<3; j++ )
-         v3_copy( sc->arrvertices[ptri[j]].co, tri[j] );
-      
-      buf[ count ].element_id = ptri[0];
-
-      int contact = rb_capsule__triangle( mtxA, c, tri, &buf[count] );
-      count += contact;
-
-      if( count >= 16 ){
-         vg_warn("Exceeding capsule_vs_scene capacity. Geometry too dense!\n");
-         return count;
-      }
-   }
-
-   return count;
-}
+VG_TIER_0 i32 rb_capsule__scene( m4x3f mtxA, rb_capsule *c,
+                                 m4x3f mtxB, bh_tree *scene_bh, 
+                                 rb_ct *buf, u16 ignore );
 
+#endif
index 6788e1ac8f94360a3dd169429b9c436619a50bc5..12629d69c95abe66b3cd379d8a2041f1ff568ee9 100644 (file)
@@ -4,7 +4,7 @@ static bool _skaterift_script_board_maker( ent_script_event *event )
    {
       struct script_event_world_io *inf = event->info;
       world_instance *world = &_world.main;
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "open" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "open" ) ) 
       {
          // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
          if( inf->event->flags & k_ent_event_data_const_entity_id )
@@ -22,7 +22,7 @@ static bool _skaterift_script_board_maker( ent_script_event *event )
             while( _ent_list_iter( &iter ) )
             {
                ent_marker *marker = af_arritm( &world->ent_marker, iter.index );
-               const char *alias = af_str( &world->meta.af, marker->pstr_alias );
+               const char *alias = af_str( world->meta.packed_strings, marker->pstr_alias );
 
                if( !strcmp( alias, "$board_position" ) )
                   v3_copy( marker->transform.co, _board_maker.origin );
index 2f3fb4231d272d81152537b1c427899b4103c5f1..6a0a3ed1e1ef5fb5a1d8e7dc547d66881b0a182d 100644 (file)
@@ -4,7 +4,7 @@ static bool _script_boost( ent_script_event *event )
    {
       struct script_event_world_io *inf = event->info;
       world_instance *world = &_world.main;
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "boost" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "boost" ) ) 
       {
          // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
          if( inf->event->flags & k_ent_event_data_const_entity_id )
index d5de82d01d66f1e26d968f6dcabc21472cdeccd1..b9b1488f86008f3109f0182ee66b1cbd4ec53bd5 100644 (file)
@@ -4,7 +4,7 @@ static bool _skaterift_script_explode( ent_script_event *event )
    {
       struct script_event_world_io *inf = event->info;
       world_instance *world = &_world.main;
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "explode" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "explode" ) ) 
       {
          // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
          if( inf->event->flags & k_ent_event_data_const_entity_id )
index 2480cf979acee3676c9f5ab91bb30317ddbf3d05..394151ca260af19731e68bc2469a7b1e5cccc5aa 100644 (file)
@@ -4,17 +4,17 @@ static bool _skaterift_script_generic( ent_script_event *event )
    {
       struct script_event_world_io *inf = event->info;
       world_instance *world = &_world.main;
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_mtzero" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_mtzero" ) ) 
       {
-         gui_notify( "\xb8 Mt.Zero Unlocked!", 8.0f, k_ui_green );
+         _gui_notify( "\xb8 Mt.Zero Unlocked!", 8.0f, k_ui_green );
       }
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_city" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_city" ) ) 
       {
-         gui_notify( "\xb8 Downtown Unlocked!", 8.0f, k_ui_green );
+         _gui_notify( "\xb8 Downtown Unlocked!", 8.0f, k_ui_green );
       }
-      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_valley" ) ) 
+      if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_valley" ) ) 
       {
-         gui_notify( "\xb8 Valley Unlocked!", 8.0f, k_ui_green );
+         _gui_notify( "\xb8 Valley Unlocked!", 8.0f, k_ui_green );
       }
    }
    return 1;
index ca1f3ee50bd816042727b9ea45c8ac17aadabfc5..b144e63971011cdebd3d5b42b5964259cd594459 100644 (file)
@@ -8,7 +8,7 @@ static bool _script_l1_speed( ent_script_event *event )
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
-      struct script_speed *s = VG_STACK_ALLOCATE_STRUCT( event_info->heap, struct script_speed );
+      struct script_speed *s = vg_stack_allocate( event_info->heap, sizeof(struct script_speed), 8, "Script data" );
       s->ok = 0;
       s->init = 0;
       event_info->userdata = s;
index eff9853db187d8731007906f856623e8bacca2fb..1bfd76aa9e70bb2cc2681e965292455204ac98a4 100644 (file)
@@ -9,7 +9,7 @@ static bool _skaterift_script_volc( ent_script_event *event )
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
-      struct script_volcano *v = VG_STACK_ALLOCATE_STRUCT( event_info->heap, struct script_volcano );
+      struct script_volcano *v = vg_stack_allocate( event_info->heap, sizeof(struct script_volcano), 8, "Script data" );
       v->docks_wait = 0;
       v->stopped_timer = 0.0f;
       event_info->userdata = v;
@@ -22,7 +22,7 @@ static bool _skaterift_script_volc( ent_script_event *event )
       struct script_event_world_io *inf = event->info;
       world_instance *world = &_world.main;
 
-           if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "unlock_docks" ) )
+           if( AF_STR_EQ( world->meta.packed_strings, inf->event->pstr_recieve_event, "unlock_docks" ) )
       {
          v->docks_wait = 1;
       }
diff --git a/src/serialized_replay.h b/src/serialized_replay.h
deleted file mode 100644 (file)
index c5e76c6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-#include "network_msg.h"
index 43cf6ff02dfa38bd0f695bfd96ab92618404e124..33ab07d24a241217e1495dc2b502525263bf56fe 100644 (file)
@@ -1,47 +1,12 @@
-#pragma once
-#include "vg/vg_platform.h"
+#if defined( SR_IMPLEMENTATION )
+//# include "src/shader_props.c"
+#else
 
 enum material_render_flag
 {
    k_material_render_additive = 0x20
 };
 
-struct shader_props_standard
-{
-   u32 tex_diffuse;
-   u32 render_flags;
-};
-
-struct shader_props_terrain
-{
-   u32 tex_diffuse;
-   v2f blend_offset;
-   v4f sand_colour;
-};
-
-struct shader_props_vertex_blend
-{
-   u32 tex_diffuse;
-   v2f blend_offset;
-};
-
-struct shader_props_water
-{
-   v4f shore_colour;
-   v4f deep_colour;
-   f32 fog_scale;
-   f32 fresnel;
-   f32 water_sale;
-   v4f wave_speed;
-};
-
-struct shader_props_cubemapped
-{
-   u32 tex_diffuse;
-   u32 cubemap_entity;
-   v4f tint;
-};
-
 enum workshop_shader_part
 {
    k_workshop_shader_part_truck1,
@@ -55,8 +20,57 @@ enum workshop_shader_part
    k_workshop_shader_part_deck,
    k_workshop_shader_part_max
 };
-struct shader_props_workshop
+
+union shader_props
 {
-   u32 tex_all[k_workshop_shader_part_max];
+   struct shader_props_standard
+   {
+      u32 tex_diffuse;
+      u32 render_flags;
+   }
+   standard;
+
+   struct shader_props_terrain
+   {
+      u32 tex_diffuse;
+      v2f blend_offset;
+      v4f sand_colour;
+   }
+   terrain;
+
+   struct shader_props_vertex_blend
+   {
+      u32 tex_diffuse;
+      v2f blend_offset;
+   }
+   vertex_blend;
+
+   struct shader_props_water
+   {
+      v4f shore_colour;
+      v4f deep_colour;
+      f32 fog_scale;
+      f32 fresnel;
+      f32 water_sale;
+      v4f wave_speed;
+   }
+   water;
+
+   struct shader_props_cubemapped
+   {
+      u32 tex_diffuse;
+      u32 cubemap_entity;
+      v4f tint;
+   }
+   cubemapped;
+
+   struct shader_props_workshop
+   {
+      u32 tex_all[k_workshop_shader_part_max];
+   }
+   workshop;
 };
+
 extern const char *_shader_prop_workshop_keys[k_workshop_shader_part_max];
+
+#endif
index e4652e7336cc707cce9abca5c256c1e2a6811fc2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,721 +0,0 @@
-/*
- * =============================================================================
- *
- * Copyright  .        . .       -----, ,----- ,---.   .---.
- * 2021-2025  |\      /| |           /  |      |    | |    /|
- *            | \    / | +--        /   +----- +---'  |   / |
- *            |  \  /  | |         /    |      |   \  |  /  |
- *            |   \/   | |        /     |      |    \ | /   |
- *            '        ' '--' [] '----- '----- '     ' '---'  SOFTWARE
- *
- * =============================================================================
- */
-
-#define SR_ALLOW_REWIND_HUB
-
-#ifdef _WIN32
- #include <winsock2.h>
-#endif
-
-/* 
- *     system headers
- * --------------------- */
-
-#include "vg/vg_opt.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-
-#include "skaterift.h"
-#include "render.h"
-#include "world.h"
-#include "font.h"
-#include "player.h"
-#include "network.h"
-#include "menu.h"
-#include "save.h"
-#include "player_remote.h"
-#include "particle.h"
-#include "trail.h"
-#include "freecam.h"
-#include "ent_tornado.h"
-#include "ent_skateshop.h"
-#include "ent_camera.h"
-#include "world_map.h"
-#include "gui.h"
-#include "workshop.h"
-#include "audio.h"
-#include "player_render.h"
-#include "control_overlay.h"
-#include "client.h"
-#include "skaterift_script.h"
-#include "ent_challenge.h"
-#include "ent_script.h"
-#include "board_maker.h"
-#include "compass.h"
-#include "replay2.h"
-#include "user_profile.h"
-#include "ent_route.h"
-#include "ent_npc.h"
-#include "ent_list.h"
-#include "ent_atom.h"
-
-struct skaterift_globals skaterift = 
-{ 
-   .time_rate = 1.0f,
-};
-
-static void skaterift_load_player_content(void)
-{
-   particle_alloc( &particles_grind, 300 );
-   particle_alloc( &particles_env, 200 );
-
-   player_load_animation_reference( "models/ch_none.mdl" );
-   player_load_animations( "metascenes/skater.ms" );
-   player_model_load( &localplayer.fallback_model, "models/ch_none.mdl", &vg.rtmem );
-   player__bind();
-   player_board_load( &localplayer.fallback_board, "models/board_none.mdl", &vg.rtmem );
-}
-
-int skaterift_quit_command( int argc, const char *argv[] )
-{
-   if( argc >= 1 )
-      if( !strcmp( argv[0], "1" ) )
-         skaterift.no_save_location = 1;
-
-   vg.window_should_close = 1;
-   return 1;
-}
-
-static void game_load_co( vg_coroutine *co )
-{
-   if( co_begin( co ) )
-   {
-      co_thread( co, 0, &vg.main_tasks );
-      co_thread( co, 1, &vg.loader_tasks );
-   }
-
-   if( co_step( co, 1 ) )
-   {
-      vg_loader_step( render_init, NULL );
-
-      /* please forgive me! */
-      if( g_client.demo_mode != 2 )
-      {
-         u32 sz; char *drm;
-         if( (drm = vg_file_read( &vg.scratch, "DRM", &sz, 1 )) )
-            if( !strcmp(drm, "blibby!") )
-               g_client.demo_mode = 0;
-      }
-
-      vg_loader_step( remote_players_init, NULL );
-
-      vg_loader_step( network_init, network_end );
-      vg_loader_set_user_information( "Initializing subsystems" );
-      vg_loader_step( menu_init, NULL );
-      vg_loader_step( _user_profile_init, NULL );
-      vg_loader_step( control_overlay_init, NULL );
-      vg_loader_step( world_init, NULL );
-      vg_loader_step( gui_init, NULL );
-      vg_loader_step( compass_init, NULL );
-
-      vg_loader_step( player_init, NULL );
-
-      /* content stuff */
-      vg_loader_step( addon_system_init, NULL );
-      vg_loader_step( skateshop_init, NULL );
-      vg_loader_step( world_map_init, NULL );
-      vg_loader_step( skaterift_load_player_content, NULL );
-      vg_loader_step( _replay2_init, NULL );
-      vg_loader_step( _ent_npc_init, NULL );
-
-      vg_loader_set_user_information( "Compiling shaders" );
-      vg_bake_shaders();
-
-      vg_loader_set_user_information( "Loading content files" );
-      vg_loader_step( audio_init, NULL );
-
-      _world.default_hub_addon = _addon_mount_from_folder_path( "maps/dev_hub", k_addon_type_world, ".mdl" );
-      VG_ASSERT( _world.default_hub_addon );
-
-      vg_loader_set_user_information( "Mounting addons" );
-      _addon_mount_content_folder( k_addon_type_player, "playermodels", ".mdl" );
-      _addon_mount_content_folder( k_addon_type_board, "boards", ".mdl" );
-      _addon_mount_content_folder( k_addon_type_world, "maps", ".mdl" );
-   }
-
-   if( co_step( co, 0 ) )
-   {
-      _mount_workshop_addons( NULL );
-      _ent_atom_init();
-   }
-
-   /* stalling for workshop to complete */
-   if( co_step( co, 1 ) ){}
-   if( co_step( co, 0 ) ){}
-
-   if( co_step( co, 1 ) )
-   {
-      /* initializing / loading world. */
-      vg_loader_set_user_information( "Loading savedata" );
-      skaterift_load_mainsave();
-
-      if( skaterift.override_load_world )
-         _world.load_addon = _addon_mount_from_folder_path( skaterift.override_load_world, k_addon_type_world, ".mdl" );
-
-      _world.loader_instance = &_world.main;
-      _world.loader_preview_mode = 0;
-      _world.loader_stack = _world.stack;
-
-      if( !_world.load_addon )
-      {
-         vg_warn( "Falling back to default hub world...\n" );
-         _world.load_addon = _world.default_hub_addon;
-      }
-
-      _world_loader_set_addon( _world.load_addon );
-   }
-
-   if( co_step( co, 0 ) )
-   {
-      _world.loader_state = k_world_loader_ready;
-
-      if( network_client.auto_connect )
-         network_client.user_intent = k_server_intent_online;
-      menu_at_begin();
-   }
-
-   if( co_step( co, 1 ) )
-   {
-      vg_loader_step( NULL, skaterift_autosave_synchronous );
-      _vg_tower_set_flag( vg.sig_client, 1 );
-   }
-
-   co_end( co );
-}
-
-/* 
- * UPDATE LOOP
- * ---------------------------------------------------------------------------*/
-
-static void draw_origin_axis(void)
-{
-   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
-   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
-   vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
-}
-void skaterift_change_client_world_preupdate(void);
-
-void vg_pre_update(void)
-{
-   if( !_vg_tower_clearence( _vg_tower_mask(vg.sig_engine)|_vg_tower_mask(vg.sig_client) ) )
-      return;
-
-   skaterift_preupdate_inputs();
-   world_switcher_update();
-
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-      return;
-
-   //draw_origin_axis();
-   //_skaterift_script_update();
-   _addon_system_pre_update();
-   network_update();
-
-   /* time rate */
-   f32 target = 1;
-   if( skaterift.activity & k_skaterift_replay )
-      target = 0;
-
-   if( skaterift.activity == k_skaterift_spectate )
-   {
-      if( button_down( k_srbind_mback ) )
-      {
-         vg_audio_lock();
-         vg_audio_oneshot( &audio_ui[3], 1.0f, 0.0f, 0, 0 );
-         vg_audio_unlock();
-         menu_close(); /* sets tate to default*/
-         menu_open( k_menu_page_quick );
-         gui_helper_reset( k_gui_helper_mode_clear );
-         localplayer.immobile = 0;
-      }
-   }
-
-   world_update( &_world.main, localplayer.rb.co );
-   _board_maker_pre_update();
-
-   cutscene_update( vg.time_rate * vg.time_frame_delta );
-
-   if( !((skaterift.activity == k_skaterift_menu) && (menu.page != k_menu_page_quick)) )
-      player__pre_update();
-
-   _replay2_pre_update();
-   remote_sfx_pre_update();
-
-   v3f listen_co;
-   v3_copy( localplayer.rb.co, listen_co );
-   if( skaterift.activity & k_skaterift_menu )
-   {
-      if( menu.page != k_menu_page_quick )
-      {
-         if( menu.bg_cam )
-            v3_copy( menu.bg_cam->co, listen_co );
-         else target = 0;
-      }
-   }
-   audio_ambient_sprites_update( &_world.main, listen_co );
-
-   vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) );
-   vg.time_rate = vg_smoothstepf( skaterift.time_rate );
-}
-
-void vg_fixed_update(void)
-{
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-      return;
-
-   world_routes_fixedupdate( &_world.main );
-   player__update();
-}
-
-void vg_post_update(void)
-{
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-      return;
-
-   player__post_update();
-
-   float dist;
-   int sample_index;
-   world_audio_sample_distances( localplayer.rb.co, &sample_index, &dist );
-
-   vg_audio_lock();
-   vg_dsp.echo_distances[sample_index] = dist;
-
-   v3f ears = { 1.0f,0.0f,0.0f };
-   m3x3_mulv( g_render.cam.transform, ears, ears );
-   v3_copy( ears, _vg_audio.controls.listener_right_ear_direction );
-   v3_copy( g_render.cam.transform[3], _vg_audio.controls.listener_position );
-
-   if( localplayer.gate_waiting )
-      m4x3_mulv( localplayer.gate_waiting->transport, _vg_audio.controls.listener_position, _vg_audio.controls.listener_position );
-
-   v3_copy( localplayer.rb.v, _vg_audio.controls.listener_velocity );
-   vg_audio_unlock();
-
-   skaterift_autosave_update();
-
-   localplayer.immunity = 0;
-}
-
-/*
- * RENDERING
- * ---------------------------------------------------------------------------*/
-
-static void render_player_transparent(void)
-{
-   if( (skaterift.activity == k_skaterift_menu) &&
-       (menu.page == k_menu_page_main) && 
-       (menu.main_index == k_menu_main_guide) )
-   {
-      return;
-   }
-
-   if( skaterift.activity == k_skaterift_replay )
-      return;
-
-   static vg_camera small_cam;      /* DOES NOT NEED TO BE STATIC BUT MINGW 
-                                    SAIS OTHERWISE */
-
-   m4x3_copy( g_render.cam.transform, small_cam.transform );
-
-   small_cam.fov = g_render.cam.fov;
-   small_cam.nearz = 0.05f;
-   small_cam.farz  = 60.0f;
-
-   vg_camera_update_view( &small_cam );
-   vg_camera_update_projection( &small_cam, vg.window_x, vg.window_y );
-   vg_camera_finalize( &small_cam );
-
-   /* Draw player to window buffer and blend background ontop */
-   player__render( &small_cam );
-}
-
-static void render_scene(void)
-{
-}
-
-static void skaterift_composite_maincamera(void)
-{
-   /* world entity driven camera 
-    * ------------------------------------------------------------------------------ */
-   if( _world.entity_set_camera )
-   {
-      _world.entity_set_camera = 0;
-      _world.entity_camera_modulate = vg_minf( 1.0f, _world.entity_camera_modulate+vg.time_frame_delta );
-   }
-   else
-   {
-      _world.entity_camera_modulate = vg_maxf( 0.0f, _world.entity_camera_modulate-vg.time_frame_delta );
-   }
-   
-   vg_camera_lerp( &localplayer.cam, &_world.entity_driven_camera,
-                   vg_smoothstepf(_world.entity_camera_modulate), &g_render.cam );
-
-   /* replay camera 
-    * ------------------------------------------------------------------ */
-   if( skaterift.activity == k_skaterift_replay )
-   {
-      _replay2_get_camera( &g_render.cam );
-   }
-
-   if( skaterift.activity == k_skaterift_spectate )
-   {
-      _network_get_spectate_cam( &g_render.cam );
-   }
-
-   g_render.cam.nearz = 0.1f;
-   g_render.cam.farz  = 2100.0f;
-
-   /* menu override camera 
-    * -------------------------------------------------------------------- */
-   if( (skaterift.activity == k_skaterift_menu) && menu.bg_cam )
-   {
-      ent_camera_unpack( menu.bg_cam, &g_render.cam );
-   }
-
-   /* cutscene camera TODO: Fix the action camera 
-    * ---------------------------------------------------------------- */
-   ent_camera *cs_cam = _cutscene_active_camera();
-   if( cs_cam )
-      ent_camera_unpack( cs_cam, &g_render.cam );
-
-   world_map_get_transition_cam( &g_render.cam );
-
-   vg_camera_update_transform( &g_render.cam );
-
-   vg_camera_update_view( &g_render.cam );
-   vg_camera_update_projection( &g_render.cam, vg.window_x, vg.window_y );
-   vg_camera_finalize( &g_render.cam );
-}
-
-static void render_main_game(void)
-{
-   if( (_cutscene.state >= k_cutscene_state_ready) && _cutscene.player_binding )
-   {
-      struct cs_instance *inst = _cutscene.player_binding;
-      struct skeleton *sk = &localplayer.skeleton;
-      for( u32 i=0; i<sk->bone_count; i ++ )
-         m4x3_copy( inst->skinning_data[i], localplayer.final_mtx[i] );
-   }
-   else if( skaterift.activity == k_skaterift_replay ){}
-   else
-   {
-      player__animate();
-      _replay2_record_local_frame();
-   }
-
-   animate_remote_players();
-   player__pre_render();
-
-   skaterift_composite_maincamera();
-
-   bool render_actual_game = !menu_viewing_map();
-   bool render_stenciled = 0;
-
-   if( render_actual_game )
-   {
-      world_instance *world = &_world.main;
-      render_world_cubemaps( world );
-   }
-
-   /* variable res target */
-   vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
-   glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
-   glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
-
-   if( !render_actual_game )
-   {
-      render_world_map();
-
-      if( world_map_get_transition_cam(NULL) )
-      {
-         glEnable( GL_STENCIL_TEST );
-         glDisable( GL_DEPTH_TEST );
-         glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
-         glStencilFunc( GL_ALWAYS, 1, 0xFF );
-         glStencilMask( 0xFF );
-         
-         shader_blit_transition_use();
-         shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
-         shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
-         render_fsquad();
-         render_stenciled = 1;
-         render_actual_game = 1;
-      }
-   }
-
-   if( render_actual_game )
-   {
-      /* Draw world */
-      glEnable( GL_DEPTH_TEST );
-      world_prerender( &_world.main );
-
-      render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1, _vg_render.fb_main );
-
-      particle_system_update( &particles_grind, vg.time_delta );
-      //particle_system_debug( &particles_grind );
-      particle_system_prerender( &particles_grind );
-      particle_system_render( &particles_grind, &g_render.cam );
-      
-      ent_tornado_pre_update();
-      particle_system_update( &particles_env, vg.time_delta );
-      particle_system_prerender( &particles_env );
-      particle_system_render( &particles_env, &g_render.cam );
-
-      player_glide_render_effects( &g_render.cam );
-   }
-
-   glEnable( GL_DEPTH_TEST );
-
-   /* full res target */
-   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
-
-   if( render_actual_game && !render_stenciled )
-   {
-      render_player_transparent(); /* needs to read the depth buffer before we fuck
-                                      it up with the oblique rendering inside the
-                                      portals */
-
-      /* continue with variable rate */
-      vg_framebuffer_bind( _vg_render.fb_main, _vg_render.scale );
-      render_world_gates( &_world.main, &g_render.cam, _vg_render.fb_main );
-   }
-
-   /* composite */
-   if( (skaterift.activity == k_skaterift_menu) && menu.bg_blur )
-      v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, g_render.blur_override );
-   else 
-      v2_zero( g_render.blur_override );
-
-   vg_postprocess_to_screen( _vg_render.fb_main );
-   cutscene_render_fadeout();
-
-   if( gui.helper_count == 0 )
-      control_overlay_render();
-}
-
-void vg_render(void)
-{
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-   {
-      vg_loader_render();
-      return;
-   }
-
-   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-
-   glViewport( 0,0, vg.window_x, vg.window_y );
-   glDisable( GL_DEPTH_TEST );
-   glDisable( GL_BLEND );
-
-   glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
-   glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
-
-   render_main_game();
-   m4x4_copy( g_render.cam.mtx.pv, vg.pv );
-   
-   /* Other shite */
-   glDisable(GL_BLEND);
-   glDisable(GL_DEPTH_TEST);
-   vg_lines_drawall();
-   glViewport( 0,0, vg.window_x, vg.window_y );
-
-   gui_render_icons();
-
-   compass_render_texture();
-}
-
-void vg_gui( ui_context *ctx )
-{
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-      return;
-
-   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
-
-   gui_draw( ctx );
-   compass_render_imgui( ctx );
-
-   if( k_light_editor )
-      imgui_world_light_edit( ctx, &_world.main );
-   
-   vg_ui.tex_bg = _vg_render.fb_main->attachments[0].id;
-   vg_framebuffer_inverse_ratio( _vg_render.fb_main, vg_ui.bg_inverse_ratio );
-
-   _cutscene_gui( ctx );
-   _board_maker_ui( ctx );
-   menu_gui( ctx );
-   player__im_gui( ctx );
-   world_instance *world = &_world.main;
-
-   if( skaterift.activity != k_skaterift_replay )
-   {
-      world_routes_imgui( ctx, world );
-      _ent_route_imgui( ctx );
-   }
-   _replay2_imgui( ctx );
-   workshop_form_gui( ctx );
-   world_gui( ctx, world );
-
-   if( menu_viewing_map() )
-   {
-      remote_players_imgui_world( ctx, &_world.main, vg.pv, 2000.0f, 0 );
-      //remote_players_imgui_lobby( ctx );
-   }
-   else 
-   {
-      remote_players_chat_imgui( ctx ); /* TODO: conditional */
-      remote_players_imgui_world( ctx, &_world.main, vg.pv, 100.0f, 1 );
-   }
-}
-
-void vg_framebuffer_resize( int w, int h )
-{
-}
-
-#include "vg/vg_ui/filebrowser.c"
-#include "addon.c"
-#include "addon_types.c"
-#include "audio.c"
-#include "ent_challenge.c"
-#include "ent_glider.c"
-#include "entity.c"
-#include "ent_objective.c"
-#include "ent_region.c"
-#include "ent_relay.c"
-#include "ent_route.c"
-#include "ent_skateshop.c"
-#include "ent_tornado.c"
-#include "ent_traffic.c"
-#include "ent_prop.c"
-#include "ent_script.c"
-#include "freecam.c"
-#include "menu.c"
-#include "network.c"
-#include "particle.c"
-#include "player_basic_info.c"
-#include "player.c"
-#include "player_common.c"
-#include "player_dead.c"
-#include "player_effects.c"
-#include "player_glide.c"
-#include "player_ragdoll.c"
-#include "player_remote.c"
-#include "player_render.c"
-#include "player_skate.c"
-#include "player_walk.c"
-#include "render.c"
-#include "save.c"
-#include "scene.c"
-#include "trail.c"
-#include "workshop.c"
-#include "world_audio.c"
-#include "world.c"
-#include "world_entity.c"
-#include "world_gate.c"
-#include "world_gen.c"
-#include "world_load.c"
-#include "world_map.c"
-#include "world_physics.c"
-#include "world_render.c"
-#include "world_routes.c"
-#include "world_routes_ui.c"
-#include "world_sfd.c"
-#include "world_volumes.c"
-#include "world_water.c"
-#include "array_file.c"
-#include "model.c"
-#include "metascene.c"
-#include "control_overlay.c"
-#include "ent_camera.c"
-#include "skaterift_script.c"
-#include "board_maker.c"
-#include "compass.c"
-#include "replay2.c"
-#include "user_profile.c"
-#include "ent_npc.c"
-#include "ent_list.c"
-#include "ent_cutscene.c"
-#include "ent_atom.c"
-
-static void _handle_vg_signal( vg_signal_id id, bool state )
-{
-   if( (id == vg.sig_engine) && state )
-   {
-      //vg_audio.always_keep_compressed = 1;
-      co_run( game_load_co, NULL );
-   }
-}
-
-int main( int argc, const char *argv[] )
-{
-   vg_init( argc, argv, "Voyager Game Engine" );
-   vg_stack_init( &vg.rtmem, NULL, VG_MB(200), "RT Memory" );
-   vg_stack_set_flags( &vg.rtmem, VG_STACK_ALLOCATOR_METADATA );
-   vg_stack_init( &vg.scratch, NULL, VG_MB(10), "Scratch" );
-
-   network_set_host( "skaterift.com", NULL );
-
-   {
-      const char *arg;
-      if( vg_long_opt( "noauth", "Disable server authentication" ) )
-         network_client.auth_mode = eServerModeNoAuthentication;
-
-      if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
-         network_set_host( arg, NULL );
-
-      if( vg_long_opt( "demo", "Turn demo mode on" ) )
-         g_client.demo_mode = 2;
-
-      if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
-         skaterift.override_load_world = arg;
-   }
-
-   skaterift.sig_world = _vg_tower_create_signal( "World Loaded" );
-   skaterift.full_ready_mask = _vg_tower_mask( skaterift.sig_world ) | 
-                               _vg_tower_mask( vg.sig_engine ) | 
-                               _vg_tower_mask( vg.sig_client );
-   _vg_tower_register_trigger( _vg_tower_mask( vg.sig_engine ), _handle_vg_signal );
-
-   vg_console_reg_cmd( "quit", skaterift_quit_command, NULL );
-   vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
-   vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
-   vg_console_reg_var( "allow_resume", &skaterift.allow_replay_resume, k_var_dtype_i32, VG_VAR_CHEAT );
-   vg_console_reg_var( "boost_scale", &skaterift.boost_scale, k_var_dtype_f32, VG_VAR_CHEAT );
-
-   /* TODO Modules that do this automatically.... */
-   render_register();
-   remote_players_register();
-   network_register();
-   menu_register();
-   control_overlay_register();
-   world_render_register();
-   gui_register();
-   compass_register();
-   player_register();
-   player_ragdoll_register();
-   cutscene_register();
-   workshop_register();
-   ent_tornado_register();
-   _replay2_register();
-   _ent_atom_register();
-   _ent_challenge_register();
-
-   _steam_api.demo_mode = g_client.demo_mode; // FIXME Fuck you
-   _steam_api.cb_connection_changed = cb_skaterift_connection_changed;
-   _steam_api.cb_persona_changed = cb_skaterift_persona_changed;
-
-   vg_run();
-   return 0;
-}
diff --git a/src/skaterift.h b/src/skaterift.h
deleted file mode 100644 (file)
index ed5ee37..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-#define SKATERIFT
-#define SKATERIFT_APPID 2103940
-
-#define SKATERIFT_WORLD_READY 0x10000
-
-#include "vg/vg_engine.h"
-#include "vg/vg_camera.h"
-
-enum skaterift_rt 
-{
-   k_skaterift_rt_workshop_preview,
-   k_skaterift_rt_server_status,
-   k_skaterift_rt_max
-};
-
-struct skaterift_globals
-{
-   f32 time_rate;
-   
-   enum skaterift_activity {
-      k_skaterift_default    = 0x00,  /* regular playing */
-      k_skaterift_replay     = 0x01,
-      k_skaterift_spectate   = 0x02,
-      k_skaterift_menu       = 0x04,
-      k_skaterift_activity_max = 0x8
-   }
-   activity;
-
-   GLuint rt_textures[k_skaterift_rt_max];
-
-   u32 achievements;
-   i32 allow_replay_resume;
-   vg_signal_id sig_world;
-   u64 full_ready_mask;
-
-   const char *override_load_world;
-
-   f32 boost_scale;
-   bool no_save_location;
-}
-extern skaterift;
diff --git a/src/skaterift.hconf b/src/skaterift.hconf
new file mode 100644 (file)
index 0000000..902d157
--- /dev/null
@@ -0,0 +1,121 @@
+#if defined( _WIN32 )
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#else
+ #include <sys/socket.h>
+ #include <sys/types.h>
+ #include <netdb.h>
+#endif
+
+/* Core system level ------------------------------------------------------------------------------------------------ */
+
+#if defined( SR_ALL )
+# include "addon_types.h"
+# include "addon.h"
+#endif
+
+#if defined( SR_MODEL ) || defined( SR_ALL )
+# include "array_file.h"
+# include "shader_props.h"
+# include "model.h"
+#endif
+
+#if defined( SR_ALL )
+/* TODO: entity needs to be split -> model.h + some kind of helper logic file */
+# include "entity.h"
+
+# include "client.h"
+# include "demo_check.h"
+
+/* graphics */
+# include "render.h"
+# include "depth_compare.h"
+# include "particle.h"
+# include "trail.h"
+# include "font.h"
+# include "scene.h"
+# include "scene_rigidbody.h"
+# include "metascene.h"
+
+# include "atom.h"
+# include "audio.h"
+# include "compass.h"
+# include "control_overlay.h"
+# include "input.h"
+# include "cutscene.h"
+# include "gui.h"
+
+# include "network_msg.h"
+# include "network_common.h"
+# include "network.h"
+# include "network_compression.h"
+# include "network_requests.h"
+
+# include "replay2.h"
+# include "save2.h"
+# include "user_profile.h"
+
+/* World level ------------------------------------------------------------------------------------------------------ */
+# include "world.h"
+# include "world_audio.h"
+# include "world_entity.h"
+# include "world_gate.h"
+# include "world_gen.h"
+# include "world_info.h"
+# include "world_load.h"
+# include "world_map.h"
+# include "world_physics.h"
+# include "world_render.h"
+# include "world_routes.h"
+# include "world_routes_ui.h"
+# include "world_sfd.h"
+# include "world_volumes.h"
+# include "world_water.h"
+
+# include "ent_atom.h"
+# include "ent_camera.h"
+# include "ent_challenge.h"
+# include "ent_cutscene.h"
+# include "ent_glider.h"
+# include "ent_list.h"
+# include "ent_npc.h"
+# include "ent_objective.h"
+# include "ent_prop.h"
+# include "ent_region.h"
+# include "ent_relay.h"
+# include "ent_route.h"
+# include "ent_script.h"
+# include "ent_skateshop.h"
+# include "ent_tornado.h"
+# include "ent_traffic.h"
+
+# include "board_maker.h"
+
+/* Player lavel ----------------------------------------------------------------------------------------------------- */
+# include "player_api.h"
+# include "player_basic_info.h"
+# include "player_common.h"
+# include "player_render.h"
+# include "player_effects.h"
+
+# include "player_dead.h"
+# include "player_glide.h"
+# include "player_ragdoll.h"
+# include "player_skate.h"
+# include "player_walk.h"
+
+# include "player.h"
+# include "player_remote.h"
+
+# include "menu.h"
+# include "workshop.h"
+#endif
+
+#if defined( SR_GAMESERVER )
+# include "gameserver.h"
+# include "gameserver_database.h"
+# include "gameserver_db.h"
+# include "gameserver_monitor.h"
+# include "gameserver_replay.h"
+# include "gameserver_requests.h"
+#endif
diff --git a/src/skaterift_script.c b/src/skaterift_script.c
deleted file mode 100644 (file)
index 4b22e1c..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-#if 0
-
-#include "ent_script.h"
-
-const char *_script_linear_story[] = 
-{
-   "start",
-   "volc",
-   "volc:tutorial",
-   "volc:leaving",
-
-   "mz",
-   /* NOTES: we need to block the player in to force them to talk to mike so they don't get lost? Or at least put 
-    *        mike right in the way of where you gotta go. Perhaps on the docks.
-    */
-
-   "mz:town_region",
-   "mz:battery_jump",
-   "mz:leaving_pt1",
-   "mz:start_pt2",
-   "mz:megapark_region",
-   "mz:leaving_pt2",
-
-   "city",
-   "city:main_region",
-   "city:finale",
-   "city:leaving",
-
-   "valley",
-   "valley:main_region",
-   "valley:rocket_inspection",
-   "valley:cave",
-   "valley:finale",
-   "valley:leaving",
-
-   NULL
-};
-
-struct script_save_atom
-{
-   const char *alias;
-
-   enum save_atom_type
-   {
-      k_atom_type_numeric,
-      k_atom_type_enum
-   }
-   type;
-   
-   const char **enum_values;
-   u64 status;
-}
-_skaterift_script_savedata[] = 
-{
-   { "story", k_atom_type_enum, _script_linear_story },
-   { "unlock_docks_view" },
-
-   { "unlock_valley_view" },
-   { "unlock_mtzero_view" },
-   { "unlock_city_view" },
-
-   { "board_maker_unlock" },
-   { "board_maker_hub_view" },
-
-   { "ch1s3_view" },
-   { "ch1s3b_view" },
-   { "ch1s4_view" },
-   { "ch1s5_view" },
-
-#if 0
-   { "board_maker_unlock" },
-   { "board_maker_hub_view" },
-   { "intro_view" },
-   { "hub_info_view" },
-
-   { "ch1s2_view" },
-   { "ch1s3_view" },
-   { "ch1s3b_view" },
-   { "ch1s4_view" },
-   { "ch1s5_view" },
-   { "ch1s6a_view" },
-   { "unlock_docks_view" },
-
-   { "unlock_mtzero" },
-   { "ch2s1_view" },
-   { "ch2s2_view" },
-   { "ch2s3_view" },
-   { "battery_jump_view" },
-   { "ch2s4_view" },
-   { "ch2s5_view" },  /* is the trigger for the second map */
-   { "ch2s6_view" },
-   { "ch2e1_view" },
-
-   { "unlock_city" },
-   { "unlock_city_view" },
-   { "ch3s1_view" },
-   { "ch3s2_view" },
-   { "ch3s3_view" },
-   { "city_finale" },
-
-   { "unlock_valley" },
-
-   { "valley_progress" },
-
-   { "ch4s1a_view" },
-   { "ch4s2_view" },
-   { "valley_cave" },
-   { "ch4s1_view" },
-   { "valley_finale" },
-   { "ch4s3_view" },
-   { "rocket_launch_view" },
-
-   { "unlock_venus" },
-#endif
-};
-
-struct script_save_atom *_skaterift_get_atom( const char *alias )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_atom *atom = &_skaterift_script_savedata[i];
-      if( !strcmp( alias, atom->alias ) )
-         return atom;
-   }
-   return NULL;
-}
-
-u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value )
-{
-   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
-   if( !atom )
-   {
-      vg_error( "No atom aliased '%s'\n", atom_alias );
-      return 0;
-   }
-
-   VG_ASSERT( atom->type == k_atom_type_enum );
-   if( value )
-   {
-      for( u32 i=0; i<32; i ++ )
-      {
-         if( !atom->enum_values[i] )
-         {
-            vg_warn( "Atom '%s' does't contain the value '%s'\n", atom->alias, value );
-            return fallback_value;
-         }
-         if( !strcmp( atom->enum_values[i], value ) )
-            return i;
-      }
-      vg_warn( "Atom '%s' exceeds max enum values (%u)\n", atom->alias, 32 );
-   }
-   return fallback_value;
-}
-
-u64 _skaterift_atom_status( const char *atom_alias )
-{
-   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
-   if( !atom )
-   {
-      vg_error( "No atom aliased '%s'\n", atom_alias );
-      return 0;
-   }
-   else return atom->status;
-}
-
-void _skaterift_atom_set( const char *atom_alias, u64 value )
-{
-   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
-   if( !atom )
-   {
-      vg_error( "No atom aliased '%s'\n", atom_alias );
-      return;
-   }
-
-   atom->status = value;
-
-#if 0
-   struct script_event_atom_changed info;
-   info.alias = atom_alias;
-   info.value = value;
-   struct ent_script_event event;
-   event.type = k_escript_event_atom_changed;
-   event.info = &info;
-   ent_script_propogate_event( &_world.main, &event );
-#endif
-}
-
-void _skaterift_atom_set_enum( const char *atom_alias, const char *value )
-{
-   _skaterift_atom_set( atom_alias, _skaterift_atom_enum_index( atom_alias, value, 0 ) );
-}
-
-void _skaterift_script_write_savedata( vg_msg *sav )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_atom *atom = &_skaterift_script_savedata[i];
-      if( atom->type == k_atom_type_numeric )
-         vg_msg_wkvnum( sav, atom->alias, k_vg_msg_u64, 1, &atom->status );
-      else
-         vg_msg_wkvstr( sav, atom->alias, atom->enum_values[ atom->status ] );
-   }
-}
-
-void _skaterift_script_load_savedata( vg_msg *sav )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_atom *atom = &_skaterift_script_savedata[i];
-      if( atom->type == k_atom_type_numeric )
-         vg_msg_getkvintg( sav, atom->alias, k_vg_msg_u64, &atom->status, NULL );
-      else
-         atom->status = _skaterift_atom_enum_index( atom->alias, vg_msg_getkvstr( sav, atom->alias ), 0 );
-   }
-}
-
-/* script events 
- * ------------------------------------------------------------------------------------------------------------- */
-
-bool on_cutscene_marker( ent_script_event *event, const char *marker )
-{
-   if( event->type != k_escript_event_allocate )
-   {
-      if( _cutscene.state == k_cutscene_state_playing )
-      {
-         if( _cutscene.marker_this_frame )
-         {
-            if( vg_str_eq( marker, _cutscene.marker_this_frame ) )
-               return 1;
-         }
-      }
-   }
-   return 0;
-}
-
-bool on_world_start( ent_script_event *event )
-{
-   return event->type == k_escript_event_world_start;
-}
-
-bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value )
-{
-   if( event->type == k_escript_event_atom_changed )
-   {
-      struct script_event_atom_changed *atom_info = event->info;
-      if( !strcmp( atom_alias, atom_info->alias ) )
-      {
-         *out_value = atom_info->value;
-         return 1;
-      }
-   }
-   else if( event->type == k_escript_event_world_start )
-   {
-      *out_value = _skaterift_atom_status( atom_alias );
-      return 1;
-   }
-
-   return 0;
-}
-
-#if 0
-bool on_function_trigger( ent_script_event *event, i32 function_id )
-{
-   if( event->type == k_escript_event_call )
-   {
-      struct script_event_call *call_info = event->info;
-      if( call_info->function_id == function_id )
-         return 1;
-   }
-
-   return 0;
-}
-
-bool on_atom_once( ent_script_event *event, const char *atom_alias )
-{
-   if( event->type != k_escript_event_allocate )
-   {
-      if( _skaterift_atom_status( atom_alias ) != 1 )
-      {
-         _skaterift_atom_set( atom_alias, 1 );
-         return 1;
-      }
-   }
-
-   return 0;
-}
-#endif
-
-#include "scripts/generic.c"
-#include "scripts/blocker_break.c"
-
-#include "scripts/heaven.c"
-#include "scripts/hub.c"
-#include "scripts/tutorial_island.c"
-#include "scripts/mtzero.c"
-#include "scripts/city.c"
-#include "scripts/valley.c"
-
-#include "scripts/cutscene.c"
-#include "scripts/explode.c"
-
-/* console eventts
- * ------------------------------------------------------------------------------------------------------------- */
-
-static int _skaterift_script_ccmd( int argc, const char *argv[] )
-{
-   if( argc < 2 ) 
-   {
-      vg_error( "Usage: script <command> <data name> <optional set-value>\n" );
-      return 0;
-   }
-
-   bool all = 0;
-   if( !strcmp( argv[1], "all" ) ) 
-      all = 1;
-
-   world_instance *world = &_world.main;
-
-   if( !strcmp( argv[0], "atom" ) ) 
-   {
-      for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-      {
-         struct script_save_atom *atom = &_skaterift_script_savedata[i];
-         if( all || !strcmp( argv[1], atom->alias ) )
-         {
-            if( argc==3 ) 
-            {
-               u64 value = 0;
-               if( atom->type == k_atom_type_numeric )
-                  value = atol(argv[2]);
-               else
-                  value = _skaterift_atom_enum_index( atom->alias, argv[2], atom->status );
-               _skaterift_atom_set( atom->alias, value );
-            }
-            else 
-            {
-               if( atom->type == k_atom_type_numeric )
-                  vg_info( "%s: %lu\n", atom->alias, atom->status );
-               else
-                  vg_info( "%s: '%s' (%lu)\n", atom->alias, atom->enum_values[ atom->status ], atom->status );
-            }
-         }
-      }
-
-      return 1;
-   }
-   else if( !strcmp( argv[0], "challenge" ) )
-   {
-      u32 index = 0;
-      for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
-      {
-         ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-         const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
-         
-         if( all || (atoi( argv[1] ) == index) )
-         {
-            if( argc==3 )
-            {
-               challenge->status = atoi( argv[2] );
-               ent_region_re_eval( world );
-               
-               struct ent_script_event event;
-               struct script_event_completion_changed inf = {
-                  .entity_id = mdl_entity_id( k_ent_challenge, i ),
-                  .completion_flags = 0
-               };
-               event.type = k_escript_event_completion_changed;
-               event.info = &inf;
-               ent_script_propogate_event( world, &event );
-            }
-            else
-               vg_info( "[challenge %u '%s'] %u\n", index, alias, challenge->status );
-         }
-
-         index ++;
-      }
-      for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
-      {
-         ent_route *route = af_arritm( &world->ent_route, i );
-         const char *alias = af_str( &world->meta.af, route->pstr_name );
-
-         if( all || (atoi( argv[1] ) == index) )
-         {
-            if( argc==3 )
-            {
-               route->flags &= ~((u32)(k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver));
-
-               if( !strcmp( argv[2], "silver" ) )
-                  route->flags |= (u32)(k_ent_route_flag_achieve_silver);
-
-               if( !strcmp( argv[2], "gold" ) )
-                  route->flags |= (u32)(k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver);
-               ent_region_re_eval( world );
-
-               struct ent_script_event event;
-               struct script_event_completion_changed inf = {
-                  .entity_id = mdl_entity_id( k_ent_route, i ),
-                  .completion_flags = route->flags
-               };
-               event.type = k_escript_event_completion_changed;
-               event.info = &inf;
-               ent_script_propogate_event( world, &event );
-            }
-            else
-               vg_info( "[route %u '%s'] %s%s\n", index, alias,
-                           (route->flags & k_ent_route_flag_achieve_silver? "SILVER": "_____"),
-                           (route->flags & k_ent_route_flag_achieve_gold?   "_GOLD": "_____" ) );
-         }
-
-         index ++;
-      }
-      return 1;
-   }
-   else if( !strcmp( argv[0], "trigger" ) )
-   {
-      if( !strcmp( argv[1], "start" ) )
-      {
-         ent_script_start( &_world.main );
-         return 1;
-      }
-      else
-      {
-         vg_error( "Dont know event '%s'.\n", argv[1] );
-         return 0;
-      }
-   }
-   else                                   
-   {
-      vg_error( "'%s' is not a command\n", argv[0] );
-      return 0;
-   }
-}
-
-static void _skaterift_script_ccmd_poll( int argc, const char *argv[] )
-{
-   const char *term = argv[argc-1];
-   world_instance *world = &_world.main;
-
-   if( argc == 1 )
-   {
-      console_suggest_score_text( "atom", term, 0 );
-      console_suggest_score_text( "trigger", term, 0 );
-      console_suggest_score_text( "challenge", term, 0 );
-   }
-   else if( argc == 2 )
-   {
-      if( !strcmp( argv[0], "atom" ) )
-      {
-         console_suggest_score_text( "all", term, 0 );
-         for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-         {
-            struct script_save_atom *atom = &_skaterift_script_savedata[i];
-            console_suggest_score_text( atom->alias, term, 0 );
-         }
-      }
-      else if( !strcmp( argv[0], "trigger" ) )
-      {
-         console_suggest_score_text( "start", term, 0 );
-      }
-      else if( !strcmp( argv[0], "challenge" ) )
-      {
-         // CANT DO THIS WHILE WE DONT HAVE STRING ESCAPING IN THE CONSOLE
-#if 0
-         for( u32 i=0; i<af_arrcount( &world->ent_challenge ); i ++ )
-         {
-            ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-            console_suggest_score_text( af_str( &world->meta.af, challenge->pstr_alias ), term, 0 );
-         }
-         for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
-         {
-            ent_route *route = af_arritm( &world->ent_route, i );
-            console_suggest_score_text( af_str( &world->meta.af, route->pstr_name ), term, 0 );
-         }
-#endif
-      }
-   }
-   else if( argc == 3 )
-   {
-      if( !strcmp( argv[0], "atom" ) )
-      {
-         if( strcmp( argv[1], "all" ) )
-         {
-            struct script_save_atom *atom = _skaterift_get_atom( argv[1] );
-            if( atom->type == k_atom_type_enum )
-            {
-               for( u32 i=0; i<32; i ++ )
-               {
-                  if( !atom->enum_values[i] )
-                     break;
-                  console_suggest_score_text( atom->enum_values[i], term, 0 );
-               }
-            }
-         }
-      }
-      else if( !strcmp( argv[0], "challenge" ) )
-      {
-         // CANT DO THIS WHILE WE DONT HAVE STRING ESCAPING IN THE CONSOLE
-#if 0
-         for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
-         {
-            ent_route *route = af_arritm( &world->ent_route, i );
-            const char *alias = af_str( &world->meta.af, route->pstr_name );
-            if( !strcmp( argv[1], alias ) )
-            {
-               console_suggest_score_text( "silver", term, 0 );
-               console_suggest_score_text( "gold", term, 0 );
-               break;
-            }
-         }
-#endif
-      }
-   }
-}
-
-void _skaterift_script_init(void)
-{
-   vg_console_reg_cmd( "script", _skaterift_script_ccmd, _skaterift_script_ccmd_poll );
-}
-
-
-#endif
diff --git a/src/skaterift_script.h b/src/skaterift_script.h
deleted file mode 100644 (file)
index e4332d1..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-#if 0
-#include "ent_script.h"
-#define ATOM_MAX 0xfffffffffffffffflu
-
-void _skaterift_script_init(void);
-void _skaterift_script_write_savedata( vg_msg *sav );
-void _skaterift_script_load_savedata( vg_msg *sav );
-
-u64 _skaterift_atom_status( const char *atom_alias );
-u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value );
-void _skaterift_atom_set( const char *atom_alias, u64 value );
-void _skaterift_atom_set_enum( const char *atom_alias, const char *value );
-
-bool on_world_start( ent_script_event *event );
-bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value );
-bool on_cutscene_marker( ent_script_event *event, const char *marker );
-bool on_function_trigger( ent_script_event *event, i32 function_id );
-bool on_atom_once( ent_script_event *event, const char *atom_alias );
-bool on_advancement( ent_script_event *event );
-#endif
diff --git a/src/skeleton.h b/src/skeleton.h
deleted file mode 100644 (file)
index 87780af..0000000
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "vg/vg_lines.h"
-#include "model.h"
-#include "metascene.h"
-
-struct skeleton
-{
-   struct skeleton_bone
-   {
-      v3f co, end;
-      u32 parent;
-
-      u32 flags;
-      int defer;
-
-      //ms_keyframe kf;
-      mdl_bone *orig_bone;
-
-      u32 collider;
-      boxf hitbox;
-      const char *name;
-   }
-   *bones;
-   u32 bone_count;
-
-   struct skeleton_ik
-   {
-      u32 lower, upper, target, pole;
-      m3x3f ia, ib;
-   }
-   *ik;
-   u32 ik_count;
-
-   u32 collider_count,
-       bindable_count;
-};
-
-typedef struct skeleton_anim skeleton_anim;
-struct skeleton_anim 
-{
-   ms_strip *strip;
-   ms_keyframe *keyframes_base;
-   f32 framerate;
-};
-
-static u32 skeleton_bone_id( struct skeleton *skele, const char *name )
-{
-   for( u32 i=1; i<skele->bone_count; i++ )
-      if( !strcmp( skele->bones[i].name, name ))
-         return i;
-
-   vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
-   vg_fatal_error( "Bone does not exist\n" );
-
-   return 0;
-}
-
-static void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num )
-{
-   for( int i=0; i<num; i++ )
-      kfb[i] = kfa[i];
-}
-
-
-/* apply a rotation from the perspective of root */
-static void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q )
-{
-   v3f v0, co;
-   v3_add( kf->co, offset, co );
-   v3_sub( co, origin, v0 );
-   q_mulv( q, v0, v0 );
-   v3_add( v0, origin, co );
-   v3_sub( co, offset, kf->co );
-
-   q_mul( q, kf->q, kf->q );
-   q_normalize( kf->q );
-}
-
-static void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd )
-{
-   v3_lerp( kfa->co, kfb->co, t, kfd->co );
-   q_nlerp( kfa->q,  kfb->q,  t, kfd->q );
-   v3_lerp( kfa->s,  kfb->s,  t, kfd->s );
-}
-
-/*
- * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
- */
-static void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count )
-{
-   if( t <= 0.0001f )
-   {
-      keyframe_copy_pose( kfa, kfd, count );
-      return;
-   }
-   else if( t >= 0.9999f )
-   {
-      keyframe_copy_pose( kfb, kfd, count );
-      return;
-   }
-
-   for( int i=0; i<count; i++ )
-      keyframe_lerp( kfa+i, kfb+i, t, kfd+i );
-}
-
-static void skeleton_lerp_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd )
-{
-   keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
-}
-
-static void skeleton_copy_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd )
-{
-   keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
-}
-
-/*
- * Sample animation between 2 closest frames using time value. Output is a
- * keyframe buffer that is allocated with an appropriate size
- *
- * Time is in SECONDS
- */
-void skeleton_sample_anim( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
-{
-   ms_strip *strip = anim->strip;
-   f32 animtime  = fmodf( time*anim->framerate, (f32)strip->strip.length ),
-       animframe = floorf( animtime ),
-       t = animtime - animframe;
-
-   u32 frame = (u32)animframe % strip->strip.length,
-       next  = (frame+1) % strip->strip.length;
-
-   ms_keyframe *base  = anim->keyframes_base + strip->strip.count*frame,
-               *nbase = anim->keyframes_base + strip->strip.count*next;
-
-   skeleton_lerp_pose( skele, base, nbase, t, output );
-}
-
-/* time is in SECONDS */
-int skeleton_sample_anim_clamped( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
-{
-   ms_strip *strip = anim->strip;
-   f32 end = (strip->strip.length-1)/anim->framerate;
-   skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
-
-   if( time > end ) return 0;
-   else             return 1;
-}
-
-typedef enum anim_apply
-{
-   k_anim_apply_always,
-   k_anim_apply_defer_ik,
-   k_anim_apply_deffered_only,
-   k_anim_apply_absolute
-}
-anim_apply;
-
-static int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
-{
-   struct skeleton_bone *sb = &skele->bones[ id ],
-                        *sp = &skele->bones[ sb->parent ];
-
-   if( type == k_anim_apply_defer_ik )
-   {
-      if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer )
-      {
-         sb->defer = 1;
-         return 0;
-      }
-      else
-      {
-         sb->defer = 0;
-         return 1;
-      }
-   }
-   else if( type == k_anim_apply_deffered_only )
-   {
-      if( sb->defer )
-         return 1;
-      else
-         return 0;
-   }
-
-   return 1;
-}
-
-/*
- * Apply block of keyframes to skeletons final pose
- */
-static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx )
-{
-   if( passtype == k_anim_apply_absolute )
-   {
-      for( u32 i=1; i<skele->bone_count; i++ )
-      {
-         ms_keyframe *kf = &pose[i-1];
-
-         v3f *posemtx = final_mtx[i];
-
-         q_m3x3( kf->q, posemtx );
-         m3x3_scale( posemtx, kf->s );
-         v3_copy( kf->co, posemtx[3] );
-      }
-      return;
-   }
-
-   m4x3_identity( final_mtx[0] );
-   skele->bones[0].defer = 0;
-   skele->bones[0].flags &= ~k_bone_flag_ik;
-
-   for( u32 i=1; i<skele->bone_count; i++ )
-   {
-      struct skeleton_bone *sb = &skele->bones[i],
-                           *sp = &skele->bones[sb->parent];
-      if( !should_apply_bone( skele, i, passtype ) )
-         continue;
-
-      sb->defer = 0;
-
-      /* process pose */
-      m4x3f posemtx;
-
-      v3f temp_delta;
-      v3_sub( skele->bones[i].co, skele->bones[sb->parent].co, temp_delta );
-
-      /* pose matrix */
-      ms_keyframe *kf = &pose[i-1];
-      q_m3x3( kf->q, posemtx );
-      m3x3_scale( posemtx, kf->s );
-      v3_copy( kf->co, posemtx[3] );
-      v3_add( temp_delta, posemtx[3], posemtx[3] );
-
-      /* final matrix */
-      m4x3_mul( final_mtx[ sb->parent ], posemtx, final_mtx[i] );
-   }
-}
-
-/* 
- * Take the final matrices and decompose it into an absolute positioned anim
- */
-static void skeleton_decompose_mtx_absolute( struct skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx )
-{
-   for( u32 i=1; i<skele->bone_count; i++ )
-   {
-      struct skeleton_bone *sb = &skele->bones[i];
-      ms_keyframe *kf = &anim[i-1];
-      m4x3_decompose( final_mtx[i], kf->co, kf->q, kf->s );
-   }
-}
-
-/* 
- * creates the reference inverse matrix for an IK bone, as it has an initial 
- * intrisic rotation based on the direction that the IK is setup..
- */
-static void skeleton_inverse_for_ik( struct skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse )
-{
-   v3_copy( ivaxis, inverse[0] );
-   v3_copy( skele->bones[id].end, inverse[1] );
-   v3_normalize( inverse[1] );
-   v3_cross( inverse[0], inverse[1], inverse[2] );
-   m3x3_transpose( inverse, inverse );
-}
-
-/*
- * Creates inverse rotation matrices which the IK system uses.
- */
-static void skeleton_create_inverses( struct skeleton *skele )
-{
-   /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
-   for( u32 i=0; i<skele->ik_count; i++ )
-   {
-      struct skeleton_ik *ik = &skele->ik[i];
-      m4x3f inverse;
-      v3f iv0, iv1, ivaxis;
-      v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 );
-      v3_sub( skele->bones[ik->pole].co,   skele->bones[ik->lower].co, iv1 );
-      v3_cross( iv0, iv1, ivaxis );
-      v3_normalize( ivaxis );
-
-      skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
-      skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
-   }
-}
-
-/*
- * Apply a model matrix to all bones, should be done last
- */
-static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform, m4x3f *final_mtx )
-{
-   for( u32 i=0; i<skele->bone_count; i++ )
-   {
-      struct skeleton_bone *sb = &skele->bones[i];
-      m4x3_mul( transform, final_mtx[i], final_mtx[i] );
-   }
-}
-
-/*
- * Apply an inverse matrix to all bones which maps vertices from bind space into
- * bone relative positions
- */
-static void skeleton_apply_inverses( struct skeleton *skele, m4x3f *final_mtx )
-{
-   for( u32 i=0; i<skele->bone_count; i++ )
-   {
-      struct skeleton_bone *sb = &skele->bones[i];
-      m4x3f inverse;
-      m3x3_identity( inverse );
-      v3_negate( sb->co, inverse[3] );
-      m4x3_mul( final_mtx[i], inverse, final_mtx[i] );
-   }
-}
-
-/*
- * Apply all IK modifiers (2 bone ik reference from blender is supported)
- */
-static void skeleton_apply_ik_pass( struct skeleton *skele, m4x3f *final_mtx )
-{
-   for( u32 i=0; i<skele->ik_count; i++ )
-   {
-      struct skeleton_ik *ik = &skele->ik[i];
-      v3f v0, /* base -> target */
-          v1, /* base -> pole */
-          vaxis;
-
-      v3f co_base,
-          co_target,
-          co_pole;
-
-      v3_copy( final_mtx[ik->lower][3], co_base );
-      v3_copy( final_mtx[ik->target][3], co_target );
-      v3_copy( final_mtx[ik->pole][3], co_pole );
-
-      v3_sub( co_target, co_base, v0 );
-      v3_sub( co_pole, co_base, v1 );
-      v3_cross( v0, v1, vaxis );
-      v3_normalize( vaxis );
-      v3_normalize( v0 );
-      v3_cross( vaxis, v0, v1 );
-
-      /* localize problem into [x:v0,y:v1] 2d plane */
-      v2f base = { v3_dot( v0, co_base   ), v3_dot( v1, co_base   ) },
-          end  = { v3_dot( v0, co_target ), v3_dot( v1, co_target ) },
-          knee;
-
-      /* Compute angles (basic trig)*/
-      v2f delta;
-      v2_sub( end, base, delta );
-
-      f32 l1 = v3_length( skele->bones[ik->lower].end ),
-          l2 = v3_length( skele->bones[ik->upper].end ),
-          d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
-          c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
-          rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
-
-      knee[0] = sinf(-rot) * l1;
-      knee[1] = cosf(-rot) * l1;
-
-      m4x3_identity( final_mtx[ik->lower] );
-      m4x3_identity( final_mtx[ik->upper] );
-
-      /* create rotation matrix */
-      v3f co_knee;
-      v3_muladds( co_base, v0, knee[0], co_knee );
-      v3_muladds( co_knee, v1, knee[1], co_knee );
-      vg_line( co_base, co_knee, 0xff00ff00 );
-
-      m4x3f transform;
-      v3_copy( vaxis, transform[0] );
-      v3_muls( v0, knee[0], transform[1] );
-      v3_muladds( transform[1], v1, knee[1], transform[1] );
-      v3_normalize( transform[1] );
-      v3_cross( transform[0], transform[1], transform[2] );
-      v3_copy( co_base, transform[3] );
-
-      m3x3_mul( transform, ik->ia, transform );
-      m4x3_copy( transform, final_mtx[ik->lower] );
-
-      /* upper/knee bone */
-      v3_copy( vaxis, transform[0] );
-      v3_sub( co_target, co_knee, transform[1] );
-      v3_normalize( transform[1] );
-      v3_cross( transform[0], transform[1], transform[2] );
-      v3_copy( co_knee, transform[3] );
-
-      m3x3_mul( transform, ik->ib, transform );
-      m4x3_copy( transform, final_mtx[ik->upper] );
-   }
-}
-
-/*
- * Applies the typical operations that you want for an IK rig: 
- *    Pose, IK, Pose(deferred), Inverses, Transform
- */
-static void skeleton_apply_standard( struct skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx )
-{
-   skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik, final_mtx );
-   skeleton_apply_ik_pass( skele, final_mtx );
-   skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only, final_mtx );
-   skeleton_apply_inverses( skele, final_mtx );
-   skeleton_apply_transform( skele, transform, final_mtx );
-}
-
-static void skeleton_alloc_from( struct skeleton *skele, vg_stack_allocator *stack, mdl_context *mdl, mdl_armature *armature )
-{
-   skele->bone_count     = armature->bone_count+1;
-   skele->ik_count       = 0;
-   skele->collider_count = 0;
-
-   for( u32 i=0; i<armature->bone_count; i++ )
-   {
-      mdl_bone *bone = &mdl->bones[ armature->bone_start+i ];
-      if( bone->flags & k_bone_flag_ik )
-         skele->ik_count ++;
-      if( bone->collider )
-         skele->collider_count ++;
-   }
-
-   u32 bone_size = sizeof(struct skeleton_bone) * skele->bone_count,
-       ik_size   = sizeof(struct skeleton_ik)   * skele->ik_count;
-
-   skele->bones = vg_stack_allocate( stack, bone_size, 8, NULL );
-   skele->ik    = vg_stack_allocate( stack, ik_size, 8, NULL );
-
-   memset( skele->bones, 0, bone_size );
-   memset( skele->ik, 0, ik_size );
-}
-
-static void skeleton_fatal_err(void)
-{
-   vg_fatal_error( "Skeleton setup failed" );
-}
-
-/* Setup a skeleton from model. mdl's metadata should stick around */
-void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index, vg_stack_allocator *stack )
-{
-   u32 ik_count = 0, collider_count = 0;
-   skele->bone_count = 0;
-   skele->bones = NULL;
-
-   if( !mdl->armature_count )
-   {
-      vg_error( "No skeleton in model\n" );
-      skeleton_fatal_err();
-   }
-
-   mdl_armature *armature = &mdl->armatures[ index ];
-   skeleton_alloc_from( skele, stack, mdl, armature );
-
-   for( u32 i=0; i<armature->bone_count; i++ )
-   {
-      mdl_bone *bone = &mdl->bones[ armature->bone_start+i ];
-      struct skeleton_bone *sb = &skele->bones[i+1];
-
-      v3_copy( bone->co, sb->co );
-      v3_copy( bone->end, sb->end );
-
-      sb->parent = bone->parent;
-      sb->name   = af_str( &mdl->af, bone->pstr_name );
-      sb->flags  = bone->flags;
-      sb->collider = bone->collider;
-      sb->orig_bone = bone;
-
-      if( sb->flags & k_bone_flag_ik )
-      {
-         skele->bones[ sb->parent ].flags |= k_bone_flag_ik;
-         
-         if( ik_count == skele->ik_count )
-         {
-            vg_error( "Too many ik bones, corrupt model file\n" );
-            skeleton_fatal_err();
-         }
-
-         struct skeleton_ik *ik = &skele->ik[ ik_count ++ ];
-         ik->upper = i+1;
-         ik->lower = bone->parent;
-         ik->target = bone->ik_target;
-         ik->pole = bone->ik_pole;
-      }
-
-      box_copy( bone->hitbox, sb->hitbox );
-
-      if( bone->collider )
-      {
-         if( collider_count == skele->collider_count )
-         {
-            vg_error( "Too many collider bones\n" );
-            skeleton_fatal_err();
-         }
-         collider_count ++;
-      }
-   }
-
-   /* fill in implicit root bone */
-   v3_zero( skele->bones[0].co );
-   v3_copy( (v3f){0.0f,1.0f,0.0f}, skele->bones[0].end );
-   skele->bones[0].parent = 0xffffffff;
-   skele->bones[0].flags = 0;
-   skele->bones[0].name = "[root]";
-
-   skeleton_create_inverses( skele );
-   vg_success( "Loaded skeleton with %u bones\n", skele->bone_count );
-   vg_success( "                     %u colliders\n", skele->collider_count );
-}
-
-static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx )
-{
-   for( u32 i=1; i<skele->bone_count; i ++ )
-   {
-      struct skeleton_bone *sb = &skele->bones[i];
-      v3f p0, p1;
-      v3_copy( sb->co, p0 );
-      v3_add( p0, sb->end, p1 );
-
-      m4x3_mulv( final_mtx[i], p0, p0 );
-      m4x3_mulv( final_mtx[i], p1, p1 );
-
-      if( sb->flags & k_bone_flag_deform )
-      {
-         if( sb->flags & k_bone_flag_ik )
-            vg_line( p0, p1, 0xff0000ff );
-         else
-            vg_line( p0, p1, 0xffcccccc );
-      }
-      else
-         vg_line( p0, p1, 0xff00ffff );
-   }
-}
diff --git a/src/traffic.h b/src/traffic.h
deleted file mode 100644 (file)
index 004c624..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef TRAFFIC_H
-#define TRAFFIC_H
-
-#include "common.h"
-#include "model.h"
-#include "rigidbody.h"
-#include "world.h"
-
-typedef struct traffic_node traffic_node;
-typedef struct traffic_driver traffic_driver;
-
-struct traffic_node
-{
-   v3f co, h;
-
-   union
-   {
-      struct{ traffic_node *next, *next1; };
-      struct{ mdl_node *mn_next, *mn_next1; };
-   };
-};
-
-struct traffic_driver
-{
-   m4x3f transform;
-
-   traffic_node *current;
-   int option;
-   float t, speed;
-};
-
-static float eval_bezier_length( v3f p0, v3f p1, v3f h0, v3f h1, int res )
-{
-   float length = 0.0f, m = 1.0f/(float)res;
-   v3f l, p;
-   v3_copy( p0, l );
-
-   for( int i=0; i<res; i++ )
-   {
-      float t = (float)(i+1)*m;
-      eval_bezier_time(p0,p1,h0,h1,t,p);
-      length += v3_dist( p,l );
-      v3_copy( p, l );
-   }
-
-   return length;
-}
-
-static void traffic_finalize( traffic_node *system, int count )
-{
-   for( int i=0; i<count; i++ )
-   {
-      traffic_node *tn = &system[i];
-
-      if( tn->mn_next )
-         tn->next = &system[ tn->mn_next->sub_uid ];
-      if( tn->mn_next1 )
-         tn->next1 = &system[ tn->mn_next1->sub_uid ];
-   }
-}
-
-static void traffic_visualize_link( traffic_node *ta, traffic_node *tb )
-{
-   v3f p0, p1, h0, h1, p, l;
-
-   if( !tb ) return;
-
-   v3_copy( ta->co, p0 );
-   v3_muladds( ta->co, ta->h,  1.0f, h0 );
-   v3_copy( tb->co, p1 );
-   v3_muladds( tb->co, tb->h, -1.0f, h1 );
-   v3_copy( p0, l );
-
-   vg_line_pt3( h0, 0.2f, 0xff00ff00 );
-   vg_line_pt3( h1, 0.2f, 0xffff00ff );
-   vg_line( p0, h0, 0xff000000 );
-   vg_line( p1, h1, 0xff000000 );
-
-   for( int i=0; i<5; i++ )
-   {
-      float t = (float)(i+1)/5.0f;
-      eval_bezier_time( p0, p1, h0, h1, t, p );
-
-      vg_line( p, l, 0xffffffff );
-      v3_copy( p, l );
-   }
-}
-
-static void sample_wheel_floor( v3f pos )
-{
-   v3f ground;
-   v3_copy( pos, ground );
-   ground[1] += 4.0f;
-   
-   ray_hit hit;
-   hit.dist = 8.0f;
-
-   if( ray_world( ground, (v3f){0.0f,-1.0f,0.0f}, &hit ))
-   {
-      v3_copy( hit.pos, pos );
-   }
-}
-
-static void traffic_drive( traffic_driver *driver )
-{
-   traffic_node *next, *current = driver->current;
-
-   if( !current ) return;
-   next = driver->option==0? current->next: current->next1;
-   
-   if( driver->t > 1.0f )
-   {
-      driver->t = driver->t - floorf( driver->t );
-      driver->current = driver->option==0? current->next: current->next1;
-      driver->option = 0;
-      
-      current = driver->current;
-      if( !current )
-         return;
-
-      if( current->next && current->next1 )
-         if( vg_randf() > 0.5f )
-            driver->option = 1;
-   }
-
-   traffic_visualize_link( current, next );
-
-   /*
-    * Calculate the speed of the curve at the current point. On the reference
-    * curve the rate should come out to be exactly 1 ktimestep traveled.
-    * Dividing this distance by ktimestep gives us the modifier to use.
-    */
-   v3f p0,p1,h0,h1,pc,pn;
-   
-   v3_copy( current->co, p0 );
-   v3_muladds( current->co, current->h, 1.0f, h0 );
-   v3_copy( next->co, p1 );
-   v3_muladds( next->co, next->h, -1.0f, h1 );
-
-   eval_bezier_time( p0,p1,h0,h1, driver->t, pc );
-   eval_bezier_time( p0,p1,h0,h1, driver->t + vg.time_delta, pn );
-
-   float mod = vg.time_delta / v3_dist( pc, pn );
-   v3f dir,side,up;
-   v3_sub( pn, pc, dir );
-   v3_normalize(dir);
-   
-   /*
-    * Stick the car on the ground by casting rays where the wheels are
-    */
-   side[0] = -dir[2];
-   side[1] =  0.0f;
-   side[2] =  dir[0];
-   v3_normalize(side);
-
-   v3f fl, fr, bc;
-   v3_muladds( pc, dir, 2.0f, fr );
-   v3_muladds( pc, dir, 2.0f, fl );
-   v3_muladds( pc, dir, -2.0f, bc );
-   v3_muladds( fr, side, 1.0f, fr );
-   v3_muladds( fl, side, -1.0f, fl );
-
-   sample_wheel_floor( fl );
-   sample_wheel_floor( fr );
-   sample_wheel_floor( bc );
-
-   vg_line( fl, fr, 0xff00ffff );
-   vg_line( fr, bc, 0xff00ffff );
-   vg_line( bc, fl, 0xff00ffff );
-
-   v3f norm;
-   v3f v0, v1;
-   v3_sub( fr, fl, v0 );
-   v3_sub( bc, fl, v1 );
-   v3_cross( v1, v0, norm );
-   v3_normalize( norm );
-
-   /* 
-    * Jesus take the wheel
-    */
-   float steer_penalty = 1.0f-v3_dot( dir, driver->transform[0] );
-   steer_penalty /= vg.time_delta;
-   steer_penalty *= 30.0f;
-   
-   float target_speed = vg_maxf( 16.0f * (1.0f-steer_penalty), 0.1f ),
-         accel = target_speed - driver->speed;
-   driver->speed = stable_force( driver->speed, accel*vg.time_delta*2.0f );
-   driver->t += driver->speed*mod*vg.time_delta;
-
-   /* 
-    * Update transform
-    */
-   v3_cross( dir, norm, side );
-   v3_copy( dir, driver->transform[0] );
-   v3_copy( norm, driver->transform[1] );
-   v3_copy( side, driver->transform[2] );
-
-   v3_add( fl, fr, pc );
-   v3_add( bc, pc, pc );
-   v3_muls( pc, 1.0f/3.0f, pc );
-   v3_copy( pc, driver->transform[3] );
-}
-
-static void traffic_visualize( traffic_node *system, int count )
-{
-   for( int i=0; i<count; i++ )
-   {
-      traffic_node *tn = &system[i];
-
-      traffic_visualize_link( tn, tn->next );
-      traffic_visualize_link( tn, tn->next1 );
-   }
-}
-
-static void traffic_visualize_car( traffic_driver *driver )
-{
-   vg_line_boxf_transformed( driver->transform, 
-                                       (boxf){{-1.0f,0.0f,-0.5f},
-                                              { 1.0f,0.0f, 0.5f}}, 0xff00ff00 );
-}
-
-#endif /* TRAFFIC_H */
index fa123c13f2aa8091cf612f2dc85ef6b5221cce3b..24d9b4e2e1fc297c0fd755ead45d5e31f5a59e94 100644 (file)
@@ -1,19 +1,8 @@
-#pragma once
-#include "vg/vg_engine.h"
-#include "vg/vg_platform.h"
-#include "vg/vg_m.h"
-#include "vg/vg_lines.h"
-#include "vg/vg_camera.h"
-#include "trail.h"
-#include "shaders/particle.h"
-#include "shaders/trail.h"
-
-static void trail_increment( trail_system *sys ){
+static void trail_increment( trail_system *sys )
+{
    sys->head ++;
-
    if( sys->head == sys->max )
       sys->head = 0;
-
    /* undesirable effect: will remove active points if out of space! */
    if( sys->count < sys->max )
       sys->count ++;
@@ -114,23 +103,19 @@ void trail_system_debug( trail_system *sys )
    }
 }
 
-struct trail_init_args {
-   trail_system *sys;
-};
-
-void async_trail_init( vg_async_task *task )
+void trail_alloc( trail_system *sys, u32 max, vg_stack_allocator *stack )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN|VG_THREAD_OWNS_OPENGL ) );
 
-   struct trail_init_args *args = (void *)task->data;
-   trail_system *sys = args->sys;
+   u32 stride = sizeof(trail_vert);
+   sys->max = max;
+   sys->array = vg_stack_allocate( NULL, max*sizeof(trail_point), 8, "Trail array" );
+   sys->vertices = vg_stack_allocate( NULL, max*stride*2, 8, "Trail vertices" );
 
    glGenVertexArrays( 1, &sys->vao );
    glGenBuffers( 1, &sys->vbo );
    glBindVertexArray( sys->vao );
 
-   size_t stride = sizeof(trail_vert);
-
    glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
    glBufferData( GL_ARRAY_BUFFER, sys->max*stride*2, NULL, GL_DYNAMIC_DRAW );
 
@@ -139,28 +124,16 @@ void async_trail_init( vg_async_task *task )
    glEnableVertexAttribArray( 0 );
 }
 
-void trail_alloc( trail_system *sys, u32 max )
-{
-   THREAD_1;
-
-   size_t stride = sizeof(trail_vert);
-   sys->max = max;
-   sys->array = vg_stack_allocate( &vg.rtmem, max*sizeof(trail_point), 8, "Trail array" );
-   sys->vertices = vg_stack_allocate( &vg.rtmem, max*stride*2, 8, "Trail vertices" );
-
-   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct trail_init_args), 1 );
-   struct trail_init_args *init = (void *)task->data;
-   init->sys = sys;
-   vg_async_task_dispatch( task, async_trail_init );
-}
-
 void trail_system_prerender( trail_system *sys )
 {
-   if( sys->count < 2 ) return;
+   if( sys->count < 2 ) 
+      return;
 
-   for( i32 i=0; i<sys->count; i ++ ){
+   for( i32 i=0; i<sys->count; i ++ )
+   {
       i32 i0 = sys->head - sys->count + i;
-      if( i0 < 0 ) i0 += sys->max;
+      if( i0 < 0 ) 
+         i0 += sys->max;
 
       trail_point *p0 = &sys->array[i0];
       trail_vert *v0 = &sys->vertices[i*2+0],
@@ -171,17 +144,17 @@ void trail_system_prerender( trail_system *sys )
       v0->co[3] = p0->alpha;
       v1->co[3] = p0->alpha;
    }
-
    glBindVertexArray( sys->vao );
 
-   size_t stride = sizeof(trail_vert);
+   u32 stride = sizeof(trail_vert);
    glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
    glBufferSubData( GL_ARRAY_BUFFER, 0, sys->count*stride*2, sys->vertices );
 }
 
 void trail_system_render( trail_system *sys, vg_camera *cam )
 {
-   if( sys->count < 2 ) return;
+   if( sys->count < 2 ) 
+      return;
    glDisable( GL_CULL_FACE );
    glEnable( GL_DEPTH_TEST );
 
index 82c7d608564aeea545133224f10c35fc1295a305..409eca92523d14e7f12d3625b3fe37dab723c5d9 100644 (file)
@@ -1,4 +1,6 @@
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/trail.c"
+#else
 
 typedef struct trail_system trail_system;
 typedef struct trail_point trail_point;
@@ -25,9 +27,10 @@ struct trail_system {
    f32 width, lifetime, min_dist;
 };
 
-void trail_alloc( trail_system *sys, u32 max );
-void trail_system_update( trail_system *sys, f32 dt, v3f co, 
-                          v3f normal, f32 alpha );
+void trail_alloc( trail_system *sys, u32 max, vg_stack_allocator *stack );
+void trail_system_update( trail_system *sys, f32 dt, v3f co, v3f normal, f32 alpha );
 void trail_system_debug( trail_system *sys );
 void trail_system_prerender( trail_system *sys );
 void trail_system_render( trail_system *sys, vg_camera *cam );
+
+#endif
diff --git a/src/unit_skaterift.c b/src/unit_skaterift.c
new file mode 100644 (file)
index 0000000..112b94e
--- /dev/null
@@ -0,0 +1,8 @@
+#include "vg/vg.hconf"
+
+#define SR_ALL
+#include "src/skaterift.hconf"
+
+#define SR_IMPLEMENTATION
+#include "src/skaterift.hconf"
+#undef SR_IMPLEMENTATION
index 2209b1482d07720dd95e36857430cba91d4c0716..1cecacca3e115621042004bca471f57ff16182e9 100644 (file)
@@ -1,5 +1,3 @@
-#include "user_profile.h"
-
 struct menu_icon_inf
 {
    u16 desc_offset;
@@ -14,7 +12,7 @@ struct
 
    u32 country_index;
 
-   u16 race3, race10;
+   u32 race3, race10;
    f32 timer;
 
    enum user_profile_state
@@ -29,7 +27,7 @@ struct
    v2f country_coords;
 
    bool has_avatar;
-   GLuint cc_tex, map_tex, icon_tex, no_avatar_tex, avatar_tex;
+   vg_tex cc_tex, map_tex, icon_tex, no_avatar_tex, avatar_tex;
 }
 _user_profile = { .country_coords = {0.5f, 0.5f} };
 
@@ -41,18 +39,25 @@ struct country
 
 #include "cc.h"
 
-void _user_profile_init(void)
+static void _user_profile_load_content_async( void *_, vg_async_info *async )
+{
+   u32 flags = VG_TEX_CLAMP|VG_TEX_NEAREST;
+   _vg_tex_load( &_user_profile.cc_tex,         "textures/cc.qoi", flags );
+   _vg_tex_load( &_user_profile.map_tex,        "textures/world_map.qoi", flags );
+   _vg_tex_load( &_user_profile.icon_tex,       "textures/menu_icons.qoi", flags );
+   _vg_tex_load( &_user_profile.no_avatar_tex,  "textures/no_avatar.qoi", flags );
+   _vg_tex_load( &_user_profile.avatar_tex,     "textures/no_avatar.qoi", flags );
+}
+
+VG_API void _user_profile_init(void)
 {
-   vg_tex2d_load_qoi_async_file( "textures/cc.qoi", VG_TEX2D_CLAMP, &_user_profile.cc_tex );
-   vg_tex2d_load_qoi_async_file( "textures/world_map.qoi", VG_TEX2D_CLAMP, &_user_profile.map_tex );
-   vg_tex2d_load_qoi_async_file( "textures/menu_icons.qoi", VG_TEX2D_CLAMP, &_user_profile.icon_tex );
-   vg_tex2d_load_qoi_async_file( "textures/no_avatar.qoi", VG_TEX2D_CLAMP, &_user_profile.no_avatar_tex );
-   vg_tex2d_load_qoi_async_file( "textures/no_avatar.qoi", VG_TEX2D_CLAMP, &_user_profile.avatar_tex );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_user_profile_load_content_async );
 }
 
 static void _profile_download_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    u64 steamid = userdata;
    if( steamid != _user_profile.current_steamid ) 
@@ -66,30 +71,39 @@ static void _profile_download_callback( void *data, u32 data_size, u64 userdata,
 
    _user_profile.state = k_user_profile_state_open;
 
-   vg_msg body;
-   vg_msg_init( &body, data, data_size );
+   u32 temp_frame = _vg_start_temp_frame();
+   {
+      vg_stream kv_stream;
+      vg_buffer_stream_open( &kv_stream, data, data_size, VG_STREAM_READ );
 
-   const char *username = vg_msg_getkvstr( &body, "username" );
-   vg_strncpy( username, _user_profile.username, sizeof(_user_profile.username), k_strncpy_always_add_null );
+      vg_kvs kvs;
+      vg_kvs_init( &kvs, _vg_temp_stack() );
+      vg_kv_parser parser;
+      vg_kv_parser_init( &parser, &kvs, 0 );
+      vg_kv_parse_stream( &parser, &kv_stream );
 
-   vg_msg_getkvintg( &body, "flags", k_vg_msg_u32, &_user_profile.flags, NULL );
-   vg_msg_getkvintg( &body, "race3", k_vg_msg_u16, &_user_profile.race3, NULL );
-   vg_msg_getkvintg( &body, "race10", k_vg_msg_u16, &_user_profile.race10, NULL );
-   _user_profile.country_index = 0;
+      const c8 *username = vg_kv_value( &kvs, vg_kv_find( &kvs, 0, "username" ), NULL );
+      vg_strncpy( username, _user_profile.username, sizeof(_user_profile.username), k_strncpy_always_add_null );
 
-   const char *cc = vg_msg_getkvstr( &body, "cc" );
+      vg_kv_read_vu32( &kvs, 0, "flags", NULL, &_user_profile.flags, 1 );
+      vg_kv_read_vu32( &kvs, 0, "race3", NULL, &_user_profile.race3, 1 );
+      vg_kv_read_vu32( &kvs, 0, "race10", NULL, &_user_profile.race10, 1 );
+      _user_profile.country_index = 0;
 
-   if( cc && strlen(cc)>=2 )
-   {
-      for( u32 i=0; i<k_country_count; i ++ )
+      const c8 *cc = vg_kv_value( &kvs, vg_kv_find( &kvs, 0, "cc" ), NULL );
+      if( cc && strlen(cc)>=2 )
       {
-         if( (k_country_iso2[i*3+0] == cc[0]) && (k_country_iso2[i*3+1] == cc[1]) )
+         for( u32 i=0; i<k_country_count; i ++ )
          {
-            _user_profile.country_index = i+1;
-            break;
+            if( (k_country_iso2[i*3+0] == cc[0]) && (k_country_iso2[i*3+1] == cc[1]) )
+            {
+               _user_profile.country_index = i+1;
+               break;
+            }
          }
       }
    }
+   _vg_end_temp_frame( temp_frame );
 }
 
 void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
@@ -107,15 +121,19 @@ void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
          _user_profile.current_steamid = steamid;
          _user_profile.timer = 1.0f;
 
+         // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
          vg_info( "Request profile for: "PRINTF_U64"\n", steamid );
-         netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
-         packet->inetmsg_id = k_inetmsg_request;
-
          vg_msg data;
          vg_msg_init( &data, packet->buffer, 512 );
          vg_msg_wkvstr( &data, "endpoint", "profile" );
          vg_msg_wkvnum( &data, "steamid", k_vg_msg_u64, 1, &steamid );
-         network_send_request( packet, &data, _profile_download_callback, steamid );
+
+         const c8 *yep_fix_me = "endpoint profile\n"
+                                "steamid 1234\n";
+         network_send_request( yep_fix_me, 0, _profile_download_callback, steamid );
+#endif
+         // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
 
          u64 me_id = SteamAPI_ISteamUser_GetSteamID( _steam_api.pSteamUser );
          bool isme = 0;
@@ -139,7 +157,7 @@ void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
                      
                      if( SteamAPI_ISteamUtils_GetImageRGBA( _steam_api.pSteamUtils, avatar_handle, tmp, w*h*4 ) )
                      {
-                        glBindTexture( GL_TEXTURE_2D, _user_profile.avatar_tex );
+                        vg_tex_bind( GL_TEXTURE_2D, &_user_profile.avatar_tex, 0 );
                         glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp );
                         _user_profile.has_avatar = 1;
                      }
@@ -200,9 +218,7 @@ void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
           x = (i & 0xf)*16,
           y = ((i>>4) & 0xf)*16;
       ui_fill_rect( ctx, flag, 0xffffffff, (ui_px[4]){ x,y,x+16,y+16 } );
-
-      struct ui_batch_shader_data_image inf = { .resource = &_user_profile.cc_tex };
-      ui_flush( ctx, k_ui_shader_image, &inf );
+      ui_flush( ctx, k_ui_shader_image, &_user_profile.cc_tex );
    }
 
    ui_image( ctx, pfp, _user_profile.has_avatar? &_user_profile.avatar_tex: &_user_profile.no_avatar_tex, 1 );
@@ -274,9 +290,7 @@ void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
              w = ((icon_index>>3) & 0x7)*32;
          ui_fill_rect( ctx, medal_box, 0xffffffff, (ui_px[4]){ z,w,z+32,w+32 } );
       }
-
-      struct ui_batch_shader_data_image inf = { .resource = &_user_profile.icon_tex };
-      ui_flush( ctx, k_ui_shader_image, &inf );
+      ui_flush( ctx, k_ui_shader_image, &_user_profile.icon_tex );
 
       x = base;
       for( u32 i=0; i<medal_count; i ++ )
@@ -290,7 +304,7 @@ void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid )
             vg_str str;
             vg_strnull( &str, buf, sizeof(buf) );
             vg_strcatch( &str, 'x' );
-            vg_strcati32( &str, medal_list[i].count );
+            vg_strcati64( &str, medal_list[i].count, 10 );
             ui_text( ctx, count_box, buf, 1, k_ui_align_middle, ui_colour(ctx,k_ui_fg) );
          }
       }
@@ -353,9 +367,7 @@ bool _user_profile_country_picker( ui_context *ctx, ui_rect box )
    vg_ui.frosting = 0.0f;
 
    ui_fill_rect( ctx, box, 0xffffffff, (ui_px[4]){ 0,0,256,256 } );
-
-   struct ui_batch_shader_data_image inf1 = { .resource = &_user_profile.map_tex };
-   ui_flush( ctx, k_ui_shader_image, &inf1 );
+   ui_flush( ctx, k_ui_shader_image, &_user_profile.map_tex );
 
    for( u32 i=0; i<k_country_count; i ++ )
    {
@@ -393,9 +405,7 @@ bool _user_profile_country_picker( ui_context *ctx, ui_rect box )
           y = ((min_country>>4) & 0xf)*16;
       ui_fill_rect( ctx, min_country_rect, 0xffffffff, (ui_px[4]){ x,y,x+16,y+16 } );
    }
-
-   struct ui_batch_shader_data_image inf = { .resource = &_user_profile.cc_tex };
-   ui_flush( ctx, k_ui_shader_image, &inf );
+   ui_flush( ctx, k_ui_shader_image, &_user_profile.cc_tex );
 
    if( min_country >= 0 )
    {
@@ -522,13 +532,19 @@ bool _user_profile_country_picker( ui_context *ctx, ui_rect box )
       netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
       packet->inetmsg_id = k_inetmsg_request;
 
-      vg_msg data;
-      vg_msg_init( &data, packet->buffer, 512 );
-      vg_msg_wkvstr( &data, "endpoint", "profile" );
+      u32 temp_frame = _vg_start_temp_frame();
+      {
+         vg_kvs kvs;
+         vg_kvs_init( &kvs, _vg_temp_stack() );
+         vg_kv_append( &kvs, 0, "endpoint", "profile" );
+         u32 index = _user_profile.country_index;
+         vg_kv_append( &kvs, 0, "cc",index == 0? "00": k_country_iso2+(index-1)*3 ); 
+      }
+      _vg_end_temp_frame( temp_frame );
 
-      u32 index = _user_profile.country_index;
-      vg_msg_wkvstr( &data, "cc", index == 0? "00": k_country_iso2+(index-1)*3 );
-      network_send_request( packet, &data, _profile_download_callback, 0 );
+      VG_ASSERT(0);
+      // FIXME FIXME FIXME FIXME 
+      //network_send_request( todo, 0, _profile_download_callback, 0 );
    }
 
    return close;
index 6accf556d32266b927ae92ec79c7e0cb56b05cae..72b4624b393c0daf6ec5d0e726e272ac6bb15094 100644 (file)
@@ -1,4 +1,9 @@
-#pragma once
-void _user_profile_init(void);
+#if defined( SR_IMPLEMENTATION )
+# include "src/user_profile.c"
+#else
+
+VG_API void _user_profile_init(void);
 void _user_profile_ui( ui_context *ctx, ui_rect box, u64 steamid );
 bool _user_profile_country_picker( ui_context *ctx, ui_rect box );
+
+#endif
index 7145bec8c09583e9d583581f5d59c1d51100fb8c..b736e809d37b5d05c83084cea64cf929f761f92c 100644 (file)
@@ -78,7 +78,7 @@ void vg_post_update(void){}
 void vg_render(void)
 {
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
+   glViewport( 0,0, _vg_window.w, _vg_window.h );
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
 }
@@ -87,7 +87,7 @@ void vg_gui( ui_context *ctx )
 {
    ui_capture_mouse( ctx, 1 );
 
-   ui_rect rect = { 8,8, vg.window_x-16, vg.window_y-16 };
+   ui_rect rect = { 8,8, _vg_window.w-16, _vg_window.h-16 };
 
 }
 
index 6ce6d2f1cc5357033a1cf8d44e4b0ac9d108d143..502abff79260bd3f897e63f56884bc02a1b486d1 100644 (file)
@@ -1,7 +1,3 @@
-#include "skaterift.h"
-#include "vehicle.h"
-#include "scene_rigidbody.h"
-
 struct drivable_vehicle gzoomer =
 {
    .rb.co = {-2000,-2000,-2000}
index 3e60bb76d6d2b9e7b3cd9a6212da38b39b4982b6..98acb9f6490129684b28d0b3e0726e0cef103e44 100644 (file)
@@ -1,8 +1,6 @@
-#pragma once
-#include "vg/vg_rigidbody.h"
-#include "player.h"
-#include "world.h"
-#include "world_physics.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/vehicle.c"
+#else
 
 static float k_car_spring = 1.0f,
                 k_car_spring_damp = 0.001f,
@@ -40,3 +38,5 @@ void vehicle_wheel_force( int index );
 void vehicle_solve_friction(void);
 void vehicle_update_fixed(void);
 void vehicle_update_post(void);
+
+#endif
index 75d186372a8a3bf849266ca9045d0aa35d911804..2aaa23f4d7919fff0f76e77ff5ddcdf63fdc73d0 100644 (file)
@@ -1,15 +1,3 @@
-#include "vg/vg_engine.h"
-#include "vg/vg_tex.h"
-#include "vg/vg_image.h"
-#include "vg/vg_msg.h"
-#include "vg/vg_binstr.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include "ent_skateshop.h"
-
-#include "vg/vg_steam2.h"
-#include "workshop.h"
-
 struct workshop_form workshop_form;
 
 static struct ui_enum_opt workshop_form_visibility_opts[] = {
@@ -158,7 +146,7 @@ static const char *workshop_filetype_folder(void){
  */
 static void workshop_form_upload_submission( PublishedFileId_t file_id, char *metadata )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    UGCUpdateHandle_t handle = SteamAPI_ISteamUGC_StartItemUpdate( _steam_api.pSteamUGC, SKATERIFT_APPID, file_id );
 
    /* TODO: Handle failure cases for these */
@@ -210,6 +198,8 @@ static void workshop_form_upload_submission( PublishedFileId_t file_id, char *me
 /*
  * Steam API call result for when we've created a new item on their network, or 
  * not, if it has failed
+ *
+ * FIXME FIXME FIXME FIXME FIXME FIXME FIXME
  */
 static void on_workshop_createitem( void *data, void *user )
 {
@@ -238,23 +228,25 @@ static void on_workshop_createitem( void *data, void *user )
 /*
  * Starts the workshop upload process through Steam API
  */
-static void workshop_form_async_submit_begin( void *userdata )
+static void workshop_form_async_submit_begin( void *_, vg_async_info *async )
 {
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_OWNS_STEAM ) );
+
    /* use existing file */
    if( workshop_form.submission.file_id )
    {
-      workshop_form_upload_submission( workshop_form.submission.file_id, userdata );
+      workshop_form_upload_submission( workshop_form.submission.file_id, "undefined" );
    }
    else
    {
       vg_steam_api_call *call = vg_alloc_async_steam_api_call();
-      call->userdata = userdata;
+      call->userdata = "undefined";
       call->cb = on_workshop_createitem;
       call->id = SteamAPI_ISteamUGC_CreateItem( _steam_api.pSteamUGC, SKATERIFT_APPID, k_EWorkshopFileTypeCommunity );
    }
 }
 
-static void _workshop_form_end_op( void *userdata )
+static void _workshop_form_end_op( void *_, vg_async_info *async )
 {
    workshop_form.op = k_workshop_op_none;
 }
@@ -262,7 +254,7 @@ static void _workshop_form_end_op( void *userdata )
 /*
  * Thread which kicks off the upload process
  */
-static void _workshop_form_submit_t1( void *userdata )
+static void _workshop_form_submit_t1( void *_, vg_async_info *async )
 {
    char path_buf[4096];
    vg_str folder;
@@ -274,81 +266,77 @@ static void _workshop_form_submit_t1( void *userdata )
    if( !vg_strgood(&folder) )
    {
       vg_error( "addon folder path too long\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
-   /* 
-    * Create the metadata file
-    * -----------------------------------------------------------------------*/
-   u8 descriptor_buf[ 512 ];
-   vg_msg descriptor;
-   vg_msg_init( &descriptor, descriptor_buf, sizeof(descriptor_buf) );
-   vg_stack_clear( &vg.scratch );
-
-   /* short description */
-   vg_msg_frame( &descriptor, "workshop" );
-   {
-      vg_msg_wkvstr( &descriptor, "title", workshop_form.submission.title );
-      //vg_msg_wkvstr( &descriptor, "author", "unknown" );
-      vg_msg_wkvnum( &descriptor, "type", k_vg_msg_u32, 1, &workshop_form.submission.type );
-      vg_msg_wkvstr( &descriptor, "folder", workshop_form.addon_folder );
-   }
-   vg_msg_end_frame( &descriptor );
-   //vg_msg_wkvstr( &descriptor, "location", "USA" );
-
-   char *short_descriptor_str = vg_stack_allocate( &vg.scratch, descriptor.cur.co*2+1, 1, "Descriptor String" );
-   vg_bin_str( descriptor_buf, short_descriptor_str, descriptor.cur.co );
-   short_descriptor_str[descriptor.cur.co*2] = '\0';
-   vg_info( "binstr: %s\n", short_descriptor_str );
-
    vg_dir dir;
    if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
    {
       vg_error( "could not open addon folder '%s'\n", folder.buffer );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
-   while( vg_dir_next_entry(&dir) )
+   u32 temp_frame = _vg_start_temp_frame();
    {
-      if( vg_dir_entry_type(&dir) == k_vg_entry_type_file )
+      vg_kvs kvs;
+      vg_kvs_init( &kvs, _vg_temp_stack() );
+
+      while( vg_dir_next_entry(&dir) )
       {
-         const char *d_name = vg_dir_entry_name(&dir);
-         if( d_name[0] == '.' ) continue;
+         if( vg_dir_entry_type(&dir) == k_vg_entry_type_file )
+         {
+            const char *d_name = vg_dir_entry_name(&dir);
+            if( d_name[0] == '.' ) continue;
 
-         vg_str file = folder;
-         vg_strcat( &file, "/" );
-         vg_strcat( &file, d_name );
-         if( !vg_strgood( &file ) ) continue;
+            vg_str file = folder;
+            vg_strcat( &file, "/" );
+            vg_strcat( &file, d_name );
+            if( !vg_strgood( &file ) ) continue;
 
-         char *ext = vg_strch( &file, '.' );
-         if( !ext ) continue;
-         if( strcmp(ext,".mdl") ) continue;
+            char *ext = vg_strch( &file, '.' );
+            if( !ext ) continue;
+            if( strcmp(ext,".mdl") ) continue;
 
-         vg_msg_wkvstr( &descriptor, "content", d_name );
-         break;
+            vg_kv_append( &kvs, 0, "content", d_name );
+            break;
+         }
       }
-   }
-   vg_dir_close(&dir);
+      vg_dir_close(&dir);
 
-   vg_str descriptor_file = folder;
-   vg_strcat( &descriptor_file, "/addon.inf" );
-   if( !vg_strgood(&descriptor_file) ){
-      vg_error( "Addon info path too long\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
-      return;
-   }
-   
-   FILE *fp = fopen( descriptor_file.buffer, "wb" );
-   if( !fp )
-   {
-      vg_error( "Could not open addon info file '%s'\n", descriptor_file.buffer );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
-      return;
+      u32 workshop_block = vg_kv_append( &kvs, 0, "workshop", NULL );
+      vg_kv_append( &kvs, workshop_block, "title", workshop_form.submission.title );
+      vg_kv_append_vu32( &kvs, workshop_block, "type", &workshop_form.submission.type, 1 );
+      vg_kv_append( &kvs, workshop_block, "folder", workshop_form.addon_folder );
+
+
+      vg_str descriptor_file = folder;
+      vg_strcat( &descriptor_file, "/addon.kv" );
+      if( !vg_strgood(&descriptor_file) )
+      {
+         vg_error( "Addon info path too long\n" );
+         _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
+         _vg_end_temp_frame( temp_frame );
+         return;
+      }
+      
+      // FIXME FIXME FIXME FIXME FIXME
+      vg_error( "FIXME!!!!!!\n" );
+      VG_ASSERT(0);
+#if 0
+      FILE *fp = fopen( descriptor_file.buffer, "wb" );
+      if( !fp )
+      {
+         vg_error( "Could not open addon info file '%s'\n", descriptor_file.buffer );
+         vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+         return;
+      }
+      fwrite( descriptor_buf, descriptor.cur.co, 1, fp );
+      fclose( fp );
+#endif
    }
-   fwrite( descriptor_buf, descriptor.cur.co, 1, fp );
-   fclose( fp );
+   _vg_end_temp_frame( temp_frame );
 
    /* Save the preview 
     * -----------------------------------------------------------------------*/
@@ -358,7 +346,7 @@ static void _workshop_form_submit_t1( void *userdata )
    if( !vg_strgood(&preview) )
    {
       vg_error( "preview image path too long\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
@@ -369,7 +357,7 @@ static void _workshop_form_submit_t1( void *userdata )
    stbi_flip_vertically_on_write(1);
    stbi_write_jpg( preview.buffer, w,h, 3, workshop_form.img_buffer, 90 );
 
-   vg_async_call( &vg.main_tasks, workshop_form_async_submit_begin, short_descriptor_str );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)workshop_form_async_submit_begin );
 }
 
 /*
@@ -414,8 +402,9 @@ static void workshop_op_submit( ui_context *ctx )
 
    int w, h;
    vg_framebuffer_get_res( g_render.fb_workshop_preview, &w, &h );
-   vg_stack_clear( &vg.scratch );
-   workshop_form.img_buffer = vg_stack_allocate( &vg.scratch, w*h*3, 8, "Image buffer" );
+
+   // FIXME FIXME
+   //workshop_form.img_buffer = vg_stack_allocate( &vg.scratch, w*h*3, 8, "Image buffer" );
 
    vg_info( "read framebuffer: glReadPixels( %dx%d )\n", w,h );
 
@@ -426,7 +415,7 @@ static void workshop_op_submit( ui_context *ctx )
    workshop_form.img_w = w;
    workshop_form.img_h = h;
 
-   vg_async_call( &vg.loader_tasks, _workshop_form_submit_t1, NULL );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_form_submit_t1 );
 }
 
 /*
@@ -437,9 +426,9 @@ static void workshop_op_submit( ui_context *ctx )
 /*
  * Reciever for completion of the model file load
  */
-static void workshop_form_loadmodel_async_complete( void *userdata )
+static void workshop_form_loadmodel_async_complete( void *_, vg_async_info *async )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    v2_zero( workshop_form.view_angles );
    v3_zero( workshop_form.view_offset );
@@ -454,9 +443,9 @@ static void workshop_form_loadmodel_async_complete( void *userdata )
 /*
  * Thread which loads the model from the disk 
  */
-static void _workshop_form_load_t1( void *userdata )
+static void _workshop_form_load_t1( void *_, vg_async_info *async )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    char path_buf[4096];
    vg_str folder;
@@ -468,7 +457,7 @@ static void _workshop_form_load_t1( void *userdata )
    if( !vg_strgood(&folder) )
    {
       vg_error( "workshop async load failed: path too long\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
@@ -476,7 +465,7 @@ static void _workshop_form_load_t1( void *userdata )
    if( vg_dir_open( &dir, folder.buffer ) != k_dir_open_ok )
    {
       vg_error( "workshop async load failed: could not open folder\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
@@ -507,7 +496,7 @@ static void _workshop_form_load_t1( void *userdata )
    if( !found_mdl )
    {
       vg_error( "workshop async load failed: no model files found\n" );
-      vg_async_call( &vg.main_tasks, _workshop_form_end_op, NULL );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)_workshop_form_end_op );
       return;
    }
 
@@ -528,7 +517,7 @@ static void _workshop_form_load_t1( void *userdata )
       player_model_load( &workshop_form.player_model, path_buf, &workshop_form.model_stack );
    }
 
-   vg_async_call( &vg.main_tasks, workshop_form_loadmodel_async_complete, NULL );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)workshop_form_loadmodel_async_complete );
 }
 
 /*
@@ -536,7 +525,7 @@ static void _workshop_form_load_t1( void *userdata )
  */
 static void workshop_op_load_model( ui_context *ctx )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    world_instance *world = &_world.main;
    workshop_form.view_world = world;
 
@@ -564,7 +553,7 @@ static void workshop_op_load_model( ui_context *ctx )
    }
 
    workshop_form.op = k_workshop_op_loading_model;
-   vg_async_call( &vg.loader_tasks, _workshop_form_load_t1, NULL );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_form_load_t1 );
 }
 
 /*
@@ -575,14 +564,16 @@ static void workshop_op_load_model( ui_context *ctx )
 /*
  * The image has been decoded and is ready to slap into the framebuffer
  */
+
+// FIXME FIXME FIXME
 static void workshop_form_async_imageload( void *data )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    if( data )
    {
       vg_framebuffer_attachment *a = &g_render.fb_workshop_preview->attachments[0];
-      glBindTexture( GL_TEXTURE_2D, a->id );
+      vg_tex_bind( GL_TEXTURE_2D, &a->tex, 6 );
       glTexSubImage2D( GL_TEXTURE_2D, 0,0,0, WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, a->format, a->type, data );
       stbi_image_free( data );
       vg_success( "Loaded workshop preview image\n" );
@@ -600,9 +591,9 @@ static void workshop_form_async_imageload( void *data )
 /*
  * Load the image located at ./workshop_preview.jpg into our framebuffer
  */
-static void _workshop_load_preview_t1( void *userdata )
+static void _workshop_load_preview_t1( void *_, vg_async_info *async )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    char path_buf[ 4096 ];
    vg_str path;
@@ -621,23 +612,28 @@ static void _workshop_load_preview_t1( void *userdata )
       {
          if( (x == WORKSHOP_PREVIEW_WIDTH) && (y == WORKSHOP_PREVIEW_HEIGHT) )
          {
-            vg_async_call( &vg.main_tasks, workshop_form_async_imageload, rgb );
+            //FIXME FIXME
+            //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, rgb );
          }
          else
          {
             vg_error( "Resolution does not match framebuffer, so we can't show it\n" );
             stbi_image_free( rgb );
-            vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+
+            // FIXME FIXME
+            //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
          }
       }
       else
       {
-         vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+         // FIXME FIXME
+         //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
       }
    }
    else
    {
-      vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
+      // FIXME FIXME
+      //vg_async_call( &vg.main_tasks, workshop_form_async_imageload, NULL );
    }
 }
 
@@ -646,7 +642,7 @@ static void _workshop_load_preview_t1( void *userdata )
  */
 static void workshop_op_download_and_view_submission( int result_index )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
 
    workshop_form.op = k_workshop_op_downloading_submission;
    SteamUGCDetails_t details;
@@ -669,8 +665,10 @@ static void workshop_op_download_and_view_submission( int result_index )
       vg_strncpy( details.m_rgchTitle, workshop_form.submission.title,
                   VG_ARRAY_LEN( workshop_form.submission.title ), k_strncpy_always_add_null );
 
-      snprintf( workshop_form.addon_folder, VG_ARRAY_LEN( workshop_form.addon_folder ),
-                 "Steam Cloud ("PRINTF_U64")", details.m_nPublishedFileId );
+      vg_str folder_str;
+      vg_strnull( &folder_str, workshop_form.addon_folder, sizeof(workshop_form.addon_folder) );
+      vg_strcat( &folder_str, "Steam Cloud (" );
+      vg_strcatu64( &folder_str, details.m_nPublishedFileId, 16 );
 
       workshop_form.submission.file_id = details.m_nPublishedFileId;
       workshop_form.file_intent = k_workshop_form_file_intent_keep_old;
@@ -679,6 +677,8 @@ static void workshop_op_download_and_view_submission( int result_index )
       workshop_form.submission.type = k_addon_type_none;
       workshop_form.submission.submission_type_selection = k_addon_type_none;
 
+      // FIXME FIXME FIXME FIXME::::::::::::: 
+#if 0
       if( have_meta )
       {
          u32 len = strlen(metadata_str);
@@ -706,14 +706,14 @@ static void workshop_op_download_and_view_submission( int result_index )
       {
          vg_error( "No metadata was returned with this item.\n" );
       }
+#endif
 
       vg_framebuffer_bind( g_render.fb_workshop_preview, 1.0f );
       glClearColor( 0.2f, 0.0f, 0.0f, 1.0f );
       glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-      glViewport( 0,0, vg.window_x, vg.window_y );
-
-      vg_async_call( &vg.loader_tasks, _workshop_load_preview_t1, NULL );
+      glViewport( 0,0, _vg_window.w, _vg_window.h );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_workshop_load_preview_t1 );
    }
    else
    {
@@ -847,7 +847,7 @@ int workshop_submit_command( int argc, const char *argv[] )
    return 0;
 }
 
-void workshop_register(void)
+VG_API void _workshop_register(void)
 {
    vg_console_reg_cmd( "workshop_submit", workshop_submit_command, NULL );
 }
@@ -864,7 +864,7 @@ static void workshop_render_world_preview(void)
    render_world( &_world.main, &g_render.cam, 0, 0, 1, 1, g_render.fb_workshop_preview );
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
+   glViewport( 0,0, _vg_window.w, _vg_window.h );
 }
 
 /*
@@ -878,12 +878,12 @@ static void workshop_render_player_preview(void)
    glEnable( GL_DEPTH_TEST );
    glDisable( GL_BLEND );
 
-   struct skeleton *sk = &localplayer.skeleton;
+   ms_skeleton *sk = &localplayer.skeleton;
 
    player_pose res;
    res.type = k_player_pose_type_ik;
 
-   skeleton_anim anim;
+   ms_skeletal_animation anim;
    player_get_anim( &anim, "idle_cycle+y" );
    skeleton_sample_anim( sk, &anim, vg.time*0.1f, res.keyframes );
    q_axis_angle( res.root_q, (v3f){0.0f,1.0f,0.0f}, VG_PIf );
@@ -919,7 +919,7 @@ static void workshop_render_player_preview(void)
    render_playermodel( &cam, &_world.main, 0, &workshop_form.playermodel_view, sk, localplayer.final_mtx );
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
+   glViewport( 0,0, _vg_window.w, _vg_window.h );
 }
 
 /*
@@ -997,14 +997,14 @@ static void workshop_render_board_preview(void)
     * pre-render step, but that includes timer stuff 
     */
    struct player_board *board = &workshop_form.board_model;
-   struct ub_world_lighting *ubo = &world->ub_lighting;
+   struct ub_world_lighting *ubo = &world_render.ub_lighting;
    v3f vp0, vp1;
    v3_copy((v3f){0.0f,0.1f, board->truck_positions[0][2]}, vp0 );
    v3_copy((v3f){0.0f,0.1f, board->truck_positions[1][2]}, vp1 );
    m4x3_mulv( mmdl1, vp0, ubo->g_board_0 );
    m4x3_mulv( mmdl1, vp1, ubo->g_board_1 );
-   glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world->ub_lighting );
+   glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
 
    render_world( world, &cam, 0, 0, 0, 0, g_render.fb_workshop_preview );
    struct player_board_pose pose = {0};
@@ -1012,7 +1012,7 @@ static void workshop_render_board_preview(void)
    render_board( &cam, world, board, mmdl1, &pose, k_board_shader_entity );
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   glViewport( 0,0, vg.window_x, vg.window_y );
+   glViewport( 0,0, _vg_window.w, _vg_window.h );
 }
 
 /*
@@ -1091,11 +1091,13 @@ static void workshop_form_gui_draw_preview( ui_context *ctx, ui_rect img_box )
    enum addon_type type = workshop_form.submission.type;
    if( workshop_form.file_intent == k_workshop_form_file_intent_keep_old )
    {
-      ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+      // FIXME FIXME
+      // ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
    }
    else if( workshop_form.file_intent == k_workshop_form_file_intent_new )
    {
-      ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+      // FIXME FIXME
+      // ui_image( ctx, img_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
 
       if( type == k_addon_type_world )
          return;
@@ -1360,9 +1362,9 @@ static void workshop_form_gui_sidebar( ui_context *ctx, ui_rect sidebar )
    vg_str str;
    vg_strnull( &str, buf, sizeof(buf) );
    vg_strcat( &str, "page " );
-   vg_strcati32( &str,  workshop_form.view_published_page_id+1 );
+   vg_strcati64( &str,  workshop_form.view_published_page_id+1, 10 );
    vg_strcatch( &str, '/' );
-   vg_strcati32( &str, workshop_form.view_published_page_count );
+   vg_strcati64( &str, workshop_form.view_published_page_count, 10 );
 
    ui_rect_pad( controls, (ui_px[2]){0,4} );
    ui_rect info;
@@ -1420,7 +1422,7 @@ void workshop_form_gui( ui_context *ctx )
       return;
 
    ui_rect null;
-   ui_rect screen = { 0, 0, vg.window_x, vg.window_y };
+   ui_rect screen = { 0, 0, _vg_window.w, _vg_window.h };
    ui_rect window = { 0, 0, 1000, 700 };
    ui_rect_center( screen, window );
    ctx->wants_mouse = 1;
index 86dd1809c27c03ad15ecd2015a81eb29259cf4b0..a70719101f27089c269e2b34ab85b3de73f15ce7 100644 (file)
@@ -1,8 +1,6 @@
-#pragma once
-#include "addon_types.h"
-#include "vg/vg_steam2.h"
-#include "skaterift.h"
-#include "ent_skateshop.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/workshop.c"
+#else
 
 struct async_workshop_filepath_info{
    PublishedFileId_t id;
@@ -129,9 +127,12 @@ struct workshop_form
 }
 extern workshop_form;
 
-void workshop_register(void);
+VG_API void _workshop_register(void);
+
 int workshop_submit_command( int argc, const char *argv[] );
 void async_workshop_get_filepath( void *data, u32 len );
 void async_workshop_get_installed_files( void *data, u32 len );
 void workshop_load_metadata( const char *path,struct workshop_file_info *info );
 void workshop_form_gui( ui_context *ctx );
+
+#endif
index 21eb5cba55393fe959d16e3c49126d5e30e76f99..3e331da82bbd3e030cf609eba693b20ac3a297ac 100644 (file)
@@ -1,31 +1,16 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "skaterift.h"
-#include "world.h"
-#include "network.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_mem.h"
-#include "save.h"
-#include "player.h"
-#include "ent_traffic.h"
-
 struct world_static _world;
 
-void world_init(void)
+VG_API void _world_init(void)
 {
-   vg_loader_step( world_render_init, NULL );
-   vg_loader_step( world_sfd_init, NULL );
-   vg_loader_step( world_water_init, NULL );
-   vg_loader_step( world_gates_init, NULL );
-   vg_loader_step( world_routes_init, NULL );
+   _world_render_init();
+   _world_sfd_init();
+   _world_water_init();
+   _world_gates_init();
+   _world_routes_init();
 
    /* Allocate dynamic world memory arena */
-   _world.stack = vg_stack_make_substack( &vg.rtmem, VG_MB(76), "World main data" );
-   vg_stack_set_flags( _world.stack, VG_STACK_ALLOCATOR_METADATA );
-   _world.preview_stack = vg_stack_make_substack( &vg.rtmem, VG_MB(32), "World preview data" );
-   vg_stack_set_flags( _world.preview_stack, VG_STACK_ALLOCATOR_METADATA );
+   vg_stack_init( &_world.stack, VG_STACK_USE_HEAP, VG_MB(76), "World main data" );
+   vg_stack_init( &_world.preview_stack, VG_STACK_USE_HEAP, VG_MB(32), "World preview data" );
 }
 
 void world_update( world_instance *world, v3f pos )
@@ -40,13 +25,14 @@ void world_update( world_instance *world, v3f pos )
    world_sfd_update( world, pos );
    world_volumes_update( world, pos );
    ent_skateshop_update();
-   ent_challenge_update();
+   _ent_challenge_update();
    ent_prop_update( world );
+   _world_audio_update( pos );
 }
 
 void world_gui( ui_context *ctx, world_instance *world )
 {
-   ent_skateshop_gui( ctx );
+   _ent_skateshop_gui( ctx );
    _ent_challenge_ui( ctx );
 }
 
index 8f425468210f1b1de8c944404f39af958379c763..d1a4cf88ce90cb2f4b473cb9a2eee5d824e1cb95 100644 (file)
@@ -1,12 +1,6 @@
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
-#include "render.h"
-#include "network_msg.h"
-#include "addon.h"
-#include "scene.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world.c"
+#else
 
 /* types
  */
@@ -28,20 +22,6 @@ struct leaderboard_cache
 
 typedef struct world_instance world_instance;
 
-/* submodule headers */
-#include "world_entity.h"
-#include "world_gate.h"
-#include "world_gen.h"
-#include "world_info.h"
-#include "world_physics.h"
-#include "world_render.h"
-#include "world_sfd.h"
-#include "world_volumes.h"
-#include "world_water.h"
-#include "world_audio.h"
-#include "world_routes.h"
-#include "world_routes_ui.h"
-
 /* console variables */
 
 static f32   k_day_length            = 30.0f; /* minutes */
@@ -72,45 +52,6 @@ struct world_instance
 
    f64 time;
    f32 tar_min, tar_max;
-
-   /* STD140 */
-   struct ub_world_lighting{
-      v4f g_cube_min,
-          g_cube_inv_range;
-
-      v4f g_water_plane,
-          g_depth_bounds;
-
-      v4f g_daysky_colour;
-      v4f g_nightsky_colour;
-      v4f g_sunset_colour;
-      v4f g_ambient_colour;
-      v4f g_sunset_ambient;
-      v4f g_sun_colour;
-      v4f g_sun_dir;
-      v4f g_board_0;
-      v4f g_board_1;
-
-      float g_water_fog;
-      float g_time;
-      float g_realtime;
-      float g_shadow_length;
-      float g_shadow_spread;
-
-      float g_time_of_day;
-      float g_day_phase;
-      float g_sunset_phase;
-
-      int g_light_preview;
-      int g_shadow_samples;
-
-      int g_debug_indices;
-      int g_debug_complexity;
-   }
-   ub_lighting;
-   GLuint ubo_lighting;
-   int    ubo_bind_point;
-
    GLuint tbo_light_entities,
           tex_light_entities,
           tex_light_cubes;
@@ -118,7 +59,6 @@ struct world_instance
    float probabilities[3];
 
    v3i light_cubes;
-   vg_framebuffer *heightmap;
 
    /*
     * Dynamically allocated when world_load is called.
@@ -131,13 +71,11 @@ struct world_instance
    /*
     * Main world .mdl 
     */
-   mdl_context meta;
+   vg_model meta;
 
-   GLuint *textures;
-   u32 texture_count;
-
-   struct world_surface{
-      mdl_material info;
+   struct world_surface
+   {
+      mdl_material info; 
       mdl_submesh sm_geo,
                   sm_no_collide;
       u32 flags;
@@ -181,7 +119,7 @@ struct world_instance
                  ent_atom,
                  ent_cutscene;
    
-   GLuint *nonlocal_gates_cubemaps;
+   vg_tex *nonlocal_gates_cubemaps;
    u32 nonlocal_gate_count;
 
    enum skybox {
@@ -197,20 +135,16 @@ struct world_instance
     */
 
    /* world geometry */
-   scene_context scene_geo,
-                 scene_geo_gpu,
-                 scene_no_collide,
-                 scene_lines;
+   vg_scene scene_geometry;
+   scene_mesh main_scene_mesh,
+              line_scene_mesh,
+              transparent_scene_mesh;
 
    /* spacial mappings */
-   bh_tree *geo_bh,
-           *entity_bh;
-   u32 *entity_list;
+   bh_tree geometry_bh,
+           entity_bh;
 
-   /* graphics */
-   glmesh mesh_route_lines;
-   glmesh mesh_geo, 
-          mesh_no_collide;
+   u32 *entity_list;
    u32 cubemap_cooldown, cubemap_side;
 
    /* leaderboards */
@@ -226,7 +160,7 @@ struct world_static
     * Allocated as system memory
     * --------------------------------------------------------------------------
     */
-   vg_stack_allocator *stack, *preview_stack;
+   vg_stack_allocator stack, preview_stack;
 
    u32 current_run_version;
    f64 last_gate_hit_time;
@@ -296,7 +230,7 @@ struct world_static
 }
 extern _world;
 
-void world_init(void);
+VG_API void _world_init(void);
 
 void skaterift_world_load_thread( void *_ );
 void world_update( world_instance *world, v3f pos );
@@ -305,3 +239,5 @@ bool world_set_event( enum world_event activity );
 bool world_clear_event( enum world_event activity );
 void world_set_entity_driven_camera( vg_camera *cam );
 void world_gui( ui_context *ctx, world_instance *world );
+
+#endif
index 3e0fecd571b49cbcb3f4b85903b850539ea13ef3..f14002c9dfc771d5bf7c6bc0b39f3c356c78b5c9 100644 (file)
@@ -1,6 +1,3 @@
-#include "audio.h"
-#include "world_audio.h"
-
 /*
  * Trace out a random point, near the player to try and determine water areas
  */
@@ -43,6 +40,34 @@ enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output)
       return k_audio_sprite_type_none;
 }
 
+void _world_audio_update( v3f co )
+{
+   static float accum = 0.0f;
+   accum += vg.time_delta;
+
+   if( accum > 0.1f )
+      accum -= 0.1f;
+   else return;
+
+   v3f sprite_pos;
+   enum audio_sprite_type sprite_type = world_audio_sample_sprite_random( co, sprite_pos );
+   
+   if( sprite_type != k_audio_sprite_type_none )
+   {
+      if( sprite_type == k_audio_sprite_type_grass )
+      {
+         audio_ambient_sprite_play( sprite_pos, &audio_grass[vg_randu32(&vg.rand)%4] );
+      }
+      else if( sprite_type == k_audio_sprite_type_water )
+      {
+         if( _world.main.water.enabled )
+         {
+            audio_ambient_sprite_play( sprite_pos, &audio_water[vg_randu32(&vg.rand)%6] );
+         }
+      }
+   }
+}
+
 void world_audio_sample_distances( v3f co, int *index, float *value )
 {
    float inr3 = 0.57735027,
index 07d66d1cc300a2daca4a6df3d3962c62a35f3355..8b1e6784cac4f2479156529a0fe2bfff94c07d02 100644 (file)
@@ -1,7 +1,11 @@
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_audio.c"
+#else
 
 void world_fadeout_audio( world_instance *world );
 void world_audio_sample_distances( v3f co, int *index, float *value );
 enum audio_sprite_type 
 world_audio_sample_sprite_random( v3f origin, v3f output );
+void _world_audio_update( v3f co );
+
+#endif
index f354a786d9ef5008a3825ae21c161fc02ea64f0d..2813a909c2c2326066743e4302723d832d498294 100644 (file)
@@ -1,23 +1,3 @@
-#include "vg/vg_steam2.h"
-#include "model.h"
-#include "entity.h"
-#include "world.h"
-#include "world_load.h"
-#include "save.h"
-#include "vg/vg_msg.h"
-#include "menu.h"
-#include "ent_challenge.h"
-#include "ent_skateshop.h"
-#include "ent_route.h"
-#include "ent_traffic.h"
-#include "ent_glider.h"
-#include "ent_region.h"
-#include "ent_camera.h"
-#include "ent_atom.h"
-#include "ent_cutscene.h"
-#include "input.h"
-#include "player_walk.h"
-
 bh_system bh_system_entity_list = 
 {
    .expand_bound = entity_bh_expand_bound,
@@ -42,9 +22,9 @@ _event_system;
 
 static void _event_trigger( ent_event *event );
 
-void world_gen_entities_init( world_instance *world )
+void world_gen_entities_init( world_instance *world, vg_model_stream_context *ctx )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    /* lights */
    for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ )
@@ -74,10 +54,9 @@ void world_gen_entities_init( world_instance *world )
 
    if( world->nonlocal_gate_count )
    {
-      world->nonlocal_gates_cubemaps = vg_stack_allocate( world->stack, world->nonlocal_gate_count*sizeof(GLuint),
+      world->nonlocal_gates_cubemaps = vg_stack_allocate( world->stack, world->nonlocal_gate_count*sizeof(vg_tex),
                                                           8, "Non-local cubemaps" );
-      for( u32 i=0; i<world->nonlocal_gate_count; i ++ )
-         world->nonlocal_gates_cubemaps[i] = 0;
+      vg_zero_mem( world->nonlocal_gates_cubemaps, world->nonlocal_gate_count*sizeof(vg_tex) );
 
       for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
       {
@@ -87,9 +66,10 @@ void world_gen_entities_init( world_instance *world )
             if( gate->remote_addon_id )
             {
                char cubemap_path[256];
-               nonlocal_gate_cubemap_path( gate->remote_addon_id, af_str( &world->meta.af, gate->key ), cubemap_path );
-               vg_tex2d_load_qoi_async_file( cubemap_path, VG_TEX2D_CUBEMAP, 
-                                             &world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+               nonlocal_gate_cubemap_path( gate->remote_addon_id, af_str( world->meta.packed_strings, gate->key ), cubemap_path );
+
+               u32 flags = VG_TEX_CUBEMAP|VG_TEX_CLAMP|VG_TEX_LINEAR|VG_TEX_NOMIP;
+               _vg_tex_load( &world->nonlocal_gates_cubemaps[ gate->cubemap_id ], cubemap_path, flags );
             }
          }
       }
@@ -126,33 +106,28 @@ void world_gen_entities_init( world_instance *world )
       for( u32 k=0; k<audio->clip_count; k++ )
       {
          ent_audio_clip *clip = af_arritm( &world->ent_audio_clip, audio->clip_start+k );
+
          if( clip->_.file.pack_size )
          {
             u32 size = clip->_.file.pack_size,
                 offset = clip->_.file.pack_offset;
 
-            /* embedded files are fine to clear the scratch buffer, only
-             * external audio uses it */
-
-            vg_stack_clear( &vg.scratch );
-            void *data = vg_stack_allocate( &vg.scratch, clip->_.file.pack_size, 8, "Pack data" );
-
-            mdl_fread_pack_file( &world->meta, &clip->_.file, data );
+            clip->_.clip.any_data = vg_stack_allocate( world->stack, clip->_.file.pack_size, 8, "Pack data" );
+            vg_stream_read( vg_model_stream_pack_stream( ctx, &clip->_.file ), clip->_.clip.any_data, clip->_.file.pack_size );
 
             clip->_.clip.path = NULL;
             clip->_.clip.flags = audio->flags;
-            clip->_.clip.any_data = data;
             clip->_.clip.size = size;
          }
          else
          {
-            clip->_.clip.path = af_str( &world->meta.af, clip->_.file.pstr_path );
+            clip->_.clip.path = af_str( world->meta.packed_strings, clip->_.file.pstr_path );
             clip->_.clip.flags = audio->flags;
             clip->_.clip.any_data = NULL;
             clip->_.clip.size = 0;
          }
 
-         audio_clip_load( &clip->_.clip, world->stack );
+         vg_audio_clip_load( &clip->_.clip, world->stack );
       }
    }
 
@@ -174,7 +149,6 @@ void world_gen_entities_init( world_instance *world )
    for( u32 i=0; i<VG_ARRAY_LEN(indexables); i++ )
       indexed_count += af_arrcount( indexables[i].array );
    vg_info( "indexing %u entities\n", indexed_count );
-
    world->entity_list = vg_stack_allocate( world->stack, indexed_count*sizeof(u32), 4, "Entity List");
 
    u32 index=0;
@@ -185,20 +159,19 @@ void world_gen_entities_init( world_instance *world )
       for( u32 j=0; j<count; j ++ )
          world->entity_list[index ++] = mdl_entity_id( type, j );
    }
-
-   world->entity_bh = bh_create( world->stack, &bh_system_entity_list, world, indexed_count, 2 );
+   bh_create( &world->entity_bh, &bh_system_entity_list, world, indexed_count, 2, world->stack );
 
    /* FIXME: This should be scene geometry instead?????????? */
-   world->tar_min = world->entity_bh->nodes[0].bbx[0][1];
-   world->tar_max = world->entity_bh->nodes[0].bbx[1][1] + 20.0f;
+   world->tar_min = world->entity_bh.nodes[0].bbx[0][1];
+   world->tar_max = world->entity_bh.nodes[0].bbx[1][1] + 20.0f;
 
    for( u32 i=0; i<af_arrcount(&world->ent_marker); i++ )
    {
       ent_marker *marker = af_arritm( &world->ent_marker, i );
-      if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tar_min" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tar_min" ) )
          world->tar_min = marker->transform.co[1];
 
-      if( AF_STR_EQ( &world->meta.af, marker->pstr_alias, "tar_max" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, marker->pstr_alias, "tar_max" ) )
          world->tar_max = marker->transform.co[1];
    }
 }
@@ -245,7 +218,7 @@ ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name )
    for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
    {
       r = af_arritm( &world->ent_spawn, i );
-      if( af_str_eq( &world->meta.af, r->pstr_name, name, hash ) )
+      if( af_str_eq( world->meta.packed_strings, r->pstr_name, name, hash ) )
       {
          rp = r;
          break;
@@ -364,7 +337,7 @@ entity_event_result ent_audio_event( ent_event *event )
    v3f sound_co;
    v3_copy( audio->transform.co, sound_co );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "spawn_particle" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "spawn_particle" ) )
    {
       // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
       if( mdl_entity_id_type( event->source_entity_id ) == k_ent_volume )
@@ -384,7 +357,7 @@ entity_event_result ent_audio_event( ent_event *event )
          return k_entity_event_result_invalid;
       }
    }
-   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "play" ) ){}
+   else if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "play" ) ){}
    else return k_entity_event_result_unhandled;
 
    ent_audio_trigger( audio, sound_co );
@@ -396,7 +369,7 @@ entity_event_result ent_light_event( ent_event *event )
    world_instance *world = &_world.main;
    ent_light *light = af_arritm( &world->ent_light, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "on" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "on" ) )
    {
       if( event->flags & k_ent_event_data_const_i32 )
       {
@@ -419,10 +392,10 @@ entity_event_result ent_light_event( ent_event *event )
 entity_event_result ent_ccmd_event( ent_event *event )
 {
    world_instance *world = &_world.main;
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "exec" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "exec" ) )
    {
       ent_ccmd *ccmd = af_arritm( &world->ent_ccmd, mdl_entity_id_id( event->recieve_entity_id ));
-      const char *cmd_text = af_str( &world->meta.af, ccmd->pstr_command );
+      const char *cmd_text = af_str( world->meta.packed_strings, ccmd->pstr_command );
       vg_info( "ccmd: %s\n", cmd_text );
       vg_execute_console_input( cmd_text, 0, 1 );
       return k_entity_event_result_OK;
@@ -626,7 +599,7 @@ void entity_bh_closest( void *user, u32 item_index, v3f point, v3f closest )
       vg_fatal_error( "Programming error\n" );
 }
 
-void world_entity_start( world_instance *world, vg_msg *sav )
+void world_entity_start( world_instance *world, vg_kvs *savedata )
 {
    vg_info( "Start instance %p\n", world );
    k_gravity = 9.6f;
@@ -635,7 +608,7 @@ void world_entity_start( world_instance *world, vg_msg *sav )
    for( u32 i=0; i<af_arrcount( &world->ent_event ); i ++ )
    {
       ent_event *event = af_arritm( &world->ent_event, i );
-      if( AF_STR_EQ( &world->meta.af, event->pstr_source_event, "init" ) )
+      if( AF_STR_EQ( world->meta.packed_strings, event->pstr_source_event, "init" ) )
          _event_trigger( event );
    }
 
@@ -653,33 +626,35 @@ void world_entity_start( world_instance *world, vg_msg *sav )
    for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
    {
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-      const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
-      vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &challenge->status, NULL );
+      const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
+      vg_kv_read_vu32( savedata, 0, alias, NULL, &challenge->status, 1 );
       _ent_challenge_clear( challenge );
    }
 
-   vg_msg routes_block = *sav;
-   if( vg_msg_seekframe( &routes_block, "routes" ) )
+   u32 routes_block = vg_kv_find( savedata, 0, "routes" );
+   if( routes_block )
    {
       for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
       {
          ent_route *route = af_arritm( &world->ent_route, i );
-         vg_msg route_info = routes_block;
-         if( vg_msg_seekframe( &route_info, af_str(&world->meta.af,route->pstr_name) ) )
+         
+         u32 route_info = vg_kv_find( savedata, routes_block, af_str(world->meta.packed_strings,route->pstr_name) );
+         if( route_info )
          {
             u32 flags;
-            vg_msg_getkvintg( &route_info, "flags", k_vg_msg_u32, &flags, NULL );
+            vg_kv_read_vu32( savedata, route_info, "flags", NULL, &flags, 1 );
             route->flags |= flags;
-
-            vg_msg_getkvintg( &route_info, "best_laptime", k_vg_msg_f64, &route->best_laptime, NULL );
+            
+            f32 best_time;
+            vg_kv_read_vf32( savedata, route_info, "best_laptime", NULL, &best_time, 1 );
+            route->best_laptime = best_time;
 
             f32 sections[ route->checkpoints_count ];
-            vg_msg_cmd cmd;
-            if( vg_msg_getkvcmd( &route_info, "sections", &cmd ) )
-               vg_msg_cast( cmd.value, cmd.code, sections, k_vg_msg_f32 | vg_msg_count_bits(route->checkpoints_count) );
-            else
-               for( u32 j=0; j<route->checkpoints_count; j ++ )
-                  sections[j] = 0.0f;
+            for( u32 j=0; j<route->checkpoints_count; j ++ )
+               sections[j] = 0.0f;
+
+            vg_zero_mem( sections, sizeof(sections) );
+            vg_kv_read_vf32( savedata, route_info, "sections", NULL, sections, route->checkpoints_count );
 
             for( u32 j=0; j<route->checkpoints_count; j ++ )
             {
@@ -692,16 +667,19 @@ void world_entity_start( world_instance *world, vg_msg *sav )
 
    _atom_list_clear( k_atom_list_world );
 
-   vg_msg_cursor orig = sav->cur;
-   if( vg_msg_seekframe( sav, "atoms" ) )
+   u32 atoms_block = vg_kv_find( savedata, 0, "atoms" );
+   if( atoms_block )
    {
-      vg_msg_cmd cmd;
-      while( vg_msg_next( sav, &cmd ) )
+      u32 key = vg_kv_child( savedata, atoms_block, 0 );
+      while( key )
       {
-         if( cmd.code == k_vg_msg_endframe ) break;
-         i32 value = 0;
-         vg_msg_cast( cmd.value, cmd.code, &value, k_vg_msg_i32 );
-         _atom_set( k_atom_list_world, cmd.key, value );
+         vg_strp s = { .buffer = vg_kv_value( savedata, key, NULL ) };
+
+         i64 value;
+         vg_strp_i64( &s, &value );
+         _atom_set( k_atom_list_world, vg_kv_key( savedata, key, NULL ), (i32)value );
+
+         key = vg_kv_next( savedata, key );
       }
    }
 
@@ -718,7 +696,7 @@ void world_entity_start( world_instance *world, vg_msg *sav )
       else
       {
          enum e_atom_list list = (atom->flags & k_ent_atom_global)? k_atom_list_global: k_atom_list_world;
-         value = _atom_get( list, af_str( &world->meta.af, atom->pstr_alias ) );
+         value = _atom_get( list, af_str( world->meta.packed_strings, atom->pstr_alias ) );
       }
       _world_raise_event( mdl_entity_id( k_ent_atom, i ), "changed" );
       _world_raise_event( mdl_entity_id( k_ent_atom, i ), value? "true": "false" );
@@ -728,43 +706,38 @@ void world_entity_start( world_instance *world, vg_msg *sav )
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
       _world_raise_event( mdl_entity_id( k_ent_challenge, i ), challenge->status? "true": "false" );
    }
-
-   sav->cur = orig;
 }
 
-void world_entity_serialize( world_instance *world, vg_msg *sav )
+void world_entity_serialize( world_instance *world, vg_kvs *savedata )
 {
    for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
    {
       ent_challenge *challenge = af_arritm(&world->ent_challenge,i);
-      const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
-      vg_msg_wkvnum( sav, alias, k_vg_msg_u32, 1, &challenge->status );
+      const char *alias = af_str( world->meta.packed_strings, challenge->pstr_alias );
+      vg_kv_append_vu32( savedata, 0, alias, &challenge->status, 1 );
    }
    
    if( af_arrcount(&world->ent_route) )
    {
-      vg_msg_frame( sav, "routes" );
+      u32 routes_block = vg_kv_append( savedata, 0, "routes", NULL );
       for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
       {
          ent_route *route = af_arritm( &world->ent_route, i );
-         vg_msg_frame( sav, af_str( &world->meta.af, route->pstr_name ) );
+
+         u32 route_info = vg_kv_append( savedata, routes_block, af_str( world->meta.packed_strings, route->pstr_name ), NULL );
          {
-            vg_msg_wkvnum( sav, "flags", k_vg_msg_u32, 1, &route->flags );
-            vg_msg_wkvnum( sav, "best_laptime", k_vg_msg_f64, 1, &route->best_laptime );
+            vg_kv_append_vu32( savedata, route_info, "flags", &route->flags, 1 );
+            vg_kv_append_vf32( savedata, route_info, "best_laptime", (f32[]){ route->best_laptime }, 1 );
 
             f32 sections[ route->checkpoints_count ];
-
             for( u32 j=0; j<route->checkpoints_count; j ++ )
             {
                ent_checkpoint *cp = af_arritm( &world->ent_checkpoint, route->checkpoints_start + j );
                sections[j] = cp->best_time;
             }
-
-            vg_msg_wkvnum( sav, "sections", k_vg_msg_f32, route->checkpoints_count, sections );
+            vg_kv_append_vf32( savedata, route_info, "sections", sections, route->checkpoints_count );
          }
-         vg_msg_end_frame( sav );
       }
-      vg_msg_end_frame( sav );
    }
 }
 
@@ -793,7 +766,7 @@ void _world_raise_event( u32 caller, const char *event_alias )
       if( event->source_entity_id != caller )
          continue;
 
-      if( af_str_eq( &world->meta.af, event->pstr_source_event, event_alias, event_alias_hash ) )
+      if( af_str_eq( world->meta.packed_strings, event->pstr_source_event, event_alias, event_alias_hash ) )
       {
          if( event->delay > 0.001f )
          {
@@ -867,29 +840,29 @@ static void _event_trigger( ent_event *event )
    if( event->flags & k_ent_event_data_const_string )
    {
       vg_info( "[event '%s'] %x -> %x ('%s') with '%s'\n", 
-               af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
-               event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
-               af_str( &world->meta.af, event->data.const_pstr ) );
+               af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+               event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ), 
+               af_str( world->meta.packed_strings, event->data.const_pstr ) );
    }
    else if( event->flags & k_ent_event_data_const_i32 )
    {
       vg_info( "[event '%s'] %x -> %x ('%s') with %d\n", 
-               af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
-               event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
+               af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+               event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ), 
                event->data.const_i32 );
    }
    else if( event->flags & k_ent_event_data_const_f32 )
    {
       vg_info( "[event '%s'] %x -> %x ('%s') with %ff\n", 
-               af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
-               event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
+               af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+               event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ), 
                event->data.const_f32 );
    }
    else if( event->flags & k_ent_event_data_const_f32 )
    {
       vg_info( "[event '%s'] %x -> %x ('%s') void\n", 
-               af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
-               event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ));
+               af_str( world->meta.packed_strings, event->pstr_source_event ), event->source_entity_id,
+               event->recieve_entity_id, af_str( world->meta.packed_strings, event->pstr_recieve_event ));
    }
 
    enum entity_event_result res = table[type]( event );
@@ -897,7 +870,7 @@ static void _event_trigger( ent_event *event )
    if( res == k_entity_event_result_unhandled )
    {
       vg_warn( "Call to entity %x#%x was unhandled (no event '%s').\n", type, index, 
-               af_str( &world->meta.af, event->pstr_recieve_event ) );
+               af_str( world->meta.packed_strings, event->pstr_recieve_event ) );
    }
    else if( res == k_entity_event_result_invalid )
       vg_warn( "Call to entity %x#%x invalid.\n", type, index );
index ea3e8b3828ec7a47f5855fee5c556d99a2f798ea..d03ee62b2def5fa270db0dda20812227eeb392f5 100644 (file)
@@ -1,15 +1,13 @@
-#pragma once
-#include "world.h"
-#include "entity.h"
-#include "vg/vg_bvh.h"
-#include "vg/vg_msg.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_entity.c"
+#else
 
-void world_gen_entities_init( world_instance *world );
+void world_gen_entities_init( world_instance *world, vg_model_stream_context *ctx );
 ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name );
 ent_spawn *world_find_closest_spawn( world_instance *world, v3f position );
 void world_default_spawn_pos( world_instance *world, v3f pos );
-void world_entity_start( world_instance *world, vg_msg *sav );
-void world_entity_serialize( world_instance *world, vg_msg *sav );
+void world_entity_start( world_instance *world, vg_kvs *savedata );
+void world_entity_serialize( world_instance *world, vg_kvs *savedata );
 
 //entity_call_result ent_volume_call( world_instance *world, ent_call *call );
 //entity_call_result ent_audio_call( world_instance *world, ent_call *call );
@@ -26,3 +24,5 @@ void update_ach_models(void);
 extern bh_system bh_system_entity_list;
 void _world_raise_event( u32 caller, const char *event_alias );
 void _ent_update(void);
+
+#endif
index 493ea33c932067d81e500b8f3c1070df9d105048..47590333fbb6956293120d65ee8a99b9c0cdca1c 100644 (file)
@@ -1,30 +1,9 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef WORLD_GATE_C
-#define WORLD_GATE_C
-
-#include "world.h"
-#include "world_gate.h"
-
-#include "skaterift.h"
-#include "common.h"
-#include "model.h"
-#include "entity.h"
-#include "render.h"
-
-#include "world_water.h"
-#include "player_remote.h"
-#include "shaders/model_gate_unlinked.h"
-#include <string.h>
-
-struct world_gates world_gates;
+struct _world_gates _world_gates;
 
 /*
  * Update the transform matrices for gate
  */
-void gate_transform_update( ent_gate *gate )
+VG_TIER_0 void gate_transform_update( ent_gate *gate )
 {
    if( gate->flags & k_ent_gate_flip )
    {
@@ -46,26 +25,21 @@ void gate_transform_update( ent_gate *gate )
    m4x3_mul( recv_to_world, to_local, gate->transport );
 }
 
-void world_gates_init(void)
+static void _world_gates_load_content_async( void *_, vg_async_info *async )
 {
-   THREAD_1;
-   vg_info( "world_gates_init\n" );
-   vg_stack_clear( &vg.scratch );
-
-   mdl_context mgate;
-   mdl_open( &mgate, "models/rs_gate.mdl", &vg.scratch );
-   mdl_load_metadata_block( &mgate, &vg.scratch );
-
-   world_gates.sm_surface = mgate.submeshes[ mdl_get_submesh_index( &mgate, "rs_gate" ) ];
-
-   const char *names[] = { "rs_gate_marker", "rs_gate_marker.001", 
-                           "rs_gate_marker.002", "rs_gate_marker.003" };
-
-   for( int i=0; i<4; i++ )
-      world_gates.sm_marker[i] = mgate.submeshes[ mdl_get_submesh_index( &mgate, names[i] ) ];
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   vg_model_load( &_world_gates.model, VG_MODEL_ENGINE_STANDARD, "models/rs_gate.mdl", VG_STACK_USE_HEAP );
+   _world_gates.sm_surface = _world_gates.model.submeshes[ vg_model_get_submesh_index( &_world_gates.model, "rs_gate" ) ];
+   const c8 *names[] = { "rs_gate_marker", "rs_gate_marker.001", 
+                         "rs_gate_marker.002", "rs_gate_marker.003" };
+   for( u32 i=0; i<4; i++ )
+      _world_gates.sm_marker[i] = _world_gates.model.submeshes[ vg_model_get_submesh_index( &_world_gates.model,names[i] ) ];
+}
 
-   mdl_async_load_glmesh( &mgate, &world_gates.mesh, NULL );
-   mdl_close( &mgate );
+VG_API void _world_gates_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_gates_load_content_async );
 }
 
 void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl )
@@ -82,17 +56,17 @@ static void render_gate_mesh( world_instance *world, ent_gate *gate )
 {
    if( gate->flags & k_ent_gate_custom_mesh )
    {
-      mesh_bind( &world->mesh_no_collide );
+      scene_mesh_bind( &world->transparent_scene_mesh );
       for( u32 i=0; i<gate->submesh_count; i++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ gate->submesh_start+i ];
-         mdl_draw_submesh( sm );
+         vg_model_draw_submesh( sm );
       }
    }
    else 
    {
-      mesh_bind( &world_gates.mesh );
-      mdl_draw_submesh( &world_gates.sm_surface );
+      vg_model_bind_mesh( &_world_gates.model );
+      vg_model_draw_submesh( &_world_gates.sm_surface );
    }
 }
 
@@ -136,29 +110,29 @@ int render_gate( world_instance *world, world_instance *world_inside, ent_gate *
    }
 
    /* update gate camera */
-   world_gates.cam.fov = cam->fov;
-   world_gates.cam.nearz = 0.1f;
-   world_gates.cam.farz  = 2000.0f;
+   _world_gates.cam.fov = cam->fov;
+   _world_gates.cam.nearz = 0.1f;
+   _world_gates.cam.farz  = 2000.0f;
 
-   m4x3_mul( gate->transport, cam->transform, world_gates.cam.transform );
-   vg_camera_update_view( &world_gates.cam );
-   vg_camera_update_projection( &world_gates.cam, vg.window_x, vg.window_y );
+   m4x3_mul( gate->transport, cam->transform, _world_gates.cam.transform );
+   vg_camera_update_view( &_world_gates.cam );
+   vg_camera_update_projection( &_world_gates.cam, _vg_window.w, _vg_window.h );
 
    /* Add special clipping plane to projection */
    v4f surface;
    q_mulv( gate->q[1], (v3f){0.0f,0.0f,-1.0f}, surface );
    surface[3] = v3_dot( surface, gate->co[1] );
    
-   m4x3_mulp( world_gates.cam.transform_inverse, surface, surface );
+   m4x3_mulp( _world_gates.cam.transform_inverse, surface, surface );
    surface[3] = -fabsf(surface[3]);
 
    if( dist < -0.5f )
-      m4x4_clip_projection( world_gates.cam.mtx.p, surface );
+      m4x4_clip_projection( _world_gates.cam.mtx.p, surface );
 
    /* Ready to draw with new camrea */
-   vg_camera_finalize( &world_gates.cam );
+   vg_camera_finalize( &_world_gates.cam );
 
-   vg_line_point( world_gates.cam.transform[3], 0.3f, 0xff00ff00 );
+   vg_line_point( _world_gates.cam.transform[3], 0.3f, 0xff00ff00 );
 
    shader_model_gate_use();
    shader_model_gate_uPv( cam->mtx.pv );
@@ -166,8 +140,8 @@ int render_gate( world_instance *world, world_instance *world_inside, ent_gate *
    shader_model_gate_uColour( (v4f){0.0f,1.0f,0.0f,0.0f} );
    shader_model_gate_uTime( vg.time*0.25f );
    shader_model_gate_uInvRes( (v2f){
-         1.0f / (float)vg.window_x,
-         1.0f / (float)vg.window_y });
+         1.0f / (float)_vg_window.w,
+         1.0f / (float)_vg_window.h });
 
    glEnable( GL_STENCIL_TEST );
    glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );  
@@ -181,7 +155,7 @@ int render_gate( world_instance *world, world_instance *world_inside, ent_gate *
    render_gate_mesh( world, gate );
 
    if( world_inside )
-      render_world( world_inside, &world_gates.cam, 1, !localplayer.gate_waiting, 1, 1, target_fb );
+      render_world( world_inside, &_world_gates.cam, 1, !localplayer.gate_waiting, 1, 1, target_fb );
 
    return 1;
 }
@@ -299,7 +273,7 @@ entity_event_result ent_gate_event( ent_event *event )
 {
    world_instance *world = &_world.main;
    ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id( event->recieve_entity_id ) );
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "lock" ) )
    {
       // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
       if( event->flags == k_ent_event_data_const_i32 )
@@ -333,7 +307,7 @@ void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key,
  */
 void world_link_gates( world_instance *world )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    bool found_nonlocal_reciever = 0;
 
@@ -349,7 +323,7 @@ void world_link_gates( world_instance *world )
       {
          if( gate->target )
          {
-            const char *dest_world = af_str( &world->meta.af, gate->target );
+            const char *dest_world = af_str( world->meta.packed_strings, gate->target );
             
             addon_alias q;
             if( addon_parse_uid( dest_world, &q ) )
@@ -367,7 +341,7 @@ void world_link_gates( world_instance *world )
 
          if( _world.travelled_through_nonlocal_gate )
          {
-            const char *key = af_str( &world->meta.af, gate->key );
+            const char *key = af_str( world->meta.packed_strings, gate->key );
             if( vg_str_eq( key, _world.nonlocal_destination_key ) )
             {
                if( found_nonlocal_reciever )
@@ -424,5 +398,3 @@ void world_link_gates( world_instance *world )
       _world.travelled_through_nonlocal_gate = 0;
    }
 }
-
-#endif /* WORLD_GATE_C */
index a11fb00506f0a9b99b402b981acf6a4b4497d5fe..6939cefd256e516bdc4c23406e9c54924d137c36 100644 (file)
@@ -1,26 +1,19 @@
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_gate.c"
+#else
 
-#pragma once
-
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "shaders/model_gate.h"
-#include "entity.h"
-
-struct world_gates
+struct _world_gates
 {
-   glmesh mesh;
+   vg_model model;
    mdl_submesh sm_surface, sm_marker[4];
    vg_camera cam;
-
    v3f userportal_co;
 }
-extern world_gates;
+extern _world_gates;
 
-void world_gates_init(void);
-void gate_transform_update( ent_gate *gate );
+VG_API void _world_gates_init(void);
+
+VG_TIER_0 void gate_transform_update( ent_gate *gate );
 int render_gate( world_instance *world, world_instance *world_inside,
                  ent_gate *gate, vg_camera *cam, vg_framebuffer *target_fb );
 
@@ -34,3 +27,5 @@ void world_link_gates( world_instance *world );
 void world_unlink_nonlocal( world_instance *world );
 void render_gate_unlinked( world_instance *world, ent_gate *gate, vg_camera *cam );
 void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key, char path[256] );
+
+#endif
index 314ef3257e34291912de9713017ff0eabc657f7b..b20b7e1a74c9572c22cc51f1aba0252564b9ec74 100644 (file)
@@ -1,27 +1,12 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- *
- * World generation/population. Different to regular loading, since it needs to
- * create geometry, apply procedural stuff and save that image to files etc.
- */
-#include "world.h"
-#include "world_gen.h"
-#include "world_load.h"
-#include "world_volumes.h"
-#include "world_gate.h"
-#include <string.h>
-
 /*
  * Add all triangles from the model, which match the material ID
  * applies affine transform to the model
  */
-static void world_add_all_if_material( m4x3f transform, scene_context *scene, 
-                                          mdl_context *mdl, u32 id )
+static void world_add_all_if_material( m4x3f transform, scene_builder_context *builder, vg_model *mdl, u32 id )
 {
    for( u32 i=0; i<mdl->mesh_count; i++ )
    {
       mdl_mesh *mesh = &mdl->meshes[ i ];
-
       for( u32 j=0; j<mesh->submesh_count; j++ )
       {
          mdl_submesh *sm = &mdl->submeshes[ mesh->submesh_start+j ];
@@ -30,8 +15,7 @@ static void world_add_all_if_material( m4x3f transform, scene_context *scene,
             m4x3f transform2;
             mdl_transform_m4x3( &mesh->transform, transform2 );
             m4x3_mul( transform, transform2, transform2 );
-
-            scene_add_mdl_submesh( scene, mdl, sm, transform2 );
+            scene_builder_add_model_submesh( builder, mdl, sm, transform2 );
          }
       }
    }
@@ -46,8 +30,7 @@ static void world_add_all_if_material( m4x3f transform, scene_context *scene,
  * |        |
  * |________|
  */
-static void world_gen_add_blob( vg_rand *rand, world_instance *world,
-                                   scene_context *scene, ray_hit *hit )
+static void world_gen_add_blob( vg_rand *rand, world_instance *world, scene_builder_context *builder, ray_hit *hit )
 {
    m4x3f transform;
    v4f qsurface, qrandom;
@@ -55,7 +38,7 @@ static void world_gen_add_blob( vg_rand *rand, world_instance *world,
 
    v3_cross( (v3f){0.0f,1.0f,0.0f}, hit->normal, axis );
 
-   float angle = v3_dot(hit->normal,(v3f){0.0f,1.0f,0.0f});
+   f32 angle = v3_dot(hit->normal,(v3f){0.0f,1.0f,0.0f});
    q_axis_angle( qsurface, axis, angle );
    q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf64(rand)*VG_TAUf );
    q_mul( qsurface, qrandom, qsurface );
@@ -73,41 +56,30 @@ static void world_gen_add_blob( vg_rand *rand, world_instance *world,
    };
 
    const u32 indices[] = { 0,1,3, 0,3,2, 2,3,5, 2,5,4 };
+   scene_vert *dst_verts = vg_stack_allocate( &builder->vertex_stack, sizeof(scene_vert)*VG_ARRAY_LEN(verts), 1, "verts" );
+   u32 *dst_indices      = vg_stack_allocate( &builder->indice_stack, sizeof(u32)*VG_ARRAY_LEN(indices), 1, "indices" );
+   scene_vert *ref       = &world->scene_geometry.vertex_buffer[ hit->tri[0] ];
 
-   if( scene->vertex_count + VG_ARRAY_LEN(verts) > scene->max_vertices )
-      vg_fatal_error( "Scene vertex buffer overflow" );
-
-   if( scene->indice_count + VG_ARRAY_LEN(indices) > scene->max_indices )
-      vg_fatal_error( "Scene index buffer overflow" );
-
-   scene_vert *dst_verts = &scene->arrvertices[ scene->vertex_count ];
-   u32 *dst_indices      = &scene->arrindices [ scene->indice_count ];
-
-   scene_vert *ref       = &world->scene_geo.arrvertices[ hit->tri[0] ];
-
-   for( u32 i=0; i<VG_ARRAY_LEN(verts); i++ ){
+   for( u32 i=0; i<VG_ARRAY_LEN(verts); i++ )
+   {
       scene_vert *pvert = &dst_verts[ i ],
                  *src   = &verts[ i ];
-
       m4x3_mulv( transform, src->co, pvert->co );
       scene_vert_pack_norm( pvert, transform[1], 0.0f );
-
       v2_copy( ref->uv, pvert->uv );
    }
 
    for( u32 i=0; i<VG_ARRAY_LEN(indices); i++ )
-      dst_indices[i] = indices[i] + scene->vertex_count;
+      dst_indices[i] = indices[i] + builder->scene.vertex_count;
 
-   scene->vertex_count += VG_ARRAY_LEN(verts);
-   scene->indice_count += VG_ARRAY_LEN(indices);
+   builder->scene.vertex_count += VG_ARRAY_LEN(verts);
+   builder->scene.indice_count += VG_ARRAY_LEN(indices);
 }
 
 /* 
  * Sprinkle foliage models over the map on terrain material 
  */
-static void world_apply_procedural_foliage( world_instance *world,
-                                               scene_context *scene,
-                                               struct world_surface *mat )
+static void world_apply_procedural_foliage( world_instance *world, scene_builder_context *builder, struct world_surface *mat )
 {
    if( (vg.quality_profile == k_quality_profile_low) ||
        (vg.quality_profile == k_quality_profile_min) )
@@ -116,12 +88,12 @@ static void world_apply_procedural_foliage( world_instance *world,
    vg_info( "Applying foliage (%u)\n", mat->info.pstr_name );
 
    v3f volume;
-   v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], volume );
+   v3_sub( world->scene_geometry.bbx[1], world->scene_geometry.bbx[0], volume );
    volume[1] = 1.0f;
 
    int count = 0;
 
-   float area = volume[0]*volume[2];
+   f32 area = volume[0]*volume[2];
    u32 particles = 0.08f * area;
 
    vg_info( "Map area: %f. Max particles: %u\n", area, particles );
@@ -132,7 +104,7 @@ static void world_apply_procedural_foliage( world_instance *world,
       v3f pos;
       v3_mul( volume, (v3f){ vg_randf64(), 1000.0f, vg_randf64() }, pos );
       pos[1] = 1000.0f;
-      v3_add( pos, world->scene_geo.bbx[0], pos );
+      v3_add( pos, world->scene_geometry.bbx[0], pos );
       
       ray_hit hit;
       hit.dist = INFINITY;
@@ -153,26 +125,28 @@ static void world_apply_procedural_foliage( world_instance *world,
    
    const f32 tile_scale = 16.0f;
    v2i tiles = { volume[0]/tile_scale, volume[2]/tile_scale };
-
    u32 per_tile = particles/(tiles[0]*tiles[1]);
 
-   for( i32 x=0; x<tiles[0]; x ++ ){
-      for( i32 z=0; z<tiles[1]; z ++ ){
-         for( u32 i=0; i<per_tile; i ++ ){
+   for( i32 x=0; x<tiles[0]; x ++ )
+   {
+      for( i32 z=0; z<tiles[1]; z ++ )
+      {
+         for( u32 i=0; i<per_tile; i ++ )
+         {
             v3f co = { (f32)x+vg_randf64(&rand), 0, (f32)z+vg_randf64(&rand) };
             v3_muls( co, tile_scale, co );
             co[1] = 1000.0f;
-            v3_add( co, world->scene_geo.bbx[0], co );
+            v3_add( co, world->scene_geometry.bbx[0], co );
 
             ray_hit hit;
             hit.dist = INFINITY;
 
-            if( ray_world( world, co, (v3f){0.0f,-1.0f,0.0f}, &hit, 
-                           k_material_flag_ghosts )){
+            if( ray_world( world, co, (v3f){0.0f,-1.0f,0.0f}, &hit, k_material_flag_ghosts ))
+            {
                struct world_surface *m1 = ray_hit_surface( world, &hit );
-               if((hit.normal[1] > 0.8f) && (m1 == mat) &&
-                  (hit.pos[1] > 0.0f+10.0f)){
-                  world_gen_add_blob( &rand, world, scene, &hit );
+               if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f))
+               {
+                  world_gen_add_blob( &rand, world, builder, &hit );
                   count ++;
                }
             }
@@ -183,27 +157,22 @@ static void world_apply_procedural_foliage( world_instance *world,
 
 #endif
 
-
-
    u64 t1 = SDL_GetPerformanceCounter(),
        utime_blobs = t1-t0,
        ufreq = SDL_GetPerformanceFrequency();
    f64 ftime_blobs = ((f64)utime_blobs / (f64)ufreq)*1000.0;
-
-   vg_info( "%d foliage models added. %f%% (%fms)\n", count, 
-            100.0*((f64)count/(f64)particles), ftime_blobs);
+   vg_info( "%d foliage models added. %f%% (%fms)\n", count, 100.0*((f64)count/(f64)particles), ftime_blobs);
 }
 
-static 
-void world_unpack_submesh_dynamic( world_instance *world,
-                                   scene_context *scene, mdl_submesh *sm ){
-   if( sm->flags & k_submesh_flag_consumed ) return;
+static void world_unpack_submesh_dynamic( world_instance *world, scene_builder_context *builder, mdl_submesh *sm )
+{
+   if( sm->flags & k_submesh_flag_consumed ) 
+      return;
 
    m4x3f identity;
    m4x3_identity( identity );
-   scene_add_mdl_submesh( scene, &world->meta, sm, identity );
-
-   scene_copy_slice( scene, sm );
+   scene_builder_add_model_submesh( builder, &world->meta, sm, identity );
+   scene_builder_get_submesh( builder, sm );
    sm->flags |= k_submesh_flag_consumed;
 }
 
@@ -215,11 +184,9 @@ void world_gen_generate_meshes( world_instance *world )
    /* 
     * Compile meshes into the world scenes
     */
-   u32 geo_max_verts = 320000,
-       geo_max_indices = 1200000;
-   scene_init( &world->scene_geo, geo_max_verts, geo_max_indices );
-   u8 *buffer = vg_stack_allocate( world->stack, scene_mem_required( &world->scene_geo ), 8, "Geometry buffer" );
-   scene_supply_buffer( &world->scene_geo, buffer );
+
+   scene_builder_context geo_ctx;
+   scene_builder_init( &geo_ctx, 320000, 1200000, world->stack );
 
    m4x3f midentity;
    m4x3_identity( midentity );
@@ -234,73 +201,54 @@ void world_gen_generate_meshes( world_instance *world )
    for( u32 i=0; i<world->surface_count; i++ )
    {
       struct world_surface *surf = &world->surfaces[ i ];
-
       if( surf->info.flags & k_material_flag_collision )
-         world_add_all_if_material( midentity, &world->scene_geo, &world->meta, i );
+         world_add_all_if_material( midentity, &geo_ctx, &world->meta, i );
 
-      scene_copy_slice( &world->scene_geo, &surf->sm_geo );
-      scene_set_vertex_flags( &world->scene_geo, 
-                              surf->sm_geo.vertex_start,
-                              surf->sm_geo.vertex_count, 
-                              (u16)(surf->info.flags & 0xffff) );
+      scene_builder_get_submesh( &geo_ctx, &surf->sm_geo );
+      scene_builder_set_vertex_flags( &geo_ctx,
+                                      surf->sm_geo.vertex_start,
+                                      surf->sm_geo.vertex_count, 
+                                      (u16)(surf->info.flags & 0xffff) );
    }
 
-   /* reduce down to minimum size */
-   u32 new_vert_max = world->scene_geo.vertex_count,
-       new_vert_size = vg_align8(new_vert_max*sizeof(scene_vert)),
-       new_indice_len = world->scene_geo.indice_count*sizeof(u32);
-   u32 *src_indices = world->scene_geo.arrindices,
-       *dst_indices = (u32 *)(buffer + new_vert_size);
-   memmove( dst_indices, src_indices, new_indice_len );
-
-   world->scene_geo.max_indices = world->scene_geo.indice_count;
-   world->scene_geo.max_vertices = world->scene_geo.vertex_count;
-   buffer = vg_stack_resize_last( world->stack, scene_mem_required( &world->scene_geo ) );
-
-   world->scene_geo.arrvertices = (scene_vert *)(buffer);
-   world->scene_geo.arrindices = (u32 *)(buffer + new_vert_size);
-
-   /* create a copy for the GPU (bvh scrambles the data) */
-   scene_context *gpu_scene = &world->scene_geo_gpu;
-   vg_async_task *task = scene_alloc_async( gpu_scene, &world->mesh_geo, geo_max_verts, geo_max_indices );
-   memcpy( gpu_scene->arrvertices, world->scene_geo.arrvertices, world->scene_geo.vertex_count*sizeof(scene_vert) );
-   memcpy( gpu_scene->arrindices, world->scene_geo.arrindices, world->scene_geo.indice_count*sizeof(u32) );
-   gpu_scene->vertex_count = world->scene_geo.vertex_count;
-   gpu_scene->indice_count = world->scene_geo.indice_count;
-   box_copy( world->scene_geo.bbx, gpu_scene->bbx );
-   vg_async_task_dispatch( task, async_scene_upload );
+   scene_builder_compact_memory( &geo_ctx, world->stack );
+   scene_builder_save_scene( &geo_ctx, &world->scene_geometry );
+   scene_builder_upload_async( &geo_ctx, &world->main_scene_mesh );
 
    if( !_world.loader_preview_mode )
    {
       vg_info( "creating bvh\n" );
-      world->geo_bh = scene_bh_create( world->stack, &world->scene_geo );
+      // NOTE: destructive to geometry ordering (material/surface indices become garbage)
+      scene_bh_create( &world->scene_geometry, &world->geometry_bh, world->stack );
    }
 
    /*
     * Generate scene: non-collidable geometry
     * ----------------------------------------------------------------
     */
-   vg_info( "Generating non-collidable geometry\n" );
-   vg_async_task *task2 = scene_alloc_async( &world->scene_no_collide, &world->mesh_no_collide, 250000, 500000 );
+
+   u32 temp_frame = _vg_start_temp_frame();
+   scene_builder_context trans_ctx;
+   scene_builder_init( &trans_ctx, 250000, 500000, _vg_temp_stack() );
 
    for( u32 i=0; i<world->surface_count; i++ )
    {
       struct world_surface *surf = &world->surfaces[ i ];
-
       if( !(surf->info.flags & k_material_flag_collision) )
-         world_add_all_if_material( midentity, &world->scene_no_collide, &world->meta, i );
+         world_add_all_if_material( midentity, &trans_ctx, &world->meta, i );
 
       if( !_world.loader_preview_mode )
-      {
          if( surf->info.flags & k_material_flag_grow_grass )
-            world_apply_procedural_foliage( world, &world->scene_no_collide, surf );
-      }
-
-      scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
+            world_apply_procedural_foliage( world, &trans_ctx, surf );
+      scene_builder_get_submesh( &trans_ctx, &surf->sm_no_collide );
    }
 
    if( _world.loader_preview_mode )
-      goto IL_UPLOAD;
+   {
+      scene_builder_upload_async( &trans_ctx, &world->transparent_scene_mesh );
+      _vg_end_temp_frame( temp_frame );
+      return;
+   }
 
    /* unpack traffic models.. TODO: should we just put all these submeshes in a
     * dynamic models list? and then the actual entitities point to the 
@@ -317,7 +265,7 @@ void world_gen_generate_meshes( world_instance *world )
       for( u32 j=0; j<vehc->submesh_count; j++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ vehc->submesh_start+j ];
-         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+         world_unpack_submesh_dynamic( world, &trans_ctx, sm );
          world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_TRAFFIC;
       }
    }
@@ -326,22 +274,21 @@ void world_gen_generate_meshes( world_instance *world )
    for( u32 i=0; i<af_arrcount( &world->ent_objective ); i++ )
    {
       ent_objective *objective = af_arritm( &world->ent_objective, i );
-
       for( u32 j=0; j<objective->submesh_count; j ++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ objective->submesh_start+j ];
-         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+         world_unpack_submesh_dynamic( world, &trans_ctx, sm );
       }
    }
 
    /* unpack region models */
-   for( u32 i=0; i<af_arrcount( &world->ent_region ); i++ ){
+   for( u32 i=0; i<af_arrcount( &world->ent_region ); i++ )
+   {
       ent_region *region = af_arritm( &world->ent_region, i );
-
       for( u32 j=0; j<region->submesh_count; j ++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ region->submesh_start+j ];
-         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+         world_unpack_submesh_dynamic( world, &trans_ctx, sm );
       }
    }
 
@@ -349,12 +296,12 @@ void world_gen_generate_meshes( world_instance *world )
    for( u32 i=0; i<af_arrcount( &world->ent_gate ); i++ )
    {
       ent_gate *gate = af_arritm( &world->ent_gate, i );
-      if( !(gate->flags & k_ent_gate_custom_mesh) ) continue;
-
+      if( !(gate->flags & k_ent_gate_custom_mesh) ) 
+         continue;
       for( u32 j=0; j<gate->submesh_count; j ++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ gate->submesh_start+j ];
-         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+         world_unpack_submesh_dynamic( world, &trans_ctx, sm );
       }
    }
 
@@ -362,30 +309,30 @@ void world_gen_generate_meshes( world_instance *world )
    for( u32 i=0; i<af_arrcount( &world->ent_prop ); i++ )
    {
       ent_prop *prop = af_arritm( &world->ent_prop, i );
-
       for( u32 j=0; j<prop->submesh_count; j ++ )
       {
          mdl_submesh *sm = &world->meta.submeshes[ prop->submesh_start+j ];
          world->surfaces[ sm->material_id ].flags |= WORLD_SURFACE_HAS_PROPS;
-         world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm );
+         world_unpack_submesh_dynamic( world, &trans_ctx, sm );
       }
    }
 
-IL_UPLOAD:
-   vg_async_task_dispatch( task2, async_scene_upload );
+   scene_builder_upload_async( &trans_ctx, &world->transparent_scene_mesh );
+   _vg_end_temp_frame( temp_frame );
+   return;
 }
 
 /* signed distance function for cone */
 static f32 fsd_cone_infinite( v3f p, v2f c )
 {
    v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
-   float s = vg_maxf( 0.0f, v2_dot( q, c ) );
+   f32 s = vg_maxf( 0.0f, v2_dot( q, c ) );
 
    v2f v0;
    v2_muls( c, s, v0 );
    v2_sub( q, v0, v0 );
 
-   float d = v2_length( v0 );
+   f32 d = v2_length( v0 );
    return d * ((q[0]*c[1]-q[1]*c[0]<0.0f)?-1.0f:1.0f);
 }
 
@@ -395,15 +342,13 @@ struct light_indices_upload_info
    v3i count;
    u8 data[];
 };
-static void async_upload_light_indices_task( vg_async_task *task )
+static void async_upload_light_indices_task( struct light_indices_upload_info *in_args, vg_async_info *async )
 {
-   THREAD_0;
-   struct light_indices_upload_info *info = (void *)task->data;
-
-   glGenTextures( 1, &info->world->tex_light_cubes );
-   glBindTexture( GL_TEXTURE_3D, info->world->tex_light_cubes );
-   glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI, info->count[0], info->count[1], info->count[2],
-                 0, GL_RG_INTEGER, GL_UNSIGNED_INT, info->data );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   glGenTextures( 1, &in_args->world->tex_light_cubes );
+   glBindTexture( GL_TEXTURE_3D, in_args->world->tex_light_cubes );
+   glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI, in_args->count[0], in_args->count[1], in_args->count[2],
+                 0, GL_RG_INTEGER, GL_UNSIGNED_INT, in_args->data );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 }
@@ -415,8 +360,8 @@ void world_gen_compute_light_indices( world_instance *world )
 {
    /* light cubes */
    v3f cubes_min, cubes_max;
-   v3_muls( world->scene_geo.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
-   v3_muls( world->scene_geo.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
+   v3_muls( world->scene_geometry.bbx[0], 1.0f/k_world_light_cube_size, cubes_min );
+   v3_muls( world->scene_geometry.bbx[1], 1.0f/k_world_light_cube_size, cubes_max );
 
    v3_sub( cubes_min, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_min );
    v3_add( cubes_max, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_max );
@@ -426,20 +371,21 @@ void world_gen_compute_light_indices( world_instance *world )
 
    v3i icubes_min, icubes_max;
 
-   for( int i=0; i<3; i++ ){
+   for( int i=0; i<3; i++ )
+   {
       icubes_min[i] = cubes_min[i];
       icubes_max[i] = cubes_max[i];
    }
 
    v3f cube_size;
-
    v3i icubes_count;
    v3i_sub( icubes_max, icubes_min, icubes_count );
    
-   for( int i=0; i<3; i++ ){
+   for( int i=0; i<3; i++ )
+   {
       int clamped_count = VG_MIN( 128, icubes_count[i]+1 );
-      float clamped_max = icubes_min[i] + clamped_count,
-                    max = icubes_min[i] + icubes_count[i]+1;
+      f32 clamped_max = icubes_min[i] + clamped_count,
+                  max = icubes_min[i] + icubes_count[i]+1;
 
       icubes_count[i] = clamped_count;
       cube_size[i] = (max / clamped_max) * k_world_light_cube_size;
@@ -449,11 +395,11 @@ void world_gen_compute_light_indices( world_instance *world )
    v3_mul( cubes_min, cube_size, cubes_min );
    v3_mul( cubes_max, cube_size, cubes_max );
 
-   for( int i=0; i<3; i++ ){
-      float range = cubes_max[i]-cubes_min[i];
-      world->ub_lighting.g_cube_inv_range[i] = 1.0f / range;
-      world->ub_lighting.g_cube_inv_range[i] *= (float)icubes_count[i];
-
+   for( int i=0; i<3; i++ )
+   {
+      f32 range = cubes_max[i]-cubes_min[i];
+      world_render.ub_lighting.g_cube_inv_range[i] = 1.0f / range;
+      world_render.ub_lighting.g_cube_inv_range[i] *= (f32)icubes_count[i];
       vg_info( "cubes[%d]: %d\n", i, icubes_count[i] );
    }
 
@@ -461,21 +407,20 @@ void world_gen_compute_light_indices( world_instance *world )
 
    u32 data_size = total_cubes*sizeof(u32)*2;
 
-   vg_async_task *task = 
-      vg_allocate_async_task( &vg.main_tasks, sizeof(struct light_indices_upload_info) + data_size, 1 );
-   struct light_indices_upload_info *info = (void *)task->data;
-   info->world = world;
-   u32 *cubes_index = (void *)info->data;
+   struct light_indices_upload_info *out_args = 
+      _vg_async_alloc( VG_THREAD_MAIN_ID, sizeof(struct light_indices_upload_info) + data_size );
+   out_args->world = world;
+   u32 *cubes_index = (void *)out_args->data;
 
    for( int i=0; i<3; i++ )
-      info->count[i] = icubes_count[i];
+      out_args->count[i] = icubes_count[i];
                                        
    vg_info( "Computing light cubes (%d) [%f %f %f] -> [%f %f %f]\n", 
              total_cubes, cubes_min[0], -cubes_min[2], cubes_min[1],
                           cubes_max[0], -cubes_max[2], cubes_max[1] );
-   v3_copy( cubes_min, world->ub_lighting.g_cube_min );
+   v3_copy( cubes_min, world_render.ub_lighting.g_cube_min );
 
-   float bound_radius = v3_length( cube_size );
+   f32 bound_radius = v3_length( cube_size );
 
    for( int iz = 0; iz<icubes_count[2]; iz ++ )
    {
@@ -484,14 +429,11 @@ void world_gen_compute_light_indices( world_instance *world )
          for( int ix = 0; ix<icubes_count[0]; ix++ )
          {
             boxf bbx;
-            v3_div( (v3f){ ix, iy, iz }, world->ub_lighting.g_cube_inv_range, 
-                  bbx[0] );
-            v3_div( (v3f){ ix+1, iy+1, iz+1 }, 
-                  world->ub_lighting.g_cube_inv_range, 
-                  bbx[1] );
+            v3_div( (v3f){ ix, iy, iz }, world_render.ub_lighting.g_cube_inv_range, bbx[0] );
+            v3_div( (v3f){ ix+1, iy+1, iz+1 }, world_render.ub_lighting.g_cube_inv_range, bbx[1] );
 
-            v3_add( bbx[0], world->ub_lighting.g_cube_min, bbx[0] );
-            v3_add( bbx[1], world->ub_lighting.g_cube_min, bbx[1] );
+            v3_add( bbx[0], world_render.ub_lighting.g_cube_min, bbx[0] );
+            v3_add( bbx[1], world_render.ub_lighting.g_cube_min, bbx[1] );
 
             v3f center;
             v3_add( bbx[0], bbx[1], center );
@@ -500,7 +442,7 @@ void world_gen_compute_light_indices( world_instance *world )
             u32 indices[6] = { 0, 0, 0, 0, 0, 0 };
             u32 count = 0;
 
-            float influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+            f32 influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
             const int N = VG_ARRAY_LEN( influences );
 
             for( u32 j=0; j<af_arrcount(&world->ent_light); j ++ )
@@ -522,8 +464,7 @@ void world_gen_compute_light_indices( world_instance *world )
                   v3f local;
                   m4x3_mulv( light->inverse_world, center, local );
 
-                  float r = fsd_cone_infinite( local, light->angle_sin_cos );
-
+                  f32 r = fsd_cone_infinite( local, light->angle_sin_cos );
                   if( r > bound_radius )
                      continue;
                }
@@ -572,18 +513,17 @@ void world_gen_compute_light_indices( world_instance *world )
       }
    }
 
-   vg_async_task_dispatch( task, async_upload_light_indices_task );
+   _vg_async_send( out_args, (vg_async_fn)async_upload_light_indices_task );
 }
 
 /*
  * Rendering pass needed to complete the world
  */
-void async_world_postprocess( void *userdata )
+void async_world_postprocess( void *_, vg_async_info *async )
 {
    /* create scene lighting buffer */
-   world_instance *world = userdata;
-
-   u32 size = VG_MAX(af_arrcount(&world->ent_light),1) * sizeof(float)*12;
+   world_instance *world = _world.loader_instance;
+   u32 size = VG_MAX(af_arrcount(&world->ent_light),1) * sizeof(f32)*12;
    vg_info( "Upload %ubytes (lighting)\n", size );
 
    glGenBuffers( 1, &world->tbo_light_entities );
@@ -610,8 +550,8 @@ void async_world_postprocess( void *userdata )
       if( !light->daytime )
       {
          u32 hash = (i * 29986577u) & 0xffu;
-         float switch_on = hash;
-               switch_on *= (1.0f/255.0f);
+         f32 switch_on = hash;
+             switch_on *= (1.0f/255.0f);
 
          light_dst[i*3+0][3] = 0.44f + switch_on * 0.015f;
       }
@@ -633,16 +573,16 @@ void async_world_postprocess( void *userdata )
 
    /* Upload lighting uniform buffer */
    if( world->water.enabled )
-      v4_copy( world->water.plane, world->ub_lighting.g_water_plane );
+      v4_copy( world->water.plane, world_render.ub_lighting.g_water_plane );
 
    v4f info_vec;
-   v3f *bounds = world->scene_geo.bbx;
+   v3f *bounds = world->scene_geometry.bbx;
 
    info_vec[0] = bounds[0][0];
    info_vec[1] = bounds[0][2];
    info_vec[2] = 1.0f/ (bounds[1][0]-bounds[0][0]);
    info_vec[3] = 1.0f/ (bounds[1][2]-bounds[0][2]);
-   v4_copy( info_vec, world->ub_lighting.g_depth_bounds );
+   v4_copy( info_vec, world_render.ub_lighting.g_depth_bounds );
 
    /* 
     * Rendering the depth map
@@ -650,14 +590,14 @@ void async_world_postprocess( void *userdata )
    vg_camera ortho;
 
    v3f extent;
-   v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], extent );
+   v3_sub( world->scene_geometry.bbx[1], world->scene_geometry.bbx[0], extent );
 
-   float fl = world->scene_geo.bbx[0][0],
-         fr = world->scene_geo.bbx[1][0],
-         fb = world->scene_geo.bbx[0][2],
-         ft = world->scene_geo.bbx[1][2],
-         rl = 1.0f / (fr-fl),
-         tb = 1.0f / (ft-fb);
+   f32 fl = world->scene_geometry.bbx[0][0],
+       fr = world->scene_geometry.bbx[1][0],
+       fb = world->scene_geometry.bbx[0][2],
+       ft = world->scene_geometry.bbx[1][2],
+       rl = 1.0f / (fr-fl),
+       tb = 1.0f / (ft-fb);
 
    m4x4_zero( ortho.mtx.p );
    ortho.mtx.p[0][0] = 2.0f * rl;
@@ -672,7 +612,7 @@ void async_world_postprocess( void *userdata )
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    glDisable(GL_CULL_FACE);
-   vg_framebuffer_bind( world->heightmap, 1.0f );
+   vg_framebuffer_bind( world_render.heightmap, 1.0f );
    shader_blitcolour_use();
    shader_blitcolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
    render_fsquad();
@@ -687,8 +627,8 @@ void async_world_postprocess( void *userdata )
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
 
    /* upload full buffer */
-   glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world->ub_lighting );
+   glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
 
    /*
     * Allocate cubemaps
@@ -731,38 +671,7 @@ void async_world_postprocess( void *userdata )
 /* Loads textures from the pack file */
 void world_gen_load_surfaces( world_instance *world )
 {
-   THREAD_1;
-   if( _world.loader_preview_mode )
-   {
-      world->texture_count = 0;
-   }
-   else
-   {
-      vg_info( "Loading textures\n" );
-      world->texture_count = world->meta.texture_count+1;
-      world->textures = vg_stack_allocate( world->stack, sizeof(GLuint)*world->texture_count, 8, "Textures" );
-      world->textures[0] = vg.tex_missing;
-
-      for( u32 i=0; i<world->meta.texture_count; i++ )
-      {
-         mdl_texture *tex = &world->meta.textures[ i ];
-
-         if( !tex->file.pack_size )
-         {
-            vg_fatal_error( "World models must have packed textures!" );
-         }
-
-         vg_stack_clear( &vg.scratch );
-         void *src_data = vg_stack_allocate( &vg.scratch, tex->file.pack_size, 8, "Pack Data" );
-         mdl_fread_pack_file( &world->meta, &tex->file, src_data );
-
-         vg_tex2d_load_qoi_async( src_data, tex->file.pack_size,
-                                  VG_TEX2D_NEAREST|VG_TEX2D_REPEAT,
-                                  &world->textures[i+1] );
-      }
-   }
-
-   vg_info( "Loading materials\n" );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
 
    world->surface_count = world->meta.material_count+1;
    world->surfaces = vg_stack_allocate( world->stack, sizeof(struct world_surface)*world->surface_count, 8, "Surfaces" );
@@ -778,16 +687,10 @@ void world_gen_load_surfaces( world_instance *world )
       surf->flags = 0;
 
       if( surf->info.shader == k_shader_water )
-      {
-         struct shader_props_water *props = surf->info.props.compiled;
-         world->ub_lighting.g_water_fog = props->fog_scale;
-      }
+         world_render.ub_lighting.g_water_fog = world->meta.shader_props[i].water.fog_scale;
 
       if( surf->info.shader == k_shader_standard_cutout || surf->info.shader == k_shader_foliage )
-      {
-         struct shader_props_standard *props = surf->info.props.compiled;
-         surf->alpha_tex = props->tex_diffuse;
-      }
+         surf->alpha_tex = world->meta.shader_props[i].standard.tex_diffuse;
       else
          surf->alpha_tex = 0;
    }
index 8e65780fa1af85aff6623ea3a782cd22f149d907..49e328389052904930000a250d1c5e8f4c68dd2c 100644 (file)
@@ -1,15 +1,11 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- *
- * World generation/population. Different to regular loading, since it needs to
- * create geometry, apply procedural stuff and save that image to files etc.
- */
-
-#pragma once
-#include "world.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_gen.c"
+#else
 
 void world_init_blank( world_instance *world );
 void world_gen_load_surfaces( world_instance *world );
 void world_gen_generate_meshes( world_instance *world );
 void world_gen_compute_light_indices( world_instance *world );
-void async_world_postprocess( void *userdata );
+void async_world_postprocess( void *_, vg_async_info *async );
+
+#endif
index 3b29b1fedf60a82c7d215059158c57c6daf0060a..ba0fecc2d0f239be396e51cc5c4b902bbc56bb48 100644 (file)
@@ -1,12 +1,5 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef WORLD_INFO_H
-#define WORLD_INFO_H
-
-/* Purely an information header, shares common strings across client and 
- * server programs. */
+#if defined( SR_IMPLEMENTATION )
+#else
 
 struct track_info
 {
index 01890c38c1bf2f37507a3a20cbcea25b7509bf60..5abdace3a79feca57706ca86319f79bf02c5b86a 100644 (file)
@@ -1,56 +1,41 @@
-#include "world_load.h"
-#include "world_routes.h"
-#include "world_gate.h"
-#include "ent_skateshop.h"
-#include "addon.h"
-#include "save.h"
-#include "vg/vg_msg.h"
-#include "network.h"
-#include "player_remote.h"
-#include "vg/vg_loader.h"
-#include "vg/vg_io.h"
-#include <string.h>
-#include "ent_atom.h"
-
 /* 
  * load the .mdl file located in path as a world instance
  */
 static void world_instance_load_mdl( world_instance *world, const char *path, vg_stack_allocator *stack )
 {
-   vg_loader_set_user_information( "Loading world data" );
+   _vg_loader_set_user_information( "Loading world data" );
    world_init_blank( world );
    world->stack = stack;
    
    vg_info( "Loading world model: %s\n", path );
 
-   mdl_context *meta = &world->meta;
-   array_file_context *af = &meta->af;
-
-   mdl_open( meta, path, world->stack );
-   mdl_load_metadata_block( meta, world->stack );
-   mdl_load_mesh_block( meta, world->stack );
+   vg_model_stream_context ctx;
+   vg_model_stream_open( &ctx, &world->meta, path );
+   vg_model_stream_metadata( &ctx, stack );
+   vg_model_stream_meshes_cpu( &ctx, stack ); // NOTE: Maybe this can go in temp storage now.
+   
+   if( !_world.loader_preview_mode )
+      vg_model_stream_textures_gpu( &ctx );
 
    bool load_all = !_world.loader_preview_mode;
-
    if( load_all )
    {
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_gate,      ent_gate,   stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_camera,    ent_camera, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_gate,   ent_gate,   stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_camera, ent_camera, stack );
 
 #if (MDL_VERSION_MIN <= 107)
-      if( meta->version <= 107 )
+      if( world->meta.version <= 107 )
       {
+         u32 temp_frame = _vg_start_temp_frame();
          array_file_ptr legacy_cameras;
-         af_load_array( af, &legacy_cameras, "ent_camera", &vg.scratch, sizeof(struct ent_camera_v107) );
-
+         af_load_array( &ctx.af, &legacy_cameras, "ent_camera", _vg_temp_stack(), sizeof(struct ent_camera_v107) );
          for( u32 i=0; i<af_arrcount(&legacy_cameras); i ++ )
-         {
             fix_ent_camera_v107( af_arritm( &legacy_cameras, i ), af_arritm( &world->ent_camera, i ) );
-         }
+         _vg_end_temp_frame( temp_frame );
       }
 #endif
 
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_spawn,     ent_spawn,      stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_spawn, ent_spawn, stack );
 
       if( af_arrcount( &world->ent_spawn ) == 0 )
       {
@@ -84,70 +69,68 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vg
          }
       }
 
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_light,     ent_light,      stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_route_node,ent_route_node, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_path_index,ent_path_index, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_checkpoint,ent_checkpoint, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_light,     ent_light,      stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_route_node,ent_route_node, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_path_index,ent_path_index, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_checkpoint,ent_checkpoint, stack );
    }
 
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_route,     ent_route,      stack );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_region,    ent_region,     stack );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_route,     ent_route,      stack );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_region,    ent_region,     stack );
 
    if( load_all )
    {
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_water,     ent_water,      stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio_clip,ent_audio_clip, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio,     ent_audio,      stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_volume,    ent_volume,     stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_traffic,   ent_traffic,    stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_marker,    ent_marker,     stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_skateshop, ent_skateshop,  stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_swspreview,ent_swspreview, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_ccmd,      ent_ccmd,       stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_objective, ent_objective,  stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_challenge, ent_challenge,  stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_cubemap,   ent_cubemap,    stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_prop,      ent_prop,       stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_glider,    ent_glider,     stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_list,      ent_list,       stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->file_entity_ref, file_entity_ref, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_script, ent_script, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_event,     ent_event, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_npc,       ent_npc, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_atom,      ent_atom, stack );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_cutscene,  ent_cutscene, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_water,     ent_water,      stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_audio_clip,ent_audio_clip, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_audio,     ent_audio,      stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_volume,    ent_volume,     stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_traffic,   ent_traffic,    stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_marker,    ent_marker,     stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_skateshop, ent_skateshop,  stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_swspreview,ent_swspreview, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_ccmd,      ent_ccmd,       stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_objective, ent_objective,  stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_challenge, ent_challenge,  stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_cubemap,   ent_cubemap,    stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_prop,      ent_prop,       stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_glider,    ent_glider,     stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_list,      ent_list,       stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->file_entity_ref, file_entity_ref, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_script, ent_script, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_event,     ent_event, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_npc,       ent_npc, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_atom,      ent_atom, stack );
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &world->ent_cutscene,  ent_cutscene, stack );
    }
 
-   array_file_ptr infos;
-   AF_LOAD_ARRAY_STRUCT( af, &infos, ent_worldinfo, &vg.scratch );
-
-   world->skybox = k_skybox_default;
-   if( af_arrcount(&infos) )
+   u32 temp_frame = _vg_start_temp_frame();
    {
-      world->info = *((ent_worldinfo *)af_arritm(&infos,0));
+      array_file_ptr infos;
+      AF_LOAD_ARRAY_STRUCT( &ctx.af, &infos, ent_worldinfo, _vg_temp_stack() );
 
-      if( world->meta.version >= 104 )
+      world->skybox = k_skybox_default;
+      if( af_arrcount(&infos) )
       {
-         if( AF_STR_EQ( &world->meta.af, world->info.pstr_skybox, "space" ))
-         {
-            world->skybox = k_skybox_space;
-         }
-      }
+         world->info = *((ent_worldinfo *)af_arritm(&infos,0));
+         if( world->meta.version >= 104 )
+            if( AF_STR_EQ( world->meta.packed_strings, world->info.pstr_skybox, "space" ))
+               world->skybox = k_skybox_space;
 
-      if( world->meta.version < 108 )
-         world->info.wind_scale = 0.5f;
-   }
-   else
-   {
-      world->info.pstr_author = 0;
-      world->info.pstr_desc = 0;
-      world->info.pstr_name = 0;
-      world->info.timezone = 0.0f;
-      world->info.flags = 0;
+         if( world->meta.version < 108 )
+            world->info.wind_scale = 0.5f;
+      }
+      else
+      {
+         world->info.pstr_author = 0;
+         world->info.pstr_desc = 0;
+         world->info.pstr_name = 0;
+         world->info.timezone = 0.0f;
+         world->info.flags = 0;
+      }
    }
+   _vg_end_temp_frame( temp_frame );
 
-   vg_loader_set_user_information( "Compiling world details" );
-
+   _vg_loader_set_user_information( "Compiling world details" );
    time_t seconds = time(NULL) % ((u32)vg_maxf(1.0f,k_day_length)*60);
    world->time  = ((f64)(seconds)/(k_day_length*60.0));
    world->time += (world->info.timezone/24.0);
@@ -160,9 +143,11 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vg
    if( load_all )
    {
       world_gen_routes_ent_init( world );
-      world_gen_entities_init( world );
+      world_gen_entities_init( world, &ctx );
    }
 
+   vg_model_stream_close( &ctx );
+
    u64 t6 = SDL_GetPerformanceCounter();
    
    /* main bulk */
@@ -179,7 +164,6 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vg
       world_gen_compute_light_indices( world );
 
    u64 t3 = SDL_GetPerformanceCounter();
-   mdl_close( meta );
 
    u64 utime_mesh = t1-t0,
        utime_route = t2-t1,
@@ -215,32 +199,24 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vg
       world->routes_ui = vg_stack_allocate( stack, sizeof(struct route_ui)*af_arrcount(&world->ent_route), 8, "Route UI buffer" );
       ent_script_alloc( world, stack );
 
-      vg_loader_set_user_information( "Postprocessing world" );
-      vg_async_call( &vg.main_tasks, async_world_postprocess, world );
+      _vg_loader_set_user_information( "Postprocessing world" );
+      _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_postprocess );
    }
 }
 
 static void async_world_loader_done( void *userdata )
 {
-   THREAD_0;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
    _world.loader_state = k_world_loader_init;
    _world.loader_instance->complete = 1;
 }
-
-struct world_load_info
-{
-   bool OK;
-   char path[4096];
-};
-void skaterift_world_load_t1( vg_async_task *task )
+void skaterift_world_load_t1( struct world_load_info *in_args, vg_async_info *async )
 {
-   THREAD_1;
-   struct world_load_info *info = (void *)task->data;
-
-   if( !info->OK )
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   if( !in_args->OK )
       return;
 
-   vg_loader_set_user_information( "Scanning world directory" );
+   _vg_loader_set_user_information( "Scanning world directory" );
 
    addon_reg *reg = addon_details( _world.load_addon );
    _world.loader_instance->addon_id = _world.load_addon;
@@ -252,7 +228,7 @@ void skaterift_world_load_t1( vg_async_task *task )
    char path_buf[ 4096 ];
    vg_str path;
    vg_strnull( &path, path_buf, sizeof( path_buf ) );
-   vg_strcat( &path, info->path );
+   vg_strcat( &path, in_args->path );
    
    vg_str folder = path;
    if( !vg_strgood( &folder ) ) 
@@ -328,25 +304,27 @@ void skaterift_world_load_t1( vg_async_task *task )
    }
 
    world_instance_load_mdl( _world.loader_instance, mdl_path, _world.loader_stack );
-   vg_async_call( &vg.main_tasks, async_world_loader_done, NULL );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_MAIN_ID, 0 ), (vg_async_fn)async_world_loader_done );
 }
 
 struct world_savedata_info
 {
-   savedata_file save;
+   //savedata_file save;
    world_instance *instance;
 };
 
-void async_worldsave_go( vg_async_task *task )
+void async_worldsave_go( struct world_savedata_info *in_args, vg_async_info *async )
 {
-   THREAD_0;
-   struct world_savedata_info *info = (void *)task->data;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   VG_ASSERT( 0 );
 
-   vg_msg sav;
-   vg_msg_init( &sav, info->save.buf, info->save.msg.max );
+   // FIXME FIXME FIXME
+   
+#if 0
+   struct world_savedata_info *info = (void *)task->data;
 
    /* start entities in the world */
-   world_entity_start( info->instance, &sav );
+   world_entity_start( info->instance, &info->save.kvs );
 
    /* start player in the world */
    if( _world.travelled_through_nonlocal_gate )
@@ -358,12 +336,11 @@ void async_worldsave_go( vg_async_task *task )
    else
    {
       bool restored_player_position = 0;
-
-      vg_msg_init( &sav, info->save.buf, info->save.msg.max );
-      vg_msg player_frame = sav;
-      if( vg_msg_seekframe( &player_frame, "player" ) )
+      
+      u32 player_block = vg_kv_find( &info->save.kvs, 0, "player" );
+      if( player_block )
       {
-         if( vg_msg_getkvvecf( &player_frame, "co", k_vg_msg_v3f, localplayer.rb.co, NULL ) )
+         if( vg_kv_read_vf32( &info->save.kvs, player_block, "co", NULL, localplayer.rb.co, 3 ) )
             restored_player_position = 1;
       }
 
@@ -376,18 +353,21 @@ void async_worldsave_go( vg_async_task *task )
    network_send_item( k_netmsg_playeritem_world0 );
    _world.loader_state = k_world_loader_done;
    _world.load_addon = 0;
-   _vg_tower_set_flag( skaterift.sig_world, 1 );
    menu_on_world_change( _world.main.addon_id );
    relink_all_remote_player_worlds();
 
    vg_audio_lock();
    vg_audio_oneshot( &audio_ui[2], 1.0f, 0.0f, 0, 0 );
    vg_audio_unlock();
+#endif
 }
 
-void load_world_savedata_t1( void *userdata )
+void load_world_savedata_t1( void *_, vg_async_info *async )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+   VG_ASSERT( 0 );
+   // FIXME FIXME
+#if 0
    vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct world_savedata_info), 1 );
    struct world_savedata_info *info = (void *)task->data;
 
@@ -396,6 +376,7 @@ void load_world_savedata_t1( void *userdata )
    addon_make_savedata_path( _world.load_addon, info->save.path );
    savedata_file_read( &info->save );
    vg_async_task_dispatch( task, async_worldsave_go );
+#endif
 }
 
 void world_switcher_update(void)
@@ -405,9 +386,11 @@ void world_switcher_update(void)
 
    if( _world.loader_state == k_world_loader_saving_current )
    {
-      skaterift_write_all_savedata(1);
+      VG_ASSERT(0);
+      //FIXME FIXME FIMXE
+      //skaterift_write_all_savedata(1);
       _world.loader_state = k_world_loader_unloading_current;
-      vg_loader_set_user_information( "Unloading current world" );
+      _vg_loader_set_user_information( "Unloading current world" );
    }
 
    /* pre-load step aka waiting for audio to end. */
@@ -425,19 +408,19 @@ void world_switcher_update(void)
       world_instance_free_graphics_data( &_world.main );
       _world.main.complete = 0;
       _world.loader_state = k_world_loader_ready;
-      vg_loader_set_user_information( "Waiting for loading thread" );
+      _vg_loader_set_user_information( "Waiting for loading thread" );
    }
 
    if( _world.loader_state == k_world_loader_ready )
    {
       _world.loader_state = k_world_loader_loading;
       vg_stack_clear( _world.loader_stack );
-      vg_async_task *task = vg_allocate_async_task( &vg.loader_tasks, sizeof(struct world_load_info), 1 );
-      struct world_load_info *info = (void *)task->data;
+      
+      struct world_load_info *out_args = _vg_async_alloc( VG_THREAD_ASYNC_ID, sizeof(struct world_load_info) );
       vg_str folder_str;
-      vg_strnull( &folder_str, info->path, sizeof(info->path) );
-      info->OK = addon_get_content_folder( _world.load_addon, &folder_str );
-      vg_async_task_dispatch( task, skaterift_world_load_t1 );
+      vg_strnull( &folder_str, out_args->path, sizeof(out_args->path) );
+      out_args->OK = addon_get_content_folder( _world.load_addon, &folder_str );
+      _vg_async_send( out_args, (vg_async_fn)skaterift_world_load_t1 );
    }
 
    if( _world.loader_state == k_world_loader_init )
@@ -450,19 +433,13 @@ void world_switcher_update(void)
       else
       {
          _world.loader_state = k_world_loader_load_savedata;
-         vg_async_call( &vg.loader_tasks, load_world_savedata_t1, NULL );
+         _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)load_world_savedata_t1 );
       }
    }
 }
 
 void skaterift_load_world_start( addon_id addon_id, bool preview )
 {
-   if( !_vg_tower_clearence( skaterift.full_ready_mask ) )
-   {
-      vg_error( "Cannot start changeworld while client is not ready?\n" );
-      return;
-   }
-
    if( _world.loader_state != k_world_loader_done )
    {
       vg_error( "Cannot start changeworld while loader is not done?\n" );
@@ -487,14 +464,13 @@ void skaterift_load_world_start( addon_id addon_id, bool preview )
       if( addon_id != world->addon_id )
          _world.previous_world_addon = _world.main.addon_id;
 
-      _vg_tower_set_flag( skaterift.sig_world, 0 );
       _replay2_clear_local_buffer();
       _world.loader_state = k_world_loader_saving_current;
       _world.event = k_world_event_none;
       player__clear_world_dependent_variables();
       relink_all_remote_player_worlds();
       _ent_npc_reset();
-      vg_loader_set_user_information( "Saving current world" );
+      _vg_loader_set_user_information( "Saving current world" );
    }
    else
       _world.loader_state = k_world_loader_ready;
@@ -502,7 +478,6 @@ void skaterift_load_world_start( addon_id addon_id, bool preview )
    char uid[ADDON_UID_MAX];
    addon_make_uid( addon_id, uid );
    vg_info( "loading world: %s %s\n", uid, preview? "(preview mode)": "" );
-   vg_stack_clear( &vg.scratch ); /* ?? */
 
    if( preview )
    {
@@ -524,7 +499,7 @@ void skaterift_load_world_start( addon_id addon_id, bool preview )
    }
 
    _world.loader_instance = world;
-   _world.loader_stack = preview? _world.preview_stack: _world.stack;
+   _world.loader_stack = preview? &_world.preview_stack:& _world.stack;
    _world.loader_preview_mode = preview;
    _world_loader_set_addon( addon_id );
 }
@@ -572,7 +547,7 @@ int skaterift_load_world_command( int argc, const char *argv[] )
          if( addon_id )
          {
             bool allowed = 1;
-            if( g_client.demo_mode )
+            if( _is_running_demo() )
             {
                addon_reg *reg = addon_details( addon_id );
                if( reg )
@@ -616,17 +591,16 @@ int skaterift_load_world_command( int argc, const char *argv[] )
 void world_instance_free_graphics_data( world_instance *world )
 {
    /* free meshes */
-   mesh_free( &world->mesh_route_lines );
-   mesh_free( &world->mesh_geo );
-   mesh_free( &world->mesh_no_collide );
+   scene_mesh_free( &world->main_scene_mesh );
+   scene_mesh_free( &world->line_scene_mesh );
+   scene_mesh_free( &world->transparent_scene_mesh );
    
    glDeleteBuffers( 1, &world->tbo_light_entities );
    glDeleteTextures( 1, &world->tex_light_entities );
    glDeleteTextures( 1, &world->tex_light_cubes );
 
    /* delete textures and meshes */
-   if( world->texture_count )
-      glDeleteTextures( world->texture_count-1, world->textures+1 );
+   vg_model_unload_gpu( &world->meta );
 
    for( u32 i=0; i<af_arrcount(&world->ent_cubemap); i++ )
    {
@@ -636,8 +610,8 @@ void world_instance_free_graphics_data( world_instance *world )
       glDeleteRenderbuffers( 1, &cm->renderbuffer_id );
    }
 
-   if( world->nonlocal_gate_count )
-      glDeleteTextures( world->nonlocal_gate_count, world->nonlocal_gates_cubemaps );
+   for( u32 i=0; i<world->nonlocal_gate_count; i ++ )
+      vg_tex_delete( &world->nonlocal_gates_cubemaps[i] );
 }
 
 /* 
@@ -646,15 +620,9 @@ void world_instance_free_graphics_data( world_instance *world )
  */
 void world_init_blank( world_instance *world )
 {
-   memset( &world->meta, 0, sizeof(mdl_context) );
-
-   world->textures = NULL;
-   world->texture_count = 0;
+   vg_zero_mem( &world->meta, sizeof(vg_model) );
    world->surfaces = NULL;
    world->surface_count = 0;
-
-   world->geo_bh = NULL;
-   world->entity_bh = NULL;
    world->entity_list = NULL;
    world->rendering_gate = NULL;
 
@@ -663,7 +631,7 @@ void world_init_blank( world_instance *world )
 
    /* default lighting conditions 
     * -------------------------------------------------------------*/
-   struct ub_world_lighting *state = &world->ub_lighting;
+   struct ub_world_lighting *state = &world_render.ub_lighting;
 
    state->g_light_preview = 0;
    state->g_shadow_samples = 8;
index 76f98136773d54563501da46935614b95a03d432..6c5bacfe8f954526b8cc275d8fd9abd5e88663d3 100644 (file)
@@ -1,8 +1,6 @@
-#pragma once
-#include <time.h>
-
-#include "world.h"
-#include "addon.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_load.c"
+#else
 
 int skaterift_load_world_command( int argc, const char *argv[] );
 void skaterift_load_world_start( addon_id addon, bool preview_mode );
@@ -10,4 +8,12 @@ void _world_loader_set_addon( addon_id addon );
 void world_switcher_update(void);
 void world_instance_free_graphics_data( world_instance *world );
 vg_async_task *world_load_go(void);
-void skaterift_world_load_t1( vg_async_task *task );
+
+struct world_load_info
+{
+   bool OK;
+   char path[4096];
+};
+void skaterift_world_load_t1( struct world_load_info *in_args, vg_async_info *async );
+
+#endif
index 7e9f5bca4906f13597c867e92937b56a97bf326a..fb32d7878df5c91ff9ddf4d032c84b91231bc0f4 100644 (file)
@@ -1,12 +1,3 @@
-#include "skaterift.h"
-#include "world_map.h"
-#include "world.h"
-#include "input.h"
-#include "gui.h"
-#include "menu.h"
-#include "scene.h"
-#include "shaders/model_superworld.h"
-
 struct world_map world_map;
 
 static void world_map_get_dir( v3f dir )
@@ -63,7 +54,7 @@ static void respawn_map_draw_icon( vg_camera *cam, enum gui_icon icon, v3f pos,
 void world_map_initialize_view(void)
 {
    world_instance *world = &_world.main;
-   v3f *bbx = world->scene_geo.bbx;
+   v3f *bbx = world->scene_geometry.bbx;
 
    respawn_world_to_plane_pos( localplayer.rb.co, world_map.plane_pos );
    world_map.boom_dist = 400.0f;
@@ -98,7 +89,7 @@ static void world_map_update_final_camera( vg_camera *cam )
    }
    vg_camera_update_transform( &world_map.final_cam );
    vg_camera_update_view( &world_map.final_cam );
-   vg_camera_update_projection( &world_map.final_cam, vg.window_x, vg.window_y );
+   vg_camera_update_projection( &world_map.final_cam, _vg_window.w, _vg_window.h );
    vg_camera_finalize( &world_map.final_cam );
    vg_camera_finalize( &world_map.final_cam );
 }
@@ -194,11 +185,11 @@ void render_world_map(void)
       glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
       
       v3f bg;
-      v3_muls( world->ub_lighting.g_daysky_colour,
-                  world->ub_lighting.g_day_phase - world->ub_lighting.g_sunset_phase*0.1f, bg );
+      v3_muls( world_render.ub_lighting.g_daysky_colour,
+               world_render.ub_lighting.g_day_phase - world_render.ub_lighting.g_sunset_phase*0.1f, bg );
 
-      v3_muladds( bg, world->ub_lighting.g_sunset_colour, (1.0f-0.5f)*world->ub_lighting.g_sunset_phase, bg );
-      v3_muladds( bg, world->ub_lighting.g_nightsky_colour, (1.0f-world->ub_lighting.g_day_phase), bg );
+      v3_muladds( bg, world_render.ub_lighting.g_sunset_colour, (1.0f-0.5f)*world_render.ub_lighting.g_sunset_phase, bg );
+      v3_muladds( bg, world_render.ub_lighting.g_nightsky_colour, (1.0f-world_render.ub_lighting.g_day_phase), bg );
 
       glClearColor( bg[0], bg[1], bg[2], 0.0f );
       glClear( GL_COLOR_BUFFER_BIT );
@@ -349,7 +340,7 @@ void render_world_map(void)
          v3_normalize(dir);
 
          v3f centroid;
-         v3_add( world->scene_geo.bbx[0], world->scene_geo.bbx[1], centroid );
+         v3_add( world->scene_geometry.bbx[0], world->scene_geometry.bbx[1], centroid );
          v3_muls( centroid, 0.5f, centroid );
          v3_muladds( centroid, dir, 900.0f, cam.pos );
 
@@ -367,7 +358,7 @@ void render_world_map(void)
          v3_angles( dir, cam.angles );
          v3f v0, v1;
          v3_sub( centroid, cam.pos, v0 );
-         v3_sub( world->scene_geo.bbx[1], cam.pos, v1 );
+         v3_sub( world->scene_geometry.bbx[1], cam.pos, v1 );
          v3_normalize( v0 );
          v3_normalize( v1 );
 
@@ -418,12 +409,11 @@ void render_world_map(void)
       shader_model_superworld_uColour( (v4f){0.4f,0.8f,0.0f,0.0f} );
       shader_model_superworld_uTime( vg.time*0.25f );
 
-      mesh_bind( &world_map.superworld_mesh );
-      mdl_context *model = &world_map.superworld_meta;
+      vg_model *model = &world_map.superworld_meta;
+      vg_model_bind_mesh( model );
       for( u32 i=0; i<model->mesh_count; i ++ )
       {
          mdl_mesh *mesh = &model->meshes[i];
-
          q_axis_angle( mesh->transform.q, (v3f){0,1,0}, vg.time_real*0.4f );
 
          m4x3f mmdl;
@@ -433,7 +423,7 @@ void render_world_map(void)
          for( u32 j=0; j<mesh->submesh_count; j ++ )
          {
             mdl_submesh *submesh = &model->submeshes[ mesh->submesh_start + j ];
-            mdl_draw_submesh( submesh );
+            vg_model_draw_submesh( submesh );
          }
       }
 
@@ -564,12 +554,12 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
                if( selected_type == k_ent_challenge )
                {
                   ent_challenge *challenge = af_arritm( &world->ent_challenge, selected_index );
-                  name = af_str( &world->meta.af, challenge->pstr_alias );
+                  name = af_str( world->meta.packed_strings, challenge->pstr_alias );
                }
                else if( selected_type == k_ent_route )
                {
                   ent_route *route = af_arritm( &world->ent_route, selected_index );
-                  name = af_str( &world->meta.af, route->pstr_name );
+                  name = af_str( world->meta.packed_strings, route->pstr_name );
                   ent_route_leaderboard_ui( ctx, spawn_box, selected_index );
                }
                ui_text( ctx, name_box, name, 1, k_ui_align_middle_center, 0 );
@@ -591,7 +581,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
       }
       else
       {
-         title_text = af_str( &world->meta.af, world->info.pstr_name );
+         title_text = af_str( world->meta.packed_strings, world->info.pstr_name );
          subtitle_text = "Current Location";
          ctx->font = &vgf_default_title;
          upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
@@ -609,14 +599,14 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
          m2x2_mulv( rm, steer, steer );
          v2_muladds( world_map.plane_pos, steer, vg.time_frame_delta * 200.0f, world_map.plane_pos );
 
-         v3f *bbx = world->scene_geo.bbx;
+         v3f *bbx = world->scene_geometry.bbx;
          v2_minv( (v2f){ bbx[1][0], bbx[1][2] }, world_map.plane_pos, world_map.plane_pos );
          v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, world_map.plane_pos, world_map.plane_pos );
 
          if( vg_input.display_input_method == k_input_method_kbm )
          {
-            world_map.view_centroid[0] =   ((f32)ctx->mouse[0] / (f32)vg.window_x)*2.0f - 1.0f;
-            world_map.view_centroid[1] = -(((f32)ctx->mouse[1] / (f32)vg.window_y)*2.0f - 1.0f);
+            world_map.view_centroid[0] =   ((f32)ctx->mouse[0] / (f32)_vg_window.w)*2.0f - 1.0f;
+            world_map.view_centroid[1] = -(((f32)ctx->mouse[1] / (f32)_vg_window.h)*2.0f - 1.0f);
          }
          else
          {
@@ -687,7 +677,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
                   continue;
                ent_list *list = af_arritm( &world->ent_list, mdl_entity_id_id( list_id ) );
 
-               const char *title = af_str( &world->meta.af, region->pstr_title );
+               const char *title = af_str( world->meta.packed_strings, region->pstr_title );
                ctx->font = &vgf_default_large;
 
                ui_rect title_box;
@@ -745,7 +735,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
 
                      vg_strnull( &str, buf, sizeof(buf) );
                      vg_strcat( &str, "(Race) " );
-                     vg_strcat( &str, af_str( &world->meta.af, route->pstr_name ));
+                     vg_strcat( &str, af_str( world->meta.packed_strings, route->pstr_name ));
 
                      if( route->flags & k_ent_route_flag_achieve_silver )
                         vg_strcat( &str, " \xb3");
@@ -762,7 +752,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
                      else
                      {
                         vg_strnull( &str, buf, sizeof(buf) );
-                        vg_strcat( &str, af_str( &world->meta.af,challenge->pstr_alias));
+                        vg_strcat( &str, af_str( world->meta.packed_strings,challenge->pstr_alias));
 
                         u32 flags = 0x00;
                         if( challenge->status )
@@ -820,7 +810,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
 
 #if 0
       ctx->font = &vgf_default_large;
-      ui_rect title = { vg.window_x/2- 512/2, height+8, 512, 64 };
+      ui_rect title = { _vg_window.w/2- 512/2, height+8, 512, 64 };
 
       ui_px x = 8,
             y = height+8;
@@ -832,7 +822,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
       vg_strnull( &str, buf, sizeof(buf) );
 
       world_instance *world = &_world.main;
-      const char *world_name = af_str( &world->meta.af, world->info.pstr_name );
+      const char *world_name = af_str( world->meta.packed_strings, world->info.pstr_name );
       vg_strnull( &str, buf, sizeof(buf) );
       vg_strcat( &str, world_name );
       
@@ -852,7 +842,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
       vs[3].co[1] = stat_panel[1];
 
       ui_rect back_button = {0,0,300,32};
-      ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, back_button );
+      ui_rect_center( (ui_rect){0,0,_vg_window.w,_vg_window.h}, back_button );
       if( ui_button_text( ctx, back_button, "up", 1 ) == k_ui_button_click )
       {
          world_map.activity = k_map_activity_
@@ -885,7 +875,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
       planet_box[0] += 4;
       planet_box[2] = WORKSHOP_PREVIEW_WIDTH;
       planet_box[3] = WORKSHOP_PREVIEW_HEIGHT;
-      ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].id, 0 );
+      ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].tex, 0 );
 
       ui_rect planet_box_title;
       ui_split( planet_box, k_ui_axis_h, 28, 0, planet_box_title, planet_box );
@@ -1074,7 +1064,7 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
 
          if( menu.clicked_world_id != _world.main.addon_id )
          {
-            if( g_client.demo_mode )
+            if( _is_running_demo() )
             {
                addon_reg *reg = addon_details( menu.clicked_world_id );
                if( reg )
@@ -1119,15 +1109,22 @@ void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *al
    }
 }
 
-void world_map_init(void)
+static void _world_map_load_content_async( void *_, vg_async_info *async )
+{
+   vg_model_stream_context ctx;
+   VG_ASSERT( vg_model_stream_open( &ctx, &world_map.superworld_meta, "models/rs_superworlds.mdl" ) );
+   vg_model_stream_metadata( &ctx, VG_STACK_USE_HEAP );
+   vg_model_stream_meshes_gpu( &ctx, NULL );
+   vg_model_stream_textures_gpu( &ctx );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &world_map.ent_camera, ent_camera, NULL );
+   AF_LOAD_ARRAY_STRUCT( &ctx.af, &world_map.ent_marker, ent_marker, NULL );
+   vg_model_stream_close( &ctx );
+}
+
+VG_API void _world_map_init(void)
 {
-   mdl_context *model = &world_map.superworld_meta;
-   mdl_open( model, "models/rs_superworlds.mdl", &vg.rtmem );
-   mdl_load_metadata_block( model, &vg.rtmem );
-   mdl_async_load_glmesh( model, &world_map.superworld_mesh, NULL );
-   AF_LOAD_ARRAY_STRUCT( &model->af, &world_map.ent_camera, ent_camera, &vg.rtmem );
-   AF_LOAD_ARRAY_STRUCT( &model->af, &world_map.ent_marker, ent_marker, &vg.rtmem );
-   mdl_close( model );
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_map_load_content_async );
 
    world_map.superworld_cam.nearz = 0.1f;
    world_map.superworld_cam.farz = 250.0f;
index 41d7fd8304ad89cadc6d50a082de33f3a87e513a..77a6a421d85745813c18eaf5d4a41a2fbf41310a 100644 (file)
@@ -1,7 +1,7 @@
-#pragma once
-#include "vg/vg_platform.h"
-#include "vg/vg_camera.h"
-#include "world_entity.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_map.c"
+#else
+
 enum superworld
 {
    k_superworld_venus_moon = 0,
@@ -30,8 +30,7 @@ struct world_map
    }
    activity;
 
-   mdl_context superworld_meta;
-   glmesh superworld_mesh;
+   vg_model superworld_meta;
    array_file_ptr ent_camera,
                   ent_marker,
                   ent_challenge;
@@ -46,7 +45,7 @@ struct world_map
 extern world_map;
 void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *allow_back_to_exit );
 void render_world_map(void);
-void world_map_init(void);
+VG_API void _world_map_init(void);
 void world_map_initialize_view(void);
 bool world_map_get_transition_cam( vg_camera *cam );
 
@@ -57,3 +56,5 @@ const char *_superworld_names[] =
    [k_superworld_campaign] = "Earth",
    [k_superworld_steam_workshop] = "Steam Workshop Planet",
 };
+
+#endif
index 03be1fc27fd7c7744bd526e6d03b5391eaa4a5d1..4971af6b9f851b76bb718eb83bb4aec59ab7b87a 100644 (file)
@@ -1,20 +1,12 @@
-#ifndef WORLD_PHYSICS_C
-#define WORLD_PHYSICS_C
-
-#include "world.h"
-#include "world_physics.h"
-
 void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] )
 {
    for( int i=0; i<3; i++ )
-      v3_copy( world->scene_geo.arrvertices[ hit->tri[i] ].co, tri[i] );
+      v3_copy( world->scene_geometry.vertex_buffer[ hit->tri[i] ].co, tri[i] );
 }
 
-int ray_world( world_instance *world,
-               v3f pos, v3f dir, ray_hit *hit, u16 ignore )
+int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit, u16 ignore )
 {
-   return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit, 
-                         ignore );
+   return scene_raycast( &world->scene_geometry, &world->geometry_bh, pos, dir, hit, ignore );
 }
 
 /*
@@ -45,15 +37,17 @@ int spherecast_world( world_instance *world,
    bh_iter it;
    bh_iter_init_box( 0, &it, region );
    i32 idx;
-   while( bh_next( world->geo_bh, &it, &idx ) ){
-      u32 *ptri = &world->scene_geo.arrindices[ idx*3 ];
-      if( world->scene_geo.arrvertices[ptri[0]].flags & ignore ) continue;
+   while( bh_next( &world->geometry_bh, &it, &idx ) )
+   {
+      u32 *ptri = &world->scene_geometry.indice_buffer[ idx*3 ];
+      if( world->scene_geometry.vertex_buffer[ptri[0]].flags & ignore ) continue;
 
       v3f tri[3];
       boxf box;
       box_init_inf( box );
-      for( int j=0; j<3; j++ ){
-         v3_copy( world->scene_geo.arrvertices[ptri[j]].co, tri[j] );
+      for( int j=0; j<3; j++ )
+      {
+         v3_copy( world->scene_geometry.vertex_buffer[ptri[j]].co, tri[j] );
          box_addpt( box, tri[j] );
       }
 
@@ -103,5 +97,3 @@ struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit )
 {
    return world_tri_index_surface( world, hit->tri[0] );
 }
-
-#endif /* WORLD_PHYSICS_C */
index 06143b9a9d9ed3c322cb5089196feec6153a9e56..cb238c0e8ff218e3540d1e35dd4fbe88cb1edd4e 100644 (file)
@@ -1,24 +1,12 @@
-#pragma once
-#include "world.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_rigidbody_collision.h"
-#include "vg/vg_bvh.h"
-
-void ray_world_get_tri( world_instance *world,
-                           ray_hit *hit, v3f tri[3] );
-
-int ray_world( world_instance *world,
-                  v3f pos, v3f dir, ray_hit *hit, u16 ignore );
-
-int spherecast_world( world_instance *world,
-                         v3f pa, v3f pb, float r, float *t, v3f n,
-                         u16 ignore );
-
-struct world_surface *world_tri_index_surface( world_instance *world, 
-                                                  u32 index );
-
-struct world_surface *world_contact_surface( world_instance *world,
-                                                  rb_ct *ct );
-
-struct world_surface *ray_hit_surface( world_instance *world,
-                                                 ray_hit *hit );
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_physics.c"
+#else
+
+void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] );
+int ray_world( world_instance *world, v3f pos, v3f dir, ray_hit *hit, u16 ignore );
+int spherecast_world( world_instance *world, v3f pa, v3f pb, float r, float *t, v3f n, u16 ignore );
+struct world_surface *world_tri_index_surface( world_instance *world, u32 index );
+struct world_surface *world_contact_surface( world_instance *world, rb_ct *ct );
+struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit );
+
+#endif
index 8023f0b032abc04de75a38a48f1751d50da006ee..1ab6aedb17667845fdc62e74be4856f4df5f2e5e 100644 (file)
@@ -1,20 +1,3 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "world.h"
-#include "world_render.h"
-#include "font.h"
-#include "gui.h"
-#include "world_map.h"
-#include "player_remote.h"
-#include "ent_skateshop.h"
-#include "shaders/model_entity.h"
-#include "shaders/model_sky_cubemap.h"
-#include "shaders/scene_preview.h"
-#include "shaders/scene_override.h"
-#include "board_maker.h"
-
 struct world_render world_render;
 
 static int ccmd_render_portals( int argc, const char *argv[] );
@@ -29,19 +12,7 @@ static int ccmd_set_time( int argc, const char *argv[] )
    return 0;
 }
 
-static void async_world_render_init( void *userdata )
-{
-   vg_info( "Allocate uniform buffers\n" );
-
-   world_instance *world = &_world.main;
-   world->ubo_bind_point = 0;
-   glGenBuffers( 1, &world->ubo_lighting );
-   glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), NULL, GL_DYNAMIC_DRAW );
-   glBindBufferBase( GL_UNIFORM_BUFFER, 0, world->ubo_lighting );
-}
-
-void world_render_register(void)
+VG_API void _world_render_register(void)
 {
    VG_VAR_F32( k_day_length );
    VG_VAR_I32( k_debug_light_indices );
@@ -52,33 +23,29 @@ void world_render_register(void)
    vg_console_reg_cmd( "render_portals", ccmd_render_portals, NULL );
 }
 
-void world_render_init(void)
+static void _world_render_load_content_async( void *_, vg_async_info *async )
 {
-   THREAD_1;
-   vg_info( "Loading world resources\n" );
-   vg_stack_clear( &vg.scratch );
-
-   mdl_context msky;
-   mdl_open( &msky, "models/rs_skydome.mdl", &vg.scratch );
-   mdl_load_metadata_block( &msky, &vg.scratch );
-   mdl_async_load_glmesh( &msky, &world_render.skydome, NULL );
-   world_render.skydome_complete_mesh = msky.submeshes[ mdl_get_submesh_index( &msky, "dome_complete" ) ];
-   world_render.skydome_squanched_mesh = msky.submeshes[ mdl_get_submesh_index( &msky, "dome_squanched" ) ];
-   mdl_close( &msky );
-
-   vg_info( "Loading default world textures\n" );
-   vg_tex2d_load_qoi_async_file( "textures/garbage.qoi", 
-                                 VG_TEX2D_NEAREST|VG_TEX2D_REPEAT, 
-                                 &world_render.tex_terrain_noise );
-
-   vg_info( "Allocate frame buffers\n" );
-   world_instance *world = &_world.main;
-   world->heightmap = vg_framebuffer_allocate( &vg.rtmem, 1, 0 );
-   world->heightmap->display_name = NULL;
-   world->heightmap->fixed_w = 1024;
-   world->heightmap->fixed_h = 1024;
-   world->heightmap->resolution_div = 0;
-   world->heightmap->attachments[0] = (vg_framebuffer_attachment)
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+   vg_model_load( &world_render.skydome, VG_MODEL_ENGINE_STANDARD, "models/rs_skydome.mdl", VG_STACK_USE_HEAP );
+   world_render.skydome_complete_mesh = vg_model_get_submesh_index( &world_render.skydome, "dome_complete" );
+   world_render.skydome_squanched_mesh = vg_model_get_submesh_index( &world_render.skydome, "dome_squanched" );
+
+   u32 flags = VG_TEX_NEAREST|VG_TEX_REPEAT|VG_TEX_NOMIP;
+   _vg_tex_load( &world_render.tex_terrain_noise, "textures/garbage.qoi", flags );
+}
+
+VG_API void _world_render_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_render_load_content_async );
+
+   world_render.heightmap = _vg_framebuffer_alloc( VG_STACK_USE_HEAP, 1, 0 );
+   world_render.heightmap->display_name = NULL;
+   world_render.heightmap->fixed_w = 1024;
+   world_render.heightmap->fixed_h = 1024;
+   world_render.heightmap->resolution_div = 0;
+   world_render.heightmap->attachments[0] = (vg_framebuffer_attachment)
    {
       NULL, k_framebuffer_attachment_type_texture,
       .internalformat = GL_RG16F,
@@ -86,58 +53,54 @@ void world_render_init(void)
       .type           = GL_FLOAT,
       .attachment     = GL_COLOR_ATTACHMENT0
    };
-   vg_framebuffer_create( world->heightmap );
-   vg_async_call( &vg.main_tasks, async_world_render_init, NULL );
+   vg_framebuffer_init( world_render.heightmap );
+
+   world_render.ubo_bind_point = 0;
+   glGenBuffers( 1, &world_render.ubo_lighting );
+   glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+   glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), NULL, GL_DYNAMIC_DRAW );
+   glBindBufferBase( GL_UNIFORM_BUFFER, 0, world_render.ubo_lighting );
 }
 
 /* 
  * standard uniform bindings
  * ----------------------------------------------------------------------------
  */
-void world_link_lighting_ub( world_instance *world, GLuint shader )
+void world_link_lighting( world_instance *world, 
+      enum e_shader_gl_name shader,
+      enum e_shader_gl_name uniform_block_index,
+      enum e_shader_gl_name uniform_position_tex,
+      enum e_shader_gl_name uniform_light_array,
+      enum e_shader_gl_name uniform_light_index )
 {
-   GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );   
-   glUniformBlockBinding( shader, idx, world->ubo_bind_point );
-}
+   glUniformBlockBinding( _vg_shader_names[ shader ], _vg_shader_names[ uniform_block_index ], 
+                          world_render.ubo_bind_point );
 
-void world_bind_position_texture( world_instance *world, 
-                                  GLuint shader, GLuint location,
-                                  int slot )
-{
-   vg_framebuffer_bind_texture( world->heightmap, 0, slot );
-   glUniform1i( location, slot );
-}
+   vg_framebuffer_bind_texture( world_render.heightmap, 0, 2 );
+   glUniform1i( _vg_shader_names[ uniform_position_tex ], 2 );
 
-void world_bind_light_array( world_instance *world,
-                             GLuint shader, GLuint location, 
-                             int slot )
-{
-   glActiveTexture( GL_TEXTURE0 + slot );
+   glActiveTexture( GL_TEXTURE0 + 3 );
    glBindTexture( GL_TEXTURE_BUFFER, world->tex_light_entities );
-   glUniform1i( location, slot );
-}
+   glUniform1i( _vg_shader_names[ uniform_light_array ], 3 );
 
-void world_bind_light_index( world_instance *world,
-                             GLuint shader, GLuint location,
-                             int slot )
-{
-   glActiveTexture( GL_TEXTURE0 + slot );
+   glActiveTexture( GL_TEXTURE0 + 4 );
    glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
-   glUniform1i( location, slot );
+   glUniform1i( _vg_shader_names[ uniform_light_index ], 4 );
 }
 
-void bind_terrain_noise(void)
+void world_link_terrain_noise( world_instance *world, enum e_shader_gl_name uniform_sampler )
 {
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+   vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
+   glUniform1i( _vg_shader_names[ uniform_sampler ], 0 );
 }
 
 /* 
  * Get OpenGL texture name from texture ID.
  */
-static GLuint world_get_texture( world_instance *world, u32 id ){
+static vg_tex *world_get_texture( world_instance *world, u32 id )
+{
    if( id & 0x80000000 ) return skaterift.rt_textures[id & ~0x80000000];
-   else                  return world->textures[ id ];
+   else                  return id? &world->meta.textures[ id-1 ].tex: NULL;
 }
 
 /*
@@ -151,7 +114,7 @@ struct world_pass
    enum mdl_shader shader;
    enum world_geo_type geo_type;
 
-   void (*fn_bind)( world_instance *world, struct world_surface *mat );
+   void (*fn_bind)( world_instance *world, u32 surface_id );
    void (*fn_set_mdl)( m4x3f mdl );
    void (*fn_set_uPvmPrev)( m4x4f pvm );
    void (*fn_set_uNormalMtx)( m3x3f mnorm );
@@ -183,7 +146,7 @@ static void world_render_submeshes( world_instance *world,
       pass->fn_set_mdl( mmdl );
       pass->fn_set_uPvmPrev( m4mdl );
 
-      mdl_draw_submesh( sm );
+      vg_model_draw_submesh( sm );
    }
 }
 
@@ -192,10 +155,12 @@ static void world_render_submeshes( world_instance *world,
  */
 static void world_render_props( world_instance *world, u32 material_id, struct world_pass *pass )
 {
-   struct world_surface *mat = &world->surfaces[ material_id ];
-   if( !(mat->flags & WORLD_SURFACE_HAS_PROPS) ) return;
+   struct world_surface *surf = &world->surfaces[ material_id ];
+   if( !(surf->flags & WORLD_SURFACE_HAS_PROPS) ) 
+      return;
 
-   pass->fn_bind( world, mat );
+   VG_ASSERT( material_id );
+   pass->fn_bind( world, material_id );
 
    for( u32 j=0; j<af_arrcount( &world->ent_prop ); j++ )
    {
@@ -212,11 +177,12 @@ static void world_render_props( world_instance *world, u32 material_id, struct w
  */
 static void world_render_traffic( world_instance *world, u32 material_id,struct world_pass *pass )
 {
-   struct world_surface *mat = &world->surfaces[ material_id ];
-   if( !(mat->flags & WORLD_SURFACE_HAS_TRAFFIC) ) 
+   struct world_surface *surf = &world->surfaces[ material_id ];
+   if( !(surf->flags & WORLD_SURFACE_HAS_TRAFFIC) ) 
       return;
 
-   pass->fn_bind( world, mat );
+   VG_ASSERT( material_id );
+   pass->fn_bind( world, material_id );
 
    for( u32 j=0; j<af_arrcount( &world->ent_traffic ); j++ ){
       ent_traffic *traffic = af_arritm( &world->ent_traffic, j );
@@ -233,23 +199,23 @@ static void world_render_traffic( world_instance *world, u32 material_id,struct
  */
 static void world_render_pass( world_instance *world, struct world_pass *pass )
 {
-   for( int i=0; i<world->surface_count; i++ )
+   for( int i=1; i<world->surface_count; i++ )
    {
-      struct world_surface *mat = &world->surfaces[i];
+      struct world_surface *surf = &world->surfaces[i];
 
-      if( mat->info.shader == pass->shader )
+      if( surf->info.shader == pass->shader )
       {
          mdl_submesh *sm;
 
          if( pass->geo_type == k_world_geo_type_solid )
          {
-            sm = &mat->sm_geo;
+            sm = &surf->sm_geo;
          }
          else
          {
             world_render_traffic( world, i, pass );
             world_render_props( world, i, pass );
-            sm = &mat->sm_no_collide;
+            sm = &surf->sm_no_collide;
          }
 
          if( !sm->indice_count )
@@ -259,8 +225,8 @@ static void world_render_pass( world_instance *world, struct world_pass *pass )
          m4x3_identity( mmdl );
          pass->fn_set_mdl( mmdl );
          pass->fn_set_uPvmPrev( pass->cam->mtx_prev.pv );
-         pass->fn_bind( world, mat );
-         mdl_draw_submesh( sm );
+         pass->fn_bind( world, i );
+         vg_model_draw_submesh( sm );
       }
    }
 }
@@ -273,24 +239,21 @@ static void world_render_pass( world_instance *world, struct world_pass *pass )
 static void world_render_both_stages( world_instance *world, 
                                       struct world_pass *pass )
 {
-   mesh_bind( &world->mesh_geo );
+   scene_mesh_bind( &world->main_scene_mesh );
    pass->geo_type = k_world_geo_type_solid;
    world_render_pass( world, pass );
 
    glDisable( GL_CULL_FACE );
-   mesh_bind( &world->mesh_no_collide );
+   scene_mesh_bind( &world->transparent_scene_mesh );
    pass->geo_type = k_world_geo_type_nonsolid;
    world_render_pass( world, pass );
    glEnable( GL_CULL_FACE );
 }
 
-static void bindpoint_world_vb( world_instance *world,
-                                struct world_surface *mat )
+static void bindpoint_world_vb( world_instance *world, u32 surface_id )
 {
-   struct shader_props_vertex_blend *props = mat->info.props.compiled;
-
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->vertex_blend.tex_diffuse), 1 );
 
 #if 0
    shader_scene_vertex_blend_uOffset( props->blend_offset );
@@ -302,10 +265,8 @@ static void render_world_vb( world_instance *world, vg_camera *cam )
    shader_scene_vertex_blend_use();
    shader_scene_vertex_blend_uTexGarbage(0);
    shader_scene_vertex_blend_uTexGradients(1);
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
-
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+   WORLD_LINK_LIGHTING( world, scene_vertex_blend );
+   vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
 
    shader_scene_vertex_blend_uPv( cam->mtx.pv );
    shader_scene_vertex_blend_uCamera( cam->transform[3] );
@@ -328,19 +289,15 @@ static void world_shader_standard_bind( world_instance *world, vg_camera *cam )
    shader_scene_standard_uTexGarbage(0);
    shader_scene_standard_uTexMain(1);
    shader_scene_standard_uPv( cam->mtx.pv );
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_standard );
-
-   bind_terrain_noise();
+   WORLD_LINK_LIGHTING( world, scene_standard );
+   world_link_terrain_noise( world, k_uniform_scene_standard_uTexGarbage );
    shader_scene_standard_uCamera( cam->transform[3] );
 }
 
-static void bindpoint_standard( world_instance *world, 
-                                struct world_surface *mat )
+static void bindpoint_standard( world_instance *world, u32 surface_id )
 {
-   struct shader_props_standard *props = mat->info.props.compiled;
-
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->standard.tex_diffuse), 1 );
 }
 
 static void render_world_standard( world_instance *world, vg_camera *cam )
@@ -358,15 +315,12 @@ static void render_world_standard( world_instance *world, vg_camera *cam )
    world_render_both_stages( world, &pass );
 }
 
-static void bindpoint_world_cubemapped( world_instance *world, struct world_surface *mat )
+static void bindpoint_world_cubemapped( world_instance *world, u32 surface_id )
 {
-   struct shader_props_cubemapped *props = mat->info.props.compiled;
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture( world, props->cubemapped.tex_diffuse ), 1 );
 
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, 
-                  world_get_texture( world,props->tex_diffuse ) );
-
-   u32 cubemap_id = props->cubemap_entity,
+   u32 cubemap_id = props->cubemapped.cubemap_entity,
        cubemap_index = 0;
 
    if( mdl_entity_id_type( cubemap_id ) == k_ent_cubemap )
@@ -378,17 +332,13 @@ static void bindpoint_world_cubemapped( world_instance *world, struct world_surf
    glActiveTexture( GL_TEXTURE10 );
    glBindTexture( GL_TEXTURE_CUBE_MAP, cm->texture_id );
 
-   shader_scene_cubemapped_uColour( props->tint );
+   shader_scene_cubemapped_uColour( props->cubemapped.tint );
 }
 
-static void bindpoint_world_cubemapped_disabled( world_instance *world,
-                                                 struct world_surface *mat )
+static void bindpoint_world_cubemapped_disabled( world_instance *world, u32 surface_id )
 {
-   struct shader_props_cubemapped *props = mat->info.props.compiled;
-
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, 
-                  world_get_texture( world, props->tex_diffuse ) );
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture( world, props->cubemapped.tex_diffuse ), 1 );
 }
 
 static void render_world_cubemapped( world_instance *world, vg_camera *cam, int enabled )
@@ -419,9 +369,9 @@ static void render_world_cubemapped( world_instance *world, vg_camera *cam, int
       shader_scene_cubemapped_uTexCubemap(10);
       shader_scene_cubemapped_uPv( cam->mtx.pv );
 
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_cubemapped );
+      WORLD_LINK_LIGHTING( world, scene_cubemapped );
 
-      bind_terrain_noise();
+      world_link_terrain_noise( world, k_uniform_scene_cubemapped_uTexGarbage );
       shader_scene_cubemapped_uCamera( cam->transform[3] );
       
       struct world_pass pass = 
@@ -440,13 +390,12 @@ static void render_world_cubemapped( world_instance *world, vg_camera *cam, int
 static void render_world_alphatest( world_instance *world, vg_camera *cam )
 {
    shader_scene_standard_alphatest_use();
-   shader_scene_standard_alphatest_uTexGarbage(0);
    shader_scene_standard_alphatest_uTexMain(1);
    shader_scene_standard_alphatest_uPv( cam->mtx.pv );
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_standard_alphatest );
+   WORLD_LINK_LIGHTING( world, scene_standard_alphatest );
 
-   bind_terrain_noise();
+   world_link_terrain_noise( world, k_uniform_scene_standard_uTexGarbage );
    shader_scene_standard_alphatest_uCamera( cam->transform[3] );
    glDisable(GL_CULL_FACE);
 
@@ -466,14 +415,13 @@ static void render_world_alphatest( world_instance *world, vg_camera *cam )
 static void render_world_foliage( world_instance *world, vg_camera *cam )
 {
    shader_scene_foliage_use();
-   shader_scene_foliage_uTexGarbage(0);
    shader_scene_foliage_uTexMain(1);
    shader_scene_foliage_uPv( cam->mtx.pv );
    shader_scene_foliage_uTime( vg.time );
    shader_scene_foliage_uAmt( world->info.wind_scale );
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_foliage );
-   bind_terrain_noise();
+   WORLD_LINK_LIGHTING( world, scene_foliage );
+   world_link_terrain_noise( world, k_uniform_scene_foliage_uTexGarbage );
 
    shader_scene_foliage_uCamera( cam->transform[3] );
    glDisable(GL_CULL_FACE);
@@ -535,7 +483,7 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
       bh_iter it;
       bh_iter_init_range( 0, &it, pos, radius+10.0f );
       i32 idx;
-      while( bh_next( world->entity_bh, &it, &idx ) )
+      while( bh_next( &world->entity_bh, &it, &idx ) )
       {
          u32 id    = world->entity_list[ idx ],
              type  = mdl_entity_id_type( id ),
@@ -556,7 +504,7 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
 
    /* render objectives */
    glDisable( GL_CULL_FACE );
-   mesh_bind( &world->mesh_no_collide );
+   scene_mesh_bind( &world->transparent_scene_mesh );
    u32 last_material = 0;
    for( u32 i=0; i<objective_count; i++ )
    {
@@ -601,14 +549,15 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
          if( sm->material_id != last_material )
          {
             last_material = sm->material_id;
-            pass->fn_bind( world, &world->surfaces[sm->material_id] );
+            VG_ASSERT( sm->material_id );
+            pass->fn_bind( world, sm->material_id );
          }
-         mdl_draw_submesh( sm );
+         vg_model_draw_submesh( sm );
       }
    }
 
    /* render texts */
-   font3d_bind( &gui.font, k_font_shader_world, 0, world, &g_render.cam );
+   font3d_bind( &gui.font, k_font_shader_world, 0, &g_render.cam );
 
    u32 count = 0, total = 0;
    for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
@@ -624,9 +573,9 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
    char buf[32];
    vg_str str;
    vg_strnull( &str, buf, sizeof(buf) );
-   vg_strcati32( &str, count );
+   vg_strcati64( &str, count, 10 );
    vg_strcatch( &str, '/' );
-   vg_strcati32( &str, total );
+   vg_strcati64( &str, total, 10 );
 
    f32 w = font3d_string_width( 1, buf );
    m4x3f mlocal;
@@ -662,12 +611,10 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
    }
 }
 
-static void bindpoint_fxglow( world_instance *world, struct world_surface *mat )
+static void bindpoint_fxglow( world_instance *world, u32 surface_id )
 {
-   struct shader_props_standard *props = mat->info.props.compiled;
-
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->standard.tex_diffuse), 1 );
 }
 
 static void render_world_fxglow( world_instance *host_world, 
@@ -679,7 +626,7 @@ static void render_world_fxglow( world_instance *host_world,
    shader_scene_fxglow_uUvOffset( (v2f){ 0.0f, 0.0f } );
    shader_scene_fxglow_uTexMain(1);
    shader_scene_fxglow_uPv( cam->mtx.pv );
-   //WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_fxglow );
+   //WORLD_LINK_LIGHTING( world, scene_fxglow );
    shader_scene_fxglow_uCamera( cam->transform[3] );
    glDisable(GL_CULL_FACE);
 
@@ -697,7 +644,7 @@ static void render_world_fxglow( world_instance *host_world,
 
    if( regions )
    {
-      mesh_bind( &world->mesh_no_collide );
+      scene_mesh_bind( &world->transparent_scene_mesh );
 
       u32 last_material = 0;
       for( u32 i=0; i<af_arrcount(&world->ent_region); i ++ )
@@ -725,9 +672,10 @@ static void render_world_fxglow( world_instance *host_world,
             if( sm->material_id != last_material )
             {
                last_material = sm->material_id;
-               pass.fn_bind( world, &world->surfaces[sm->material_id] );
+               VG_ASSERT( sm->material_id );
+               pass.fn_bind( world, sm->material_id );
             }
-            mdl_draw_submesh( sm );
+            vg_model_draw_submesh( sm );
          }
       }
    }
@@ -738,40 +686,41 @@ static void render_world_fxglow( world_instance *host_world,
    glEnable(GL_CULL_FACE);
 }
 
-static void bindpoint_terrain( world_instance *world,
-                               struct world_surface *mat )
+static void bindpoint_terrain( world_instance *world, u32 surface_id )
 {
-   struct shader_props_terrain *props = mat->info.props.compiled;
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
 
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, world_get_texture(world, props->tex_diffuse) );
-   shader_scene_terrain_uBlendOffset( props->blend_offset );
-   shader_scene_terrain_uSandColour( props->sand_colour );
+   vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, props->terrain.tex_diffuse), 1 );
+   shader_scene_terrain_uBlendOffset( props->terrain.blend_offset );
+   shader_scene_terrain_uSandColour( props->terrain.sand_colour );
 }
 
-static void bindpoint_override( world_instance *world, struct world_surface *mat )
+static void bindpoint_override( world_instance *world, u32 surface_id )
 {
-   f32 skate_surface = mat->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
+   struct world_surface *surf = &world->surfaces[ surface_id ];
+   f32 skate_surface = surf->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
    shader_scene_override_uSurfaceInfo( (v4f){ skate_surface, 0,0,0 } );
    
-   if( mat->info.flags & k_material_flag_collision )
+   if( surf->info.flags & k_material_flag_collision )
    {
       shader_scene_override_uAlphatest(0);
    }
    else
    {
-      glActiveTexture( GL_TEXTURE1 );
-      glBindTexture( GL_TEXTURE_2D, world_get_texture(world, mat->alpha_tex) );
+      vg_tex_bind( GL_TEXTURE_2D, world_get_texture(world, surf->alpha_tex), 1 );
       shader_scene_override_uAlphatest(1);
    }
 }
 
-static void bindpoint_world_preview( world_instance *world, struct world_surface *mat )
+static void bindpoint_world_preview( world_instance *world, u32 surface_id )
 {
-   f32 skate_surface = mat->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
+   union shader_props *props = &world->meta.shader_props[ surface_id -1 ];
+   struct world_surface *surf = &world->surfaces[ surface_id ];
+
+   f32 skate_surface = surf->info.flags & k_material_flag_skate_target? 1.0f: 0.0f;
    shader_scene_preview_uSurfaceInfo( (v4f){ skate_surface, 0,0,0 } );
 
-   if( mat->info.flags & k_material_flag_collision )
+   if( surf->info.flags & k_material_flag_collision )
    {
    }
    else
@@ -786,9 +735,8 @@ static void render_terrain( world_instance *world, vg_camera *cam )
    shader_scene_terrain_uTexGarbage(0);
    shader_scene_terrain_uTexGradients(1);
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_terrain );
-   glActiveTexture( GL_TEXTURE0 );
-   glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+   WORLD_LINK_LIGHTING( world, scene_terrain );
+   vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
 
    shader_scene_terrain_uPv( cam->mtx.pv );
    shader_scene_terrain_uCamera( cam->transform[3] );
@@ -846,36 +794,37 @@ static void render_sky( world_instance *world, vg_camera *cam )
       shader_model_sky_uPv( pv );
       shader_model_sky_uPvmPrev( pv_prev );
       shader_model_sky_uTexGarbage(0);
-      world_link_lighting_ub( world, _shader_model_sky.id );
+      glUniformBlockBinding( _vg_shader_names[ k_shader_model_sky ], 
+                             _vg_shader_names[ k_uniform_block_model_sky_ub_world_lighting ], 
+                             world_render.ubo_bind_point );
 
-      glActiveTexture( GL_TEXTURE0 );
-      glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+      vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
    }
-   else if( world->skybox == k_skybox_space ){
+   else if( world->skybox == k_skybox_space )
+   {
       shader_model_sky_space_use();
-
       shader_model_sky_space_uMdl( identity_matrix );
       shader_model_sky_space_uPv( pv );
       shader_model_sky_space_uPvmPrev( pv_prev );
       shader_model_sky_space_uTexGarbage(0);
-      world_link_lighting_ub( world, _shader_model_sky_space.id );
+      glUniformBlockBinding( _vg_shader_names[ k_shader_model_sky_space ], 
+                             _vg_shader_names[ k_uniform_block_model_sky_space_ub_world_lighting ], 
+                             world_render.ubo_bind_point );
 
-      glActiveTexture( GL_TEXTURE0 );
-      glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
+      vg_tex_bind( GL_TEXTURE_2D, &world_render.tex_terrain_noise, 0 );
    }
    else if( world->skybox == k_skybox_cubemap )
    {
       /* TODO */
    }
-   else {
+   else
       vg_fatal_error( "Programming error\n" );
-   }
 
    glDepthMask( GL_FALSE );
    glDisable( GL_DEPTH_TEST );
 
-   mesh_bind( &world_render.skydome );
-   mdl_draw_submesh( &world_render.skydome_complete_mesh );
+   vg_model_bind_mesh( &world_render.skydome );
+   vg_model_draw_submesh( &world_render.skydome.submeshes[ world_render.skydome_complete_mesh ]);
    
    glEnable( GL_DEPTH_TEST );
    glDepthMask( GL_TRUE );
@@ -946,9 +895,7 @@ void render_world_gates( world_instance *world, vg_camera *cam, vg_framebuffer *
             shader_model_sky_cubemap_uPv( cam->mtx.pv );
             shader_model_sky_cubemap_uPvmPrev( pvm );
             shader_model_sky_cubemap_uTexCubemap(10);
-
-            glActiveTexture( GL_TEXTURE10 );
-            glBindTexture( GL_TEXTURE_CUBE_MAP, world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+            vg_tex_bind( GL_TEXTURE_CUBE_MAP, &world->nonlocal_gates_cubemaps[ gate->cubemap_id ], 10 );
 
             glClear( GL_DEPTH_BUFFER_BIT );
             glStencilFunc( GL_EQUAL, 1, 0xFF );
@@ -956,8 +903,8 @@ void render_world_gates( world_instance *world, vg_camera *cam, vg_framebuffer *
             glEnable( GL_CULL_FACE );
             glEnable( GL_STENCIL_TEST );
 
-            mesh_bind( &world_render.skydome );
-            mdl_draw_submesh( &world_render.skydome_squanched_mesh );
+            vg_model_bind_mesh( &world_render.skydome );
+            vg_model_draw_submesh( &world_render.skydome.submeshes[ world_render.skydome_squanched_mesh ]);
 
             glStencilMask( 0xFF );
             glStencilFunc( GL_ALWAYS, 1, 0xFF );
@@ -987,7 +934,7 @@ void world_prerender( world_instance *world )
       world->time = world->info.timezone;
    }
 
-   struct ub_world_lighting *state = &world->ub_lighting;
+   struct ub_world_lighting *state = &world_render.ub_lighting;
 
    state->g_time = world->time;
    state->g_realtime = vg.time_real;
@@ -1023,9 +970,8 @@ void world_prerender( world_instance *world )
    world->probabilities[ k_probability_curve_wildlife_night ] = 
       1.0f-powf(fabsf((state->g_time_of_day-0.5f)*5.0f),5.0f);
       
-   glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-   glBufferSubData( GL_UNIFORM_BUFFER, 0, 
-                    sizeof(struct ub_world_lighting), &world->ub_lighting );
+   glBindBuffer( GL_UNIFORM_BUFFER, world_render.ubo_lighting );
+   glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), &world_render.ub_lighting );
 }
 
 static void render_other_entities( world_instance *world, vg_camera *cam )
@@ -1038,7 +984,8 @@ static void render_other_entities( world_instance *world, vg_camera *cam )
        glider_count = 0;
 
    i32 idx;
-   while( bh_next( world->entity_bh, &it, &idx ) ){
+   while( bh_next( &world->entity_bh, &it, &idx ) )
+   {
       u32 id    = world->entity_list[ idx ],
           type  = mdl_entity_id_type( id ),
           index = mdl_entity_id_id( id );
@@ -1054,7 +1001,7 @@ static void render_other_entities( world_instance *world, vg_camera *cam )
    shader_model_entity_uTexMain( 0 );
    shader_model_entity_uCamera( cam->transform[3] );
    shader_model_entity_uPv( cam->mtx.pv );
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+   WORLD_LINK_LIGHTING( world, model_entity );
 
    for( u32 j=0; j<glider_count; j ++ )
    {
@@ -1072,7 +1019,7 @@ static void render_other_entities( world_instance *world, vg_camera *cam )
       render_glider_model( cam, world, mdl, k_board_shader_entity, &player_glide.glider );
    }
 
-   cutscene_render( world, cam );
+   _cutscene_render( cam );
    _ent_npc_render( cam );
 }
 
@@ -1190,7 +1137,7 @@ void render_world( world_instance *world, vg_camera *cam,
 
    render_remote_players( world, cam );
    render_other_entities( world, cam );
-   _replay2_render_player( world, cam );
+   _replay2_render_player( cam );
    
    _board_maker_render( world, cam );
 
@@ -1208,7 +1155,7 @@ static void render_world_override_pass( world_instance *world,
                                         m4x3f mmdl, m3x3f mnormal,
                                         m4x4f mpvm_prev )
 {
-   for( int i=0; i<world->surface_count; i++ )
+   for( int i=1; i<world->surface_count; i++ )
    {
       struct world_surface *mat = &world->surfaces[i];
       if( mat->info.flags & k_material_flag_ghosts ) continue;
@@ -1225,8 +1172,8 @@ static void render_world_override_pass( world_instance *world,
       pass->fn_set_mdl( mmdl );
       pass->fn_set_uNormalMtx( mnormal );
       pass->fn_set_uPvmPrev( mpvm_prev );
-      pass->fn_bind( world, mat );
-      mdl_draw_submesh( sm );
+      pass->fn_bind( world, i );
+      vg_model_draw_submesh( sm );
    }
 }
 
@@ -1247,13 +1194,12 @@ void render_world_override( world_instance *world,
    };
 
    shader_scene_override_use();
-   shader_scene_override_uTexGarbage(0);
    shader_scene_override_uTexMain(1);
    shader_scene_override_uPv( pass.cam->mtx.pv );
    shader_scene_override_uMapInfo( map_info );
 
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( lighting_source, scene_override );
-   bind_terrain_noise();
+   WORLD_LINK_LIGHTING( lighting_source, scene_override );
+   world_link_terrain_noise( world, k_uniform_scene_override_uTexGarbage );
 
    shader_scene_override_uCamera( pass.cam->transform[3] );
 
@@ -1286,10 +1232,10 @@ void render_world_override( world_instance *world,
 
 
    glDisable( GL_CULL_FACE );
-   mesh_bind( &world->mesh_geo );
+   scene_mesh_bind( &world->main_scene_mesh );
    pass.geo_type = k_world_geo_type_solid;
    render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
-   mesh_bind( &world->mesh_no_collide );
+   scene_mesh_bind( &world->transparent_scene_mesh );
    pass.geo_type = k_world_geo_type_nonsolid;
    render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
    glEnable( GL_CULL_FACE );
@@ -1332,12 +1278,12 @@ void render_world_preview( vg_camera *cam )
    v3_normalize( mnormal[2] );
 
    glEnable( GL_CULL_FACE );
-   mesh_bind( &world->mesh_geo );
+   scene_mesh_bind( &world->main_scene_mesh );
    pass.geo_type = k_world_geo_type_solid;
    render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
 
    glDisable( GL_CULL_FACE );
-   mesh_bind( &world->mesh_no_collide );
+   scene_mesh_bind( &world->transparent_scene_mesh );
    pass.geo_type = k_world_geo_type_nonsolid;
    render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
    
@@ -1424,7 +1370,6 @@ void render_world_cubemaps( world_instance *world )
             .fixed_h = WORLD_CUBEMAP_RES,
             .id = cm->framebuffer_id,
             .attachment_count = 0,
-            .attachments = NULL
          };
          render_cubemap_side( world, cm->co, identity, world->cubemap_side, &temp_vg_framebuffer );
       }
@@ -1442,8 +1387,8 @@ void render_world_portal_cubemaps(void)
       .colorspace = 0
    };
 
-   u8 *src_image = malloc( 512*512*3*6 );
-   u8 *compressed_image = malloc( vg_query_qoi_storage_size( &desc ) );
+   u32 temp_frame = _vg_start_temp_frame();
+   u8 *src_image = vg_stack_allocate( _vg_temp_stack(), 512*512*3*6, 8, "RGBA Image data" );
 
    GLuint temp_tex, temp_fb, temp_rb;
    glGenFramebuffers( 1, &temp_fb );
@@ -1474,7 +1419,6 @@ void render_world_portal_cubemaps(void)
       .fixed_h = 512,
       .id = temp_fb,
       .attachment_count = 0,
-      .attachments = NULL
    };
 
    world_instance *world = &_world.main;
@@ -1501,19 +1445,21 @@ void render_world_portal_cubemaps(void)
          }
 
          char path[256];
-         nonlocal_gate_cubemap_path( world->addon_id, af_str( &world->meta.af, gate->key ), path );
+         nonlocal_gate_cubemap_path( world->addon_id, af_str( world->meta.packed_strings, gate->key ), path );
 
-         int file_size;
-         if( vg_encode_qoi2( src_image, &desc, compressed_image, &file_size ) )
-            vg_asset_write( path, compressed_image, file_size );
+         vg_stream file;
+         if( vg_file_stream_open( &file, path, VG_STREAM_WRITE ) )
+         {
+            vg_qoi_stream_encode( &desc, src_image, &file, 0 );
+            vg_file_stream_close( &file );
+         }
       }
    }
 
 e0:glDeleteTextures( 1, &temp_tex );
    glDeleteFramebuffers( 1, &temp_fb );
    glDeleteRenderbuffers( 1, &temp_rb );
-   free( src_image );
-   free( compressed_image );
+   _vg_end_temp_frame( temp_frame );
 }
 
 static int ccmd_render_portals( int argc, const char *argv[] )
@@ -1537,16 +1483,18 @@ void render_world_depth( world_instance *world, vg_camera *cam )
    shader_scene_depth_uPv( cam->mtx.pv );
    shader_scene_depth_uPvmPrev( cam->mtx_prev.pv );
    shader_scene_depth_uMdl( identity_matrix );
-   world_link_lighting_ub( world, _shader_scene_depth.id );
+   glUniformBlockBinding( _vg_shader_names[ k_shader_scene_depth ], 
+                          _vg_shader_names[ k_uniform_block_scene_depth_ub_world_lighting ], 
+                          world_render.ubo_bind_point );
 
-   mesh_bind( &world->mesh_geo );
+   scene_mesh_bind( &world->main_scene_mesh );
    for( int i=0; i<world->surface_count; i++ )
    {
       struct world_surface *mat = &world->surfaces[i];
       if( mat->info.flags & k_material_flag_ghosts ) continue;
 
       mdl_submesh *sm = &mat->sm_geo;
-      mdl_draw_submesh( sm );
+      vg_model_draw_submesh( sm );
    }
 }
 
@@ -1560,16 +1508,18 @@ void render_world_position( world_instance *world, vg_camera *cam )
    shader_scene_position_uPv( cam->mtx.pv );
    shader_scene_position_uPvmPrev( cam->mtx_prev.pv );
    shader_scene_position_uMdl( identity_matrix );
-   world_link_lighting_ub( world, _shader_scene_position.id );
+   glUniformBlockBinding( _vg_shader_names[ k_shader_scene_position ], 
+                          _vg_shader_names[ k_uniform_block_scene_position_ub_world_lighting ], 
+                          world_render.ubo_bind_point );
 
-   mesh_bind( &world->mesh_geo );
+   scene_mesh_bind( &world->main_scene_mesh );
    for( int i=0; i<world->surface_count; i++ )
    {
       struct world_surface *mat = &world->surfaces[i];
       if( mat->info.flags & k_material_flag_ghosts ) continue;
 
       mdl_submesh *sm = &mat->sm_geo;
-      mdl_draw_submesh( sm );
+      vg_model_draw_submesh( sm );
    }
 }
 
@@ -1583,18 +1533,18 @@ struct ui_enum_opt skybox_setting_options[] = {
 
 static f32 *skybox_prop_location( world_instance *world, i32 index ){
    switch( index ){
-      case 0: return world->ub_lighting.g_daysky_colour; break;
-      case 1: return world->ub_lighting.g_nightsky_colour; break;
-      case 2: return world->ub_lighting.g_sunset_colour; break;
-      case 3: return world->ub_lighting.g_ambient_colour; break;
-      case 4: return world->ub_lighting.g_sun_colour; break;
+      case 0: return world_render.ub_lighting.g_daysky_colour; break;
+      case 1: return world_render.ub_lighting.g_nightsky_colour; break;
+      case 2: return world_render.ub_lighting.g_sunset_colour; break;
+      case 3: return world_render.ub_lighting.g_ambient_colour; break;
+      case 4: return world_render.ub_lighting.g_sun_colour; break;
       default: return NULL;
    }
 }
 
 void imgui_world_light_edit( ui_context *ctx, world_instance *world )
 {
-   ui_rect panel = { vg.window_x-400, 0, 400, vg.window_y };
+   ui_rect panel = { _vg_window.w-400, 0, 400, _vg_window.h };
    ui_fill( ctx, panel, ui_colour( ctx, k_ui_bg+1 ) );
    ui_outline( ctx, panel, 1, ui_colour( ctx, k_ui_bg+7 ), 0 );
    ui_rect_pad( panel, (ui_px[2]){ 8, 8 } );
index 4f329d5e85f478154610840bf7fe5a1fa4834f37..331ac638a41b9bc97c59c3118b339357235d6920 100644 (file)
@@ -1,37 +1,19 @@
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#pragma once
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_render.c"
+#else
 
 #define WORLD_CUBEMAP_RES 32
 
-#include "vg/vg_camera.h"
-#include "world.h"
-#include "shaders/scene_standard.h"
-#include "shaders/scene_standard_alphatest.h"
-#include "shaders/scene_foliage.h"
-#include "shaders/scene_override.h"
-#include "shaders/scene_cubemapped.h"
-#include "shaders/scene_vertex_blend.h"
-#include "shaders/scene_terrain.h"
-#include "shaders/scene_fxglow.h"
-#include "shaders/scene_depth.h"
-#include "shaders/scene_position.h"
-#include "shaders/scene_font.h"
-#include "shaders/model_sky.h"
-#include "shaders/model_sky_space.h"
-
 static const float k_world_light_cube_size = 8.0f;
 
 struct world_render
 {
-   GLuint tex_terrain_noise;
+   vg_tex tex_terrain_noise;
 
    /* rendering */
-   glmesh skydome;
-   mdl_submesh skydome_complete_mesh,
-               skydome_squanched_mesh;
+   vg_model skydome;
+   i32 skydome_complete_mesh,
+       skydome_squanched_mesh;
 
    v3f render_gate_pos;
    struct timer_text{
@@ -53,23 +35,72 @@ struct world_render
    }
    text_particles[6*4];
    u32 text_particle_count;
+
+   /* STD140 */
+   struct ub_world_lighting{
+      v4f g_cube_min,
+          g_cube_inv_range;
+
+      v4f g_water_plane,
+          g_depth_bounds;
+
+      v4f g_daysky_colour;
+      v4f g_nightsky_colour;
+      v4f g_sunset_colour;
+      v4f g_ambient_colour;
+      v4f g_sunset_ambient;
+      v4f g_sun_colour;
+      v4f g_sun_dir;
+      v4f g_board_0;
+      v4f g_board_1;
+
+      float g_water_fog;
+      float g_time;
+      float g_realtime;
+      float g_shadow_length;
+      float g_shadow_spread;
+
+      float g_time_of_day;
+      float g_day_phase;
+      float g_sunset_phase;
+
+      int g_light_preview;
+      int g_shadow_samples;
+
+      int g_debug_indices;
+      int g_debug_complexity;
+   }
+   ub_lighting;
+   GLuint ubo_lighting;
+   int    ubo_bind_point;
+   vg_framebuffer *heightmap;
 }
 extern world_render;
 
-void world_render_register(void);
-void world_render_init(void);
+VG_API void _world_render_register(void);
+VG_API void _world_render_init(void);
 
 void world_prerender( world_instance *world );
-void world_link_lighting_ub( world_instance *world, GLuint shader );
-void world_bind_position_texture( world_instance *world, 
-                                  GLuint shader, GLuint location,
-                                  int slot );
-void world_bind_light_array( world_instance *world,
-                             GLuint shader, GLuint location, 
-                             int slot );
-void world_bind_light_index( world_instance *world,
-                             GLuint shader, GLuint location,
-                             int slot );
+void world_link_lighting( world_instance *world, 
+      enum e_shader_gl_name shader,
+      enum e_shader_gl_name uniform_block_index,
+      enum e_shader_gl_name uniform_position_tex,
+      enum e_shader_gl_name uniform_light_array,
+      enum e_shader_gl_name uniform_light_index );
+
+void world_link_terrain_noise( world_instance *world, enum e_shader_gl_name uniform_sampler );
+
+#define WORLD_LINK_LIGHTING( WORLD, SHADER_NAME ) \
+   world_link_lighting( WORLD, \
+                        k_shader_##SHADER_NAME, \
+                        k_uniform_block_##SHADER_NAME##_ub_world_lighting, \
+                        k_uniform_##SHADER_NAME##_g_world_depth, \
+                        k_uniform_##SHADER_NAME##_uLightsArray, \
+                        k_uniform_##SHADER_NAME##_uLightsIndex )
+
+#define WORLD_LINK_TERRAIN_NOISE( WORLD, SHADER_NAME ) \
+   world_link_terrain_noise( WORLD, k_uniform_##SHADER_NAME##_uTexGarbage )
+
 void render_world_position( world_instance *world, vg_camera *cam );
 void render_world_depth( world_instance *world, vg_camera *cam );
 void render_world( world_instance *world, vg_camera *cam,
@@ -86,12 +117,4 @@ void render_world_preview( vg_camera *cam );
 void render_world_gates( world_instance *world, vg_camera *cam, vg_framebuffer *target_fb );
 void imgui_world_light_edit( ui_context *ctx, world_instance *world );
 
-#define WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( WORLD, SHADER )            \
-   world_link_lighting_ub( WORLD, _shader_##SHADER.id );                \
-   world_bind_position_texture( WORLD, _shader_##SHADER.id,             \
-                                _uniform_##SHADER##_g_world_depth, 2 ); \
-   world_bind_light_array( WORLD, _shader_##SHADER.id,                  \
-                           _uniform_##SHADER##_uLightsArray, 3 );       \
-   world_bind_light_index( WORLD, _shader_##SHADER.id,                  \
-                           _uniform_##SHADER##_uLightsIndex, 4 );
-
+#endif
index fe85807001ecd5040cd66ae12661279e2175d5ce..79972f878b6103b824c7ed46c4f5cd14585e9f4e 100644 (file)
@@ -1,28 +1,3 @@
-#pragma once
-
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software - All Rights Reserved
- *
- * World routes
- */
-
-#include <time.h>
-#include "entity.h"
-#include "world_routes.h"
-#include "world_gate.h"
-#include "world_load.h"
-#include "network.h"
-
-#include "font.h"
-#include "gui.h"
-#include "network_msg.h"
-#include "network_common.h"
-
-#include "shaders/scene_route.h"
-#include "shaders/routeui.h"
-#include "ent_region.h"
-#include "scene_rigidbody.h"
-
 void world_routes_clear( world_instance *world )
 {
    for( u32 i=0; i<af_arrcount( &world->ent_route ); i++ )
@@ -50,7 +25,7 @@ static void world_routes_time_lap( u32 route_index )
    world_instance *world = &_world.main;
    ent_route *route = af_arritm( &world->ent_route, route_index );
 
-   const char *route_name = af_str( &world->meta.af, route->pstr_name);
+   const char *route_name = af_str( world->meta.packed_strings, route->pstr_name);
    vg_info( "------- time lap %s -------\n", route_name );
 
    double start_time = 0.0;
@@ -125,11 +100,11 @@ static void world_routes_time_lap( u32 route_index )
 
       if( (route->flags & k_ent_route_flag_achieve_gold) && !(original_flags & k_ent_route_flag_achieve_gold) )
       {
-         gui_notify( "\xb3 Route completed in gold!", 5.0f, k_ui_yellow );
+         _gui_notify( "\xb3 Route completed in gold!", 5.0f, k_ui_yellow );
       }
       else if( (route->flags & k_ent_route_flag_achieve_silver) && !(original_flags & k_ent_route_flag_achieve_silver) )
       {
-         gui_notify( "\xb3 Route completed in silver!", 5.0f, k_ui_fg );
+         _gui_notify( "\xb3 Route completed in silver!", 5.0f, k_ui_fg );
       }
 
       struct ent_script_event event;
@@ -151,7 +126,7 @@ static void world_routes_time_lap( u32 route_index )
 
       char mod_uid[ ADDON_UID_MAX ];
       addon_make_uid( _world.main.addon_id, mod_uid );
-      network_publish_laptime( mod_uid, af_str( &world->meta.af, route->pstr_name ), lap_time );
+      network_publish_laptime( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ), lap_time );
    }
 
    route->valid_checkpoints = valid_sections+1;
@@ -270,42 +245,43 @@ static void world_routes_debug( world_instance *world )
 }
 
 
-static 
-void world_routes_place_curve( world_instance *world, ent_route *route,
-                               v4f h[3], v3f n0, v3f n2, scene_context *scene )
+static void world_routes_place_curve( world_instance *world, ent_route *route,
+                                      v4f h[3], v3f n0, v3f n2, scene_builder_context *builder )
 {
-   float t;
+   f32 t;
    v3f p, pd;
    int last_valid=0;
 
-   float total_length = 0.0f,
-         travel_length = 0.0;
+   f32 total_length = 0.0f,
+       travel_length = 0.0;
 
    v3f last;
    v3_copy( h[0], last );
-   for( int it=0; it<128; it ++ ){
-      t = (float)(it+1) * (1.0f/128.0f);
+   for( int it=0; it<128; it ++ )
+   {
+      t = (f32)(it+1) * (1.0f/128.0f);
       eval_bezier3( h[0], h[1], h[2], t, p );
       total_length += v3_dist( p, last );
       v3_copy( p, last );
    }
 
-   float patch_size = 4.0f,
-         patch_count = ceilf( total_length / patch_size );
+   f32 patch_size = 4.0f,
+       patch_count = ceilf( total_length / patch_size );
 
    t = 0.0f;
    v3_copy( h[0], last );
 
-   for( int it=0; it<128; it ++ ){
-      float const k_sample_dist = 0.0025f,
-                  k_line_width = 1.5f;
+   for( int it=0; it<128; it ++ )
+   {
+      f32 const k_sample_dist = 0.0025f,
+                k_line_width = 1.5f;
 
       eval_bezier3( h[0], h[1], h[2], t, p );
       eval_bezier3( h[0], h[1], h[2], t+k_sample_dist, pd );
 
       travel_length += v3_dist( p, last );
 
-      float mod = k_sample_dist / v3_dist( p, pd );
+      f32 mod = k_sample_dist / v3_dist( p, pd );
 
       v3f v0,up, right;
 
@@ -317,7 +293,7 @@ void world_routes_place_curve( world_instance *world, ent_route *route,
       v3_cross( up, v0, right );
       v3_normalize( right );
 
-      float cur_x = (1.0f-t)*h[0][3] + t*h[2][3];
+      f32 cur_x = (1.0f-t)*h[0][3] + t*h[2][3];
       
       v3f sc, sa, sb, down;
       v3_muladds( p, right, cur_x * k_line_width, sc );
@@ -333,7 +309,8 @@ void world_routes_place_curve( world_instance *world, ent_route *route,
       int resa = ray_world( world, sa, down, &ha, k_material_flag_ghosts ),
           resb = ray_world( world, sb, down, &hb, k_material_flag_ghosts );
 
-      if( resa && resb ){
+      if( resa && resb )
+      {
          struct world_surface *surfa = ray_hit_surface( world, &ha ),
                               *surfb = ray_hit_surface( world, &hb );
 
@@ -342,7 +319,7 @@ void world_routes_place_curve( world_instance *world, ent_route *route,
          {
             scene_vert va, vb;
 
-            float gap = vg_fractf(cur_x*0.5f)*0.02f;
+            f32 gap = vg_fractf(cur_x*0.5f)*0.02f;
             
             v3_muladds( ha.pos, up, 0.06f+gap, va.co );
             v3_muladds( hb.pos, up, 0.06f+gap, vb.co );
@@ -350,24 +327,23 @@ void world_routes_place_curve( world_instance *world, ent_route *route,
             scene_vert_pack_norm( &va, up, 0.0f );
             scene_vert_pack_norm( &vb, up, 0.0f );
 
-            float t1 = (travel_length / total_length) * patch_count;
+            f32 t1 = (travel_length / total_length) * patch_count;
             va.uv[0] = t1;
             va.uv[1] = 0.0f;
             vb.uv[0] = t1;
             vb.uv[1] = 1.0f;
 
-            scene_push_vert( scene, &va );
-            scene_push_vert( scene, &vb );
+            scene_builder_push_vert( builder, &va );
+            scene_builder_push_vert( builder, &vb );
 
-            if( last_valid ){
+            if( last_valid )
+            {
                /* Connect them with triangles */
-               scene_push_tri( scene, (u32[3]){ 
-                     last_valid+0-2, last_valid+1-2, last_valid+2-2} );
-               scene_push_tri( scene, (u32[3]){ 
-                     last_valid+1-2, last_valid+3-2, last_valid+2-2} );
+               scene_builder_push_tri( builder, (u32[3]){ last_valid+0-2, last_valid+1-2, last_valid+2-2} );
+               scene_builder_push_tri( builder, (u32[3]){ last_valid+1-2, last_valid+3-2, last_valid+2-2} );
             }
             
-            last_valid = scene->vertex_count;
+            last_valid = builder->scene.vertex_count;
          }
          else
             last_valid = 0;
@@ -386,7 +362,7 @@ void world_routes_place_curve( world_instance *world, ent_route *route,
    }
 }
 
-static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_context *sc )
+static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_builder_context *builder )
 {
    ent_route *route = af_arritm( &world->ent_route, route_id );
    u8 colour[4];
@@ -394,7 +370,6 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
    colour[1] = route->colour[1] * 255.0f;
    colour[2] = route->colour[2] * 255.0f;
    colour[3] = route->colour[3] * 255.0f;
-
    u32 last_valid = 0;
 
    for( int i=0; i<route->checkpoints_count; i++ )
@@ -421,7 +396,7 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
 
       v3_add( (v3f){0.0f,0.1f,0.0f}, start_gate->co[0], p[0] );
       p[0][3]  = start_gate->ref_count;
-      p[0][3] -= (float)start_gate->route_count * 0.5f;
+      p[0][3] -= (f32)start_gate->route_count * 0.5f;
       start_gate->ref_count ++;
 
       if( !c0->path_count )
@@ -440,10 +415,9 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
                                           index->index );
          v3f v0;
          v3_sub( rn->co, both[j]->co[0], v0 );
-         float d = v3_dot( v0, both[j]->to_world[2] );
+         f32 d = v3_dot( v0, both[j]->to_world[2] );
 
-         v3_muladds( both[j]->co[0], both[j]->to_world[2], d, 
-                     temp_alignments[j] );
+         v3_muladds( both[j]->co[0], both[j]->to_world[2], d, temp_alignments[j] );
          v3_add( (v3f){0.0f,0.1f,0.0f}, temp_alignments[j], temp_alignments[j]);
       }
 
@@ -462,7 +436,7 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
             v3_copy( rn->co, p[1] );
 
          p[1][3] = rn->ref_count;
-         p[1][3] -= (float)rn->ref_total * 0.5f;
+         p[1][3] -= (f32)rn->ref_total * 0.5f;
          rn->ref_count ++;
 
          if( j+1 < c0->path_count )
@@ -476,7 +450,7 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
                v3_lerp( p[1], rn->co, 0.5f, p[2] );
 
             p[2][3] = rn->ref_count;
-            p[2][3] -= (float)rn->ref_total * 0.5f;
+            p[2][3] -= (f32)rn->ref_total * 0.5f;
          }
          else
          {
@@ -487,7 +461,7 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
             if( i == route->checkpoints_count-1)
                p[2][3] -= 1.0f;
 
-            p[2][3] -= (float)collector->route_count * 0.5f;
+            p[2][3] -= (f32)collector->route_count * 0.5f;
             //collector->ref_count ++;
          }
 
@@ -495,10 +469,10 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
           * --------------------------------------*/
          v3f surf0, surf2, n0, n2;
 
-         if( bh_closest_point( world->geo_bh, p[0], surf0, 5.0f ) == -1 )
+         if( bh_closest_point( &world->geometry_bh, p[0], surf0, 5.0f ) == -1 )
             v3_add( (v3f){0.0f,-0.1f,0.0f}, p[0], surf0 );
 
-         if( bh_closest_point( world->geo_bh, p[2], surf2, 5.0f ) == -1 )
+         if( bh_closest_point( &world->geometry_bh, p[2], surf2, 5.0f ) == -1 )
             v3_add( (v3f){0.0f,-0.1f,0.0f}, p[2], surf2 );
 
          v3_sub( surf0, p[0], n0 );
@@ -506,14 +480,14 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id, scene_
          v3_normalize( n0 );
          v3_normalize( n2 );
 
-         world_routes_place_curve( world, route, p, n0, n2, sc );
+         world_routes_place_curve( world, route, p, n0, n2, builder );
 
          /* --- */
          v4_copy( p[2], p[0] );
       }
    }
 
-   scene_copy_slice( sc, &route->sm );
+   scene_builder_get_submesh( builder, &route->sm );
 }
 
 struct world_surface *world_tri_index_surface( world_instance *world, 
@@ -524,9 +498,8 @@ struct world_surface *world_tri_index_surface( world_instance *world,
  */
 void world_gen_routes_generate( world_instance *world )
 {
-   THREAD_1;
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
    vg_info( "Generating route meshes\n" );
-   vg_async_task *task = scene_alloc_async( &world->scene_lines, &world->mesh_route_lines, 200000, 300000 );
 
    for( u32 i=0; i<af_arrcount(&world->ent_gate); i++ )
    {
@@ -546,10 +519,11 @@ void world_gen_routes_generate( world_instance *world )
       rn->ref_total = 0;
    }
 
-   for( u32 k=0; k<af_arrcount(&world->ent_route); k++ ){
+   for( u32 k=0; k<af_arrcount(&world->ent_route); k++ )
+   {
       ent_route *route = af_arritm( &world->ent_route, k );
-
-      for( int i=0; i<route->checkpoints_count; i++ ){
+      for( int i=0; i<route->checkpoints_count; i++ )
+      {
          int i0 = route->checkpoints_start+i,
              i1 = route->checkpoints_start+((i+1)%route->checkpoints_count);
 
@@ -563,20 +537,23 @@ void world_gen_routes_generate( world_instance *world )
          if( !c0->path_count )
             continue;
 
-         for( int j=0; j<c0->path_count; j ++ ){
-            ent_path_index *index = af_arritm( &world->ent_path_index, 
-                                                c0->path_start+j );
-            ent_route_node *rn = af_arritm( &world->ent_route_node,
-                                             index->index );
+         for( int j=0; j<c0->path_count; j ++ )
+         {
+            ent_path_index *index = af_arritm( &world->ent_path_index, c0->path_start+j );
+            ent_route_node *rn = af_arritm( &world->ent_route_node, index->index );
             rn->ref_total ++;
          }
       }
    }
 
+   u32 temp_frame = _vg_start_temp_frame();
+   scene_builder_context builder;
+   scene_builder_init( &builder, 200000, 300000, _vg_temp_stack() );
    for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
-      world_routes_gen_meshes( world, i, &world->scene_lines );
+      world_routes_gen_meshes( world, i, &builder );
+   scene_builder_upload_async( &builder, &world->line_scene_mesh );
+   _vg_end_temp_frame( temp_frame );
 
-   vg_async_task_dispatch( task, async_scene_upload );
    world_routes_clear( world );
 }
 
@@ -608,7 +585,7 @@ void world_gen_routes_ent_init( world_instance *world )
          route->flags |= k_ent_route_flag_out_of_zone;
 
       route->anon.official_track_id = 0xffffffff;
-      const char *route_name = af_str( &world->meta.af, route->pstr_name );
+      const char *route_name = af_str( world->meta.packed_strings, route->pstr_name );
       for( u32 j=0; j<VG_ARRAY_LEN(track_infos); j ++ )
       {
          if( !strcmp( track_infos[j].name, route_name ))
@@ -666,8 +643,10 @@ void world_gen_routes_ent_init( world_instance *world )
    world_routes_clear( world );
 }
 
-void world_routes_recv_scoreboard( world_instance *world, vg_msg *body, u32 route_id, enum request_status status )
+void world_routes_recv_scoreboard( world_instance *world, vg_kvs *kvs, u32 route_id, enum request_status status )
 {
+   // FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////FIXME////
+#if 0
    if( route_id >= af_arrcount( &world->ent_route ) )
    {
       vg_error( "Scoreboard route_id out of range (%u)\n", route_id );
@@ -691,6 +670,7 @@ void world_routes_recv_scoreboard( world_instance *world, vg_msg *body, u32 rout
 
    memcpy( board->data, body->buf, body->max );
    board->data_len = body->max;
+#endif
 }
 
 /* 
@@ -699,7 +679,7 @@ void world_routes_recv_scoreboard( world_instance *world, vg_msg *body, u32 rout
  * -----------------------------------------------------------------------------
  */
 
-void world_routes_init(void)
+VG_API void _world_routes_init(void)
 {
    _world.current_run_version = 200;
    _world.time = 300.0;
@@ -731,56 +711,44 @@ void world_routes_fixedupdate( world_instance *world )
    _null.inv_mass = 0.0f;
    m3x3_zero( _null.iI );
 
-   for( u32 i=0; i<world_render.text_particle_count; i++ ){
+   for( u32 i=0; i<world_render.text_particle_count; i++ )
+   {
       struct text_particle *particle = &world_render.text_particles[i];
-
-      if( rb_global_has_space() ){
+      if( rb_global_has_space() )
+      {
          rb_ct *buf = rb_global_buffer();
-
-         int l = rb_sphere__scene( particle->rb.to_world,
-                                   particle->radius,
-                                   NULL, world->geo_bh, buf,
+         i32 l = rb_sphere__scene( particle->rb.to_world, particle->radius, NULL, &world->geometry_bh, buf,
                                    k_material_flag_ghosts );
-
-         for( int j=0; j<l; j++ ){
+         for( int j=0; j<l; j++ )
+         {
             buf[j].rba = &particle->rb;
             buf[j].rbb = &_null;
          }
-
          rb_contact_count += l;
       }
    }
 
-   rb_presolve_contacts( rb_contact_buffer, 
-                         vg.time_fixed_delta, rb_contact_count );
+   rb_presolve_contacts( rb_contact_buffer, vg.time_fixed_delta, rb_contact_count );
 
-   for( int i=0; i<rb_contact_count; i++ ){
+   for( int i=0; i<rb_contact_count; i++ )
       rb_contact_restitution( rb_contact_buffer+i, vg_randf64(&vg.rand) );
-   }
 
-   for( int i=0; i<6; i++ ){
+   for( int i=0; i<6; i++ )
       rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-   }
 
-   for( u32 i=0; i<world_render.text_particle_count; i++ ){
+   for( u32 i=0; i<world_render.text_particle_count; i++ )
+   {
       struct text_particle *particle = &world_render.text_particles[i];
       rb_iter( &particle->rb );
    }
 
-   for( u32 i=0; i<world_render.text_particle_count; i++ ){
+   for( u32 i=0; i<world_render.text_particle_count; i++ )
+   {
       struct text_particle *particle = &world_render.text_particles[i];
       rb_update_matrices( &particle->rb );
    }
 }
 
-void bind_terrain_noise(void);
-void world_bind_light_array( world_instance *world,
-                             GLuint shader, GLuint location, 
-                             int slot );
-void world_bind_light_index( world_instance *world,
-                             GLuint shader, GLuint location, 
-                             int slot );
-
 void world_routes_update_timer_texts( world_instance *world )
 {
    world_render.timer_text_count = 0;
@@ -813,10 +781,10 @@ void world_routes_update_timer_texts( world_instance *world )
             }
          }
 
-         float h0 = 0.8f,
-               h1 = 1.2f,
-               depth = 0.4f,
-               size = 0.4f;
+         f32 h0 = 0.8f,
+             h1 = 1.2f,
+             depth = 0.4f,
+             size = 0.4f;
 
          struct timer_text *text = &world_render.timer_texts[ world_render.timer_text_count ++ ];
          text->gate = gate;
@@ -830,7 +798,7 @@ void world_routes_update_timer_texts( world_instance *world )
             double lap_time = _world.time - route->timing_base,
                    time_centiseconds = lap_time * 100.0;
 
-            if( time_centiseconds > (float)0xfffe ) time_centiseconds = 0.0;
+            if( time_centiseconds > (f32)0xfffe ) time_centiseconds = 0.0;
 
             u16 centiseconds = time_centiseconds,
                 seconds      = centiseconds / 100,
@@ -845,32 +813,32 @@ void world_routes_update_timer_texts( world_instance *world )
             
             if( minutes )
             {
-               vg_strcati32r( &str, minutes, 1, ' ' );
+               vg_strcati64r( &str, minutes, 10, 1, ' ' );
                vg_strcatch( &str, ':' );
             }
             
             if( seconds >= 10 || minutes )
             {
-               vg_strcati32r( &str, seconds, 2, '0' );
+               vg_strcati64r( &str, seconds, 10, 2, '0' );
             }
             else
             {
-               vg_strcati32r( &str, seconds, 1, '0' );
+               vg_strcati64r( &str, seconds, 10, 1, '0' );
             }
 
             vg_strcatch( &str, '.' );
-            vg_strcati32r( &str, centiseconds, 1, '0' );
+            vg_strcati64r( &str, centiseconds, 10, 1, '0' );
          }
          else
          {
-            vg_strcati32r( &str, route->valid_checkpoints, 1, ' ' );
+            vg_strcati64r( &str, route->valid_checkpoints, 10, 1, ' ' );
             vg_strcatch( &str, '/' );
-            vg_strcati32r( &str, route->checkpoints_count + 1, 1, ' ' );
+            vg_strcati64r( &str, route->checkpoints_count + 1, 10, 1, ' ' );
          }
    
          gui_font3d.font = &gui.font;
-         float align_r  = font3d_string_width( 0, text->text );
-               align_r *= size;
+         f32 align_r  = font3d_string_width( 0, text->text );
+             align_r *= size;
 
          v3f positions[] = {
             { -0.92f, h0, depth },
@@ -889,7 +857,7 @@ void world_routes_update_timer_texts( world_instance *world )
          ent_gate_get_mdl_mtx( gate, mmdl );
 
          m3x3_copy( mmdl, text->transform );
-         float ratio = v3_length(text->transform[0]) / v3_length(text->transform[1]);
+         f32 ratio = v3_length(text->transform[0]) / v3_length(text->transform[1]);
 
          m3x3_scale( text->transform, (v3f){ size, size*ratio, 0.1f } );
          m4x3_mulv( mmdl, positions[j], text->transform[3] );
@@ -924,7 +892,7 @@ void world_routes_fracture( world_instance *world, ent_gate *gate, v3f imp_co, v
       v3_zero( offset );
 
       v4f colour;
-      float brightness = 0.3f + world->ub_lighting.g_day_phase;
+      f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
       v3_muls( text->route->colour, brightness, colour );
       colour[3] = 1.0f-text->route->factive;
 
@@ -990,7 +958,7 @@ static void render_gate_markers( m4x3f world_mmdl, int run_id, ent_gate *gate )
 
          m4x3_mul( world_mmdl, mmdl, mmdl );
          shader_model_gate_uMdl( mmdl );
-         mdl_draw_submesh( &world_gates.sm_marker[j] );
+         vg_model_draw_submesh( &_world_gates.sm_marker[j] );
          break;
       }
    }
@@ -1002,15 +970,8 @@ void render_world_routes( world_instance *world,
                           int viewing_from_gate, int viewing_from_hub )
 {
    shader_scene_route_use();
-   shader_scene_route_uTexGarbage(0);
-   world_link_lighting_ub( host_world, _shader_scene_route.id );
-   world_bind_position_texture( host_world, _shader_scene_route.id, 
-                        _uniform_scene_route_g_world_depth, 2 );
-   world_bind_light_array( host_world, _shader_scene_route.id,
-                        _uniform_scene_route_uLightsArray, 3 );
-   world_bind_light_index( host_world, _shader_scene_route.id,
-                                 _uniform_scene_route_uLightsIndex, 4 );
-   bind_terrain_noise();
+   world_link_terrain_noise( host_world, k_uniform_scene_route_uTexGarbage );
+   WORLD_LINK_LIGHTING( host_world, scene_route );
 
    shader_scene_route_uPv( cam->mtx.pv );
 
@@ -1041,12 +1002,10 @@ void render_world_routes( world_instance *world,
 
    shader_scene_route_uCamera( cam->transform[3] );
 
-   mesh_bind( &world->mesh_route_lines );
-
+   scene_mesh_bind( &world->line_scene_mesh );
    for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
    {
       ent_route *route = af_arritm( &world->ent_route, i );
-
       f32 t = viewing_from_hub? 1.0f: route->factive;
 
       v4f colour;
@@ -1054,21 +1013,21 @@ void render_world_routes( world_instance *world,
       colour[3] = t*0.2f;
 
       shader_scene_route_uColour( colour );
-      mdl_draw_submesh( &route->sm );
+      vg_model_draw_submesh( &route->sm );
    }
 
    /* timers
     * ---------------------------------------------------- */
    if( !viewing_from_gate && !viewing_from_hub )
    {
-      font3d_bind( &gui.font, k_font_shader_default, 0, world, cam );
+      font3d_bind( &gui.font, k_font_shader_default, 0, cam );
 
       for( u32 i=0; i<world_render.timer_text_count; i++ )
       {
          struct timer_text *text = &world_render.timer_texts[i];
 
          v4f colour;
-         float brightness = 0.3f + world->ub_lighting.g_day_phase;
+         f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
          v3_muls( text->route->colour, brightness, colour );
          colour[3] = 1.0f-text->route->factive;
 
@@ -1097,8 +1056,7 @@ void render_world_routes( world_instance *world,
          m4x3_mul( model, particle->mlocal, particle->mdl );
          shader_model_font_uMdl( particle->mdl );
          shader_model_font_uColour( particle->colour );
-
-         mesh_drawn( particle->glyph->indice_start, particle->glyph->indice_count );
+         vg_model_draw_elements( particle->glyph->indice_start, particle->glyph->indice_count );
       }
    }
 
@@ -1109,11 +1067,8 @@ void render_world_routes( world_instance *world,
    shader_model_gate_uPv( cam->mtx.pv );
    shader_model_gate_uCam( cam->pos );
    shader_model_gate_uTime( vg.time*0.25f );
-   shader_model_gate_uInvRes( (v2f){
-         1.0f / (float)vg.window_x,
-         1.0f / (float)vg.window_y });
-
-   mesh_bind( &world_gates.mesh );
+   shader_model_gate_uInvRes( (v2f){ 1.0f/(f32)_vg_window.w, 1.0f/(f32)_vg_window.h });
+   vg_model_bind_mesh( &_world_gates.model );
 
    /* skip writing into the motion vectors for this */
    glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
@@ -1139,13 +1094,15 @@ void render_world_routes( world_instance *world,
          }
       }
    }
-   else{
-      for( u32 i=0; i<af_arrcount(&world->ent_route); i++ ){
+   else
+   {
+      for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
+      {
          ent_route *route = af_arritm( &world->ent_route, i );
-
-         if( route->active_checkpoint != 0xffff ){
+         if( route->active_checkpoint != 0xffff )
+         {
             v4f colour;
-            float brightness = 0.3f + world->ub_lighting.g_day_phase;
+            f32 brightness = 0.3f + world_render.ub_lighting.g_day_phase;
             v3_muls( route->colour, brightness, colour );
             colour[3] = 1.0f-route->factive;
 
index 09e183b32b52a12ff97bba6ed5535efdba450bd7..74ad39a9b7e36d16329162146cf98503e2fe2b60 100644 (file)
@@ -1,14 +1,9 @@
-/*
- * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_routes.c"
+#else
 
-#pragma once
-#include "vg/vg_camera.h"
-#include "vg/vg_msg.h"
-#include "world.h"
-#include "network_msg.h"
+VG_API void _world_routes_init(void);
 
-void world_routes_init(void);
 void world_routes_fracture( world_instance *world, ent_gate *gate, v3f imp_co, v3f imp_v );
 void world_routes_activate_entry_gate( world_instance *world, ent_gate *rg );
 void render_world_routes( world_instance *world, 
@@ -22,6 +17,6 @@ void world_routes_update_timer_texts( world_instance *world );
 void world_routes_update( world_instance *world );
 void world_routes_fixedupdate( world_instance *world );
 void world_routes_clear( world_instance *world );
-void world_routes_recv_scoreboard( world_instance *world, 
-                                   vg_msg *body, u32 route_id,
-                                   enum request_status status );
+void world_routes_recv_scoreboard( world_instance *world, vg_kvs *kvs, u32 route_id, enum request_status status );
+
+#endif
index ec6c115854d16c2b5fdc8627d746679bf71dcb3b..4d350d085472ce8bfab79f7f1aa3a4cbfed8c9fb 100644 (file)
@@ -1,8 +1,3 @@
-#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,
@@ -117,9 +112,9 @@ static void ent_route_imgui( ui_context *ctx, world_instance *world, ent_route *
             else
                vg_strcatch( &str, '-' );
 
-            vg_strcati32( &str, s );
+            vg_strcati64( &str, s, 10 );
             vg_strcatch( &str, '.' );
-            vg_strcati32( &str, ds );
+            vg_strcati64( &str, ds, 10 );
 
             ui_text( ctx, rect, buf, 1, k_ui_align_middle_center, 0 );
          }
index 70c0fcd06965eafb27e632b133c18707e8b0d592..016186f8dae70d876a6e31d8b71deb8eb9f89a1f 100644 (file)
@@ -1,5 +1,8 @@
-#pragma once
-#include "world_routes.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_routes_ui.c"
+#else
 
 struct route_ui{};
 void world_routes_imgui( ui_context *ctx, world_instance *world );
+
+#endif
index 04a0585f57a6dc4365f9d8d1fdd512341e8295d8..4f1b01e135938c2cd11b3e7db36e1e6ab000d4a1 100644 (file)
@@ -1,14 +1,3 @@
-#ifndef SFD_C
-#define SFD_C
-
-#include "world_sfd.h"
-#include "shaders/scene_scoretext.h"
-#include "shaders/scene_vertex_blend.h"
-#include "network.h"
-#include "entity.h"
-#include "network_common.h"
-#include "world_routes.h"
-
 struct world_sfd world_sfd;
 
 static f32 sfd_encode_glyph( char c ){
@@ -94,7 +83,7 @@ void world_sfd_compile_active_scores(void)
    {
       board = &world->leaderboard_cache[ world_sfd.active_route_board ];
       ent_route *route = af_arritm( &world->ent_route, world_sfd.active_route_board );
-      title = af_str( &world->meta.af, route->pstr_name );
+      title = af_str( world->meta.packed_strings, route->pstr_name );
    }
 
    for( u32 i=0; i<13; i++ )
@@ -126,11 +115,14 @@ void world_sfd_compile_active_scores(void)
       vg_str s;
       vg_strnull( &s, buf, 32 );
       vg_strcat( &s, "Error: " );
-      vg_strcati32( &s, board->status );
+      vg_strcati64( &s, board->status, 10 );
       sfd_encode( (v2i){-1,4}, buf, k_world_sfd_center );
       return;
    }
 
+   // FIXME FIXME
+   sfd_encode( (v2i){-1,0}, "FIX ME!!!!!", k_world_sfd_right );
+#if 0
    vg_msg body;
    vg_msg_init( &body, board->data, board->data_len );
 
@@ -157,7 +149,7 @@ void world_sfd_compile_active_scores(void)
          char buf[100];
          vg_str str;
          vg_strnull( &str, buf, 100 );
-         vg_strcati32( &str, l );
+         vg_strcati64( &str, l, 10 );
          vg_strcat( &str, " " );
 
          if( username )
@@ -180,11 +172,11 @@ void world_sfd_compile_active_scores(void)
          seconds     %= 60;
          minutes     %= 60;
          if( minutes > 9 ) vg_strcat( &str, "?" );
-         else vg_strcati32( &str, minutes );
+         else vg_strcati64( &str, minutes, 10 );
          vg_strcat( &str, ":" );
-         vg_strcati32r( &str, seconds, 2, '0' );
+         vg_strcati64r( &str, seconds, 10, 2, '0' );
          vg_strcat( &str, "." );
-         vg_strcati32r( &str, centiseconds, 2, '0' );
+         vg_strcati64r( &str, centiseconds, 10, 2, '0' );
          sfd_encode( (v2i){-1,l}, str.buffer, k_world_sfd_right );
          l ++;
 
@@ -195,6 +187,7 @@ void world_sfd_compile_active_scores(void)
    {
       sfd_encode( (v2i){-1,4}, "No records", k_world_sfd_center );
    }
+#endif
 }
 
 void world_sfd_update( world_instance *world, v3f pos )
@@ -229,7 +222,7 @@ void world_sfd_update( world_instance *world, v3f pos )
 
             char mod_uid[ ADDON_UID_MAX ];
             addon_make_uid( _world.main.addon_id, mod_uid );
-            network_request_scoreboard( mod_uid, af_str( &world->meta.af, route->pstr_name ),
+            network_request_scoreboard( mod_uid, af_str( world->meta.packed_strings, route->pstr_name ),
                                         NETWORK_LEADERBOARD_ALLTIME_AND_CURRENT_WEEK, closest );
          }
       }
@@ -263,10 +256,11 @@ void world_sfd_update( world_instance *world, v3f pos )
 void bind_terrain_noise(void);
 void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
 {
+#if 0
    mesh_bind( &world_sfd.mesh_display );
    shader_scene_scoretext_use();
    shader_scene_scoretext_uTexMain(1);
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_scoretext );
+   WORLD_LINK_LIGHTING( world, scene_scoretext );
 
    bind_terrain_noise();
 
@@ -293,11 +287,14 @@ void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
    shader_scene_vertex_blend_use();
    shader_scene_vertex_blend_uTexGarbage(0);
    shader_scene_vertex_blend_uTexGradients(1);
-   WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_vertex_blend );
+   WORLD_LINK_LIGHTING( world, scene_vertex_blend );
 
    bind_terrain_noise();
-   glActiveTexture( GL_TEXTURE1 );
-   glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
+
+   VG_ASSERT(0);
+   // FIXME FIXME FIXME
+   // glActiveTexture( GL_TEXTURE1 );
+   // glBindTexture( GL_TEXTURE_2D, world_sfd.tex_scoretex );
 
    shader_scene_vertex_blend_uPv( cam->mtx.pv );
    shader_scene_vertex_blend_uPvmPrev( pvm_prev );
@@ -305,20 +302,30 @@ void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
    shader_scene_vertex_blend_uCamera( cam->transform[3] );
    
    mesh_bind( &world_sfd.mesh_base );
-   mdl_draw_submesh( &world_sfd.sm_base );
+   vg_model_draw_submesh( &world_sfd.sm_base );
+#endif
 }
 
-void world_sfd_init(void)
+static void _world_sfd_load_content( void *_, vg_async_info *async )
 {
-   THREAD_1;
-   vg_info( "world_sfd_init\n" );
-   vg_stack_clear( &vg.scratch );
+   // FIXME FIXME FIXME
+   VG_ASSERT( 0 );
+#if 0
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_BACKGROUND ) );
+
+   u32 temp_frame = _vg_start_temp_frame();
+   vg_model scoreboard_mdl;
+   VG_ASSERT( vg_model_load( &scoreboard_mdl, VG_MODEL_ENGINE_PROCEDURAL_SOURCE, "models/rs_scoretext.mdl",
+                             _vg_temp_stack() ));
+
+
+   _vg_end_temp_frame( temp_frame );
+
 
    mdl_context mscoreboard;
-   mdl_open( &mscoreboard, "models/rs_scoretext.mdl", &vg.scratch );
+   mdl_open( &mscoreboard, , &vg.scratch );
    mdl_load_metadata_block( &mscoreboard, &vg.scratch );
    mdl_async_load_glmesh( &mscoreboard, &world_sfd.mesh_base, NULL );
-
    mdl_load_mesh_block( &mscoreboard, &vg.scratch );
 
    scene_context *scene = &world_sfd.scene;
@@ -339,25 +346,28 @@ void world_sfd_init(void)
       {
          scene_vert *vert = &scene->arrvertices[ vert_start+j ];
 
-         float const k_glyph_uvw = 1.0f/64.0f;
+         f32 const k_glyph_uvw = 1.0f/64.0f;
          vert->uv[0] -= k_glyph_uvw * (float)(i-1);
          vert->norm[3] = i*42;
       }
    }
 
-   vg_async_task_dispatch( task, async_scene_upload );
-   vg_tex2d_load_qoi_async_file( "textures/scoretext.qoi", VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &world_sfd.tex_scoretex );
    mdl_close( &mscoreboard );
+#endif
+}
 
-   int w = 27,
+VG_API void _world_sfd_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_sfd_load_content );
+
+   i32 w = 27,
        h = 13;
 
    world_sfd.w = w;
    world_sfd.h = h;
-   world_sfd.buffer = vg_stack_allocate( &vg.rtmem, 2*w*h*sizeof(f32), 8, "SFD Buffer" );
+   world_sfd.buffer = vg_stack_allocate( VG_STACK_USE_HEAP, 2*w*h*sizeof(f32), 8, "SFD Buffer" );
 
-   for( int i=0; i<w*h*2; i++ )
+   for( i32 i=0; i<w*h*2; i++ )
       world_sfd.buffer[i] = 0.0f;
 }
-
-#endif /* WORLD_SFD_C */
index b755647b1711a1e87a5d677c2318550bb3844330..1e52af6f313bd6ffb334c2f859b610d1f6d08ef1 100644 (file)
@@ -1,20 +1,12 @@
-/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-#pragma once
-#include "world.h"
-#include "world_routes.h"
-#include "scene.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_sfd.c"
+#else
 
 struct world_sfd
 {
-   GLuint tex_scoretex;
-
-   glmesh mesh_base, mesh_display;
    mdl_submesh sm_base;
 
    u32 active_route_board;
-   scene_context scene;
 
    //u32 view_weekly;
    u32 run_selecteion;
@@ -25,7 +17,7 @@ struct world_sfd
 
 }
 extern world_sfd;
-void world_sfd_init(void);
+VG_API void _world_sfd_init(void);
 
 enum world_sfd_align {
    k_world_sfd_left,
@@ -37,3 +29,5 @@ void sfd_encode( v2i co, const char *str, enum world_sfd_align align );
 void world_sfd_update( world_instance *world, v3f pos );
 void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform );
 void world_sfd_compile_active_scores(void);
+
+#endif
index 1c825293abdda1b2462c589e2dc2223f94e3b9c9..d3f0fa6dfcdccbc0883d94c77df0c87edd5ba0a4 100644 (file)
@@ -1,5 +1,3 @@
-#include "world_volumes.h"
-
 struct _world_volumes _world_volumes;
 
 void world_volumes_update( world_instance *world, v3f pos )
@@ -37,7 +35,7 @@ void world_volumes_update( world_instance *world, v3f pos )
             {
                if( world_clear_event( k_world_event_interact ) )
                {
-                  gui_helper_reset( k_gui_helper_mode_clear );
+                  _gui_helper_reset( k_gui_helper_mode_clear );
                }
             }
          }
@@ -63,7 +61,7 @@ void world_volumes_update( world_instance *world, v3f pos )
    bh_iter_init_range( 0, &it, pos, radius );
    i32 idx;
 
-   while( bh_next( world->entity_bh, &it, &idx ) )
+   while( bh_next( &world->entity_bh, &it, &idx ) )
    {
       u32 id    = world->entity_list[ idx ],
           type  = mdl_entity_id_type( id ),
@@ -126,10 +124,10 @@ void world_volumes_update( world_instance *world, v3f pos )
                   {
                      if( world_set_event( k_world_event_interact ) )
                      {
-                        gui_helper_reset( k_gui_helper_mode_black_bars );
+                        _gui_helper_reset( k_gui_helper_mode_black_bars );
                         vg_str text;
-                        if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
-                           vg_strcat( &text, af_str( &world->meta.af, volume->interact.pstr_text ) );
+                        if( _gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+                           vg_strcat( &text, af_str( world->meta.packed_strings, volume->interact.pstr_text ) );
                         _world_volumes.active_volume_interact = id;
                      }
                   }
@@ -159,7 +157,7 @@ next_volume:;
          if( world_clear_event( k_world_event_interact ) )
          {
             _world_volumes.active_volume_interact = 0;
-            gui_helper_reset( k_gui_helper_mode_clear );
+            _gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
       else if( button_down( k_srbind_maccept ) && (_cutscene.state == k_cutscene_state_none) 
@@ -171,7 +169,7 @@ next_volume:;
             if( world_clear_event( k_world_event_interact ) )
             {
                _world_volumes.active_volume_interact = 0;
-               gui_helper_reset( k_gui_helper_mode_clear );
+               _gui_helper_reset( k_gui_helper_mode_clear );
             }
          }
 
index 06ccf5f31b79bf58a79159fc8e74e01f6af0358c..b7665403df890f32cdc6afba82b00650d2836e80 100644 (file)
@@ -1,6 +1,6 @@
-#pragma once
-#include "world.h"
-#include "vg/vg_bvh.h"
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_volumes.c"
+#else
 
 struct _world_volumes
 {
@@ -10,3 +10,5 @@ extern _world_volumes;
 
 void world_volumes_update( world_instance *world, v3f pos );
 void world_volumes_start( world_instance *world );
+
+#endif
index e9e74ef55da2f7c964f6095ce0180398948f5d9c..7436b342aae4ccc788baee0886e986b4b39c14ed 100644 (file)
@@ -1,28 +1,14 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#include "world_water.h"
-#include "world_render.h"
-#include "render.h"
-#include "shaders/scene_water.h"
-#include "shaders/scene_water_fast.h"
-#include "scene.h"
-#include "player.h"
-#include "player_walk.h"
-#include "player_dead.h"
-
 struct world_water world_water;
 
-void world_water_init(void)
+static void _world_water_load_content( void *_, vg_async_info *async )
 {
-   vg_info( "world_water_init\n" );
-
-   vg_tex2d_load_qoi_async_file( "textures/water_surf.qoi",
-                                 VG_TEX2D_LINEAR|VG_TEX2D_REPEAT,
-                                 &world_water.tex_water_surf );
+   _vg_tex_load( &world_water.tex_water_surf, "textures/water_surf.qoi", VG_TEX_LINEAR|VG_TEX_REPEAT );
+}
 
-   vg_success( "done\n" );
+VG_API void _world_water_init(void)
+{
+   VG_ASSERT( _vg_thread_has_flags( VG_THREAD_MAIN ) );
+   _vg_async_send( _vg_async_alloc( VG_THREAD_ASYNC_ID, 0 ), (vg_async_fn)_world_water_load_content );
 }
 
 void water_set_surface( world_instance *world, float height )
@@ -31,17 +17,6 @@ void water_set_surface( world_instance *world, float height )
    v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane );
 }
 
-void world_link_lighting_ub( world_instance *world, GLuint shader );
-void world_bind_position_texture( world_instance *world, 
-                                     GLuint shader, GLuint location,
-                                     int slot );
-void world_bind_light_array( world_instance *world,
-                                GLuint shader, GLuint location, 
-                                int slot );
-void world_bind_light_index( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot );
-
 /*
  * Does not write motion vectors
  */
@@ -132,15 +107,11 @@ void render_water_surface( world_instance *world, vg_camera *cam )
       vg_framebuffer_bind_texture( _vg_render.fb_water_reflection, 0, 0 );
       shader_scene_water_uTexMain( 0 );
    
-      glActiveTexture( GL_TEXTURE1 );
-      glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
+      vg_tex_bind( GL_TEXTURE_2D, &world_water.tex_water_surf, 1 );
       shader_scene_water_uTexDudv( 1 );
       
-      shader_scene_water_uInvRes( (v2f){
-            1.0f / (float)vg.window_x,
-            1.0f / (float)vg.window_y });
-
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water );
+      shader_scene_water_uInvRes( (v2f){ 1.0f / (f32)_vg_window.w, 1.0f / (f32)_vg_window.h });
+      WORLD_LINK_LIGHTING( world, scene_water );
 
       vg_framebuffer_bind_texture( _vg_render.fb_water_beneath, 0, 5 );
       shader_scene_water_uTexBack( 5 );
@@ -159,22 +130,21 @@ void render_water_surface( world_instance *world, vg_camera *cam )
       glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
       glBlendEquation(GL_FUNC_ADD);
 
-      mesh_bind( &world->mesh_no_collide );
-
+      scene_mesh_bind( &world->transparent_scene_mesh );
       for( int i=0; i<world->surface_count; i++ )
       {
          struct world_surface *mat = &world->surfaces[i];
-         struct shader_props_water *props = mat->info.props.compiled;
 
          if( mat->info.shader == k_shader_water )
          {
-            shader_scene_water_uShoreColour( props->shore_colour );
-            shader_scene_water_uOceanColour( props->deep_colour );
-            shader_scene_water_uFresnel( props->fresnel );
-            shader_scene_water_uWaterScale( props->water_sale );
-            shader_scene_water_uWaveSpeed( props->wave_speed );
-
-            mdl_draw_submesh( &mat->sm_no_collide );
+            VG_ASSERT(i);
+            union shader_props *props = &world->meta.shader_props[i-1];
+            shader_scene_water_uShoreColour( props->water.shore_colour );
+            shader_scene_water_uOceanColour( props->water.deep_colour );
+            shader_scene_water_uFresnel( props->water.fresnel );
+            shader_scene_water_uWaterScale( props->water.water_sale );
+            shader_scene_water_uWaveSpeed( props->water.wave_speed );
+            vg_model_draw_submesh( &mat->sm_no_collide );
          }
       }
 
@@ -185,15 +155,13 @@ void render_water_surface( world_instance *world, vg_camera *cam )
    {
       shader_scene_water_fast_use();
 
-      glActiveTexture( GL_TEXTURE1 );
-      glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
+      vg_tex_bind( GL_TEXTURE_2D, &world_water.tex_water_surf, 1 );
       shader_scene_water_fast_uTexDudv( 1 );
 
       shader_scene_water_fast_uTime( _world.time );
       shader_scene_water_fast_uCamera( cam->transform[3] );
       shader_scene_water_fast_uSurfaceY( world->water.height );
-
-      WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water_fast );
+      WORLD_LINK_LIGHTING( world, scene_water_fast );
 
       m4x3f full;
       m4x3_identity( full );
@@ -205,19 +173,19 @@ void render_water_surface( world_instance *world, vg_camera *cam )
       glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
       glBlendEquation(GL_FUNC_ADD);
 
-      mesh_bind( &world->mesh_no_collide );
-
+      scene_mesh_bind( &world->transparent_scene_mesh );
       for( int i=0; i<world->surface_count; i++ )
       {
          struct world_surface *mat = &world->surfaces[i];
-         struct shader_props_water *props = mat->info.props.compiled;
 
          if( mat->info.shader == k_shader_water )
          {
-            shader_scene_water_fast_uShoreColour( props->shore_colour );
-            shader_scene_water_fast_uOceanColour( props->deep_colour );
+            VG_ASSERT(i);
+            union shader_props *props = &world->meta.shader_props[i-1];
+            shader_scene_water_fast_uShoreColour( props->water.shore_colour );
+            shader_scene_water_fast_uOceanColour( props->water.deep_colour );
 
-            mdl_draw_submesh( &mat->sm_no_collide );
+            vg_model_draw_submesh( &mat->sm_no_collide );
          }
       }
 
@@ -242,7 +210,7 @@ static void world_water_drown(void)
    {
       vg_str str;
       struct gui_helper *helper;
-      if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+      if( (helper = _gui_new_helper(input_button_list[k_srbind_reset], &str)) )
       {
          vg_strcat( &str, "Respawn" );
       }
@@ -268,7 +236,7 @@ bool world_water_player_safe( world_instance *world, f32 allowance )
 entity_event_result ent_water_event( ent_event *event )
 {
    world_instance *world = &_world.main;
-   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "drown" ) )
+   if( AF_STR_EQ( world->meta.packed_strings, event->pstr_recieve_event, "drown" ) )
    {
       world_water_drown();
       return k_entity_event_result_OK;
index b2d753da21f35261b811cc66d09db769ddd9be47..672f743a02bb0b27e469b77a649dd60107db835d 100644 (file)
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
+#if defined( SR_IMPLEMENTATION )
+# include "src/world_water.c"
+#else
 
-#pragma once
-#include "world.h"
-
-struct world_water{
-   GLuint tex_water_surf;
+struct world_water
+{
+   vg_tex tex_water_surf;
 }
 extern world_water;
-void world_water_init(void);
+
+VG_API void _world_water_init(void);
 
 void water_set_surface( world_instance *world, f32 height );
 void render_water_texture( world_instance *world, vg_camera *cam );
 void render_water_surface( world_instance *world, vg_camera *cam );
 entity_event_result ent_water_event( ent_event *event );
 bool world_water_player_safe( world_instance *world, f32 allowance );
+
+#endif