diff --git a/.efrocachemap b/.efrocachemap
index e398a06c..3878fa79 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -3932,24 +3932,24 @@
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
- "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/88/6c/03d5c4811e2ffb2f341a042f676e",
- "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3f/c0/7025f06247748ad8f0516389e4f8",
- "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c9/36/4393ce5c02ebf21a6a2dbb0614eb",
- "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/13/7d/2c551af0ebc26c93f52a87b02ca0",
- "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/eb/b2/ff5199a4437852f09d2d7096896d",
- "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/06/5a/d683bd2197262a9baec17b7306a6",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/26/07/08fe94d637f560acfd450d722393",
- "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cc/ae/2855e9d714ea0c7ceaf4f42a4dc2",
- "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/46/fc/16cf6c1cb45381b377c1d3bac058",
- "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/81/de/d2b16c91eed65ab721149488f399",
- "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/5d/89/1ec1c4058821e52e117142c7fbc4",
- "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/9e/90/315e8edc3ab7bc1080d18e29cf8d",
- "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ea/68/8d61d116af2df5617a11e5ae2d9d",
- "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b9/62/fa796628f2840d880dd421f9c821",
- "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f0/d0/e1e69b545cf166ce4e679621307f",
- "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b1/d0/14df0a36c445e8a2e67eb8802911",
- "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/26/eb/3f9b13ea38c9f7af8ff0532258e8",
- "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cc/56/442362d6eab98a42da31ba8cc9d6",
- "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/f9/dd209379992a04c479f4cb5e3e85",
- "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b0/d7/5ec4bfbf10cf520d2c2b85530176"
+ "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/7d/82/ee9dbd4e5f7979376228d6953bf2",
+ "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8b/1b/28311c0a6459e5d4fba5b8646f3e",
+ "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/01/bb/1aa148fa278d31cb6674174b194f",
+ "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/98/7b/5f1bcd5a6ac1916ca35e10c28a30",
+ "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/64/03/694933268214ba930b6f38b9c6c0",
+ "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/e1/49/88c92b0f65857a88f6eaaee04483",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a0/f6/39e7caccbbcd4cd442145c17a05f",
+ "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1d/c6/20d9325e37de411bc6fe3d41d503",
+ "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ab/14/4cf9664fb0de75dcb20b596ded74",
+ "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c3/9a/39b182b32184ae177611078f03ff",
+ "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/70/e2/b993cf8dd5ede4d9e6ce42cd8c24",
+ "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/60/03/166e19fae3db8f6e4b5c6a59a520",
+ "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e8/ed/62a752dbeeca8f5e99725d42e7e7",
+ "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/a9/568023651355fdd0ce7a865c2872",
+ "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0d/25/2d023ef6acd6ae5aa09bf12158d3",
+ "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/42/be/79eec8bc7b2cc914cc6cb8ed0769",
+ "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/83/00/c2e4c96a434c1ac16e9f8b8a401e",
+ "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/03/94/b12016e90c0c650b3c3222bc2453",
+ "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f2/9e/fd1ff58204bf80d0b02edfa79293",
+ "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/26/5c/a738eaa3e553bb00814f2376cb5a"
}
\ No newline at end of file
diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index 2b0fe477..917d442e 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -1009,6 +1009,7 @@
installdir
instancer
interfacetype
+ internalsrc
interstitials
intex
intp
@@ -1370,8 +1371,10 @@
nospeak
nosub
nosyncdir
+ nosyncdirlist
nosyncdirs
nosyncfile
+ nosyncfilelist
nosyncfiles
nosynctool
nosynctools
@@ -1821,6 +1824,7 @@
setactivity
setalpha
setbuild
+ setconfig
setdata
setlanguage
setmusic
diff --git a/ballisticacore-cmake/CMakeLists.txt b/ballisticacore-cmake/CMakeLists.txt
index a1e2aec1..8809727e 100644
--- a/ballisticacore-cmake/CMakeLists.txt
+++ b/ballisticacore-cmake/CMakeLists.txt
@@ -174,6 +174,441 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/external/qr_code_generator/QrCode.cpp
# AUTOGENERATED_PUBLIC_BEGIN (this section is managed by the "update_project" tool)
${BA_SRC_ROOT}/ballistica/app/app.cc
+ ${BA_SRC_ROOT}/ballistica/app/app.h
+ ${BA_SRC_ROOT}/ballistica/app/app_config.h
+ ${BA_SRC_ROOT}/ballistica/app/app_globals.h
+ ${BA_SRC_ROOT}/ballistica/app/headless_app.h
+ ${BA_SRC_ROOT}/ballistica/app/stress_test.h
+ ${BA_SRC_ROOT}/ballistica/app/vr_app.h
+ ${BA_SRC_ROOT}/ballistica/audio/al_sys.cc
+ ${BA_SRC_ROOT}/ballistica/audio/al_sys.h
+ ${BA_SRC_ROOT}/ballistica/audio/audio.cc
+ ${BA_SRC_ROOT}/ballistica/audio/audio.h
+ ${BA_SRC_ROOT}/ballistica/audio/audio_server.cc
+ ${BA_SRC_ROOT}/ballistica/audio/audio_server.h
+ ${BA_SRC_ROOT}/ballistica/audio/audio_source.cc
+ ${BA_SRC_ROOT}/ballistica/audio/audio_source.h
+ ${BA_SRC_ROOT}/ballistica/audio/audio_streamer.cc
+ ${BA_SRC_ROOT}/ballistica/audio/audio_streamer.h
+ ${BA_SRC_ROOT}/ballistica/audio/ogg_stream.cc
+ ${BA_SRC_ROOT}/ballistica/audio/ogg_stream.h
+ ${BA_SRC_ROOT}/ballistica/ballistica.cc
+ ${BA_SRC_ROOT}/ballistica/ballistica.h
+ ${BA_SRC_ROOT}/ballistica/config/config_cmake.h
+ ${BA_SRC_ROOT}/ballistica/config/config_common.h
+ ${BA_SRC_ROOT}/ballistica/core/context.cc
+ ${BA_SRC_ROOT}/ballistica/core/context.h
+ ${BA_SRC_ROOT}/ballistica/core/exception.cc
+ ${BA_SRC_ROOT}/ballistica/core/exception.h
+ ${BA_SRC_ROOT}/ballistica/core/fatal_error.cc
+ ${BA_SRC_ROOT}/ballistica/core/fatal_error.h
+ ${BA_SRC_ROOT}/ballistica/core/inline.cc
+ ${BA_SRC_ROOT}/ballistica/core/inline.h
+ ${BA_SRC_ROOT}/ballistica/core/logging.cc
+ ${BA_SRC_ROOT}/ballistica/core/logging.h
+ ${BA_SRC_ROOT}/ballistica/core/macros.cc
+ ${BA_SRC_ROOT}/ballistica/core/macros.h
+ ${BA_SRC_ROOT}/ballistica/core/module.cc
+ ${BA_SRC_ROOT}/ballistica/core/module.h
+ ${BA_SRC_ROOT}/ballistica/core/object.cc
+ ${BA_SRC_ROOT}/ballistica/core/object.h
+ ${BA_SRC_ROOT}/ballistica/core/thread.cc
+ ${BA_SRC_ROOT}/ballistica/core/thread.h
+ ${BA_SRC_ROOT}/ballistica/core/types.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_draw_snapshot.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_fuse.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_fuse.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_fuse_data.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_height_cache.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_height_cache.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_server.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_server.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_shadow.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_shadow.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_shadow_data.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_volume_light.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_volume_light.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/bg/bg_dynamics_volume_light_data.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/collision.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/collision_cache.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/collision_cache.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/dynamics.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/dynamics.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/impact_sound_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/impact_sound_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_component.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_component.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_condition_node.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_condition_node.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_context.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/material_context.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_message_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_message_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_mod_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_mod_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_user_message_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/node_user_message_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/part_mod_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/part_mod_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/python_call_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/python_call_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/roll_sound_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/roll_sound_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/skid_sound_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/skid_sound_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/sound_material_action.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/material/sound_material_action.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/part.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/part.h
+ ${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.cc
+ ${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.h
+ ${BA_SRC_ROOT}/ballistica/game/account.h
+ ${BA_SRC_ROOT}/ballistica/game/client_controller_interface.h
+ ${BA_SRC_ROOT}/ballistica/game/connection/connection.h
+ ${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client.h
+ ${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client_udp.h
+ ${BA_SRC_ROOT}/ballistica/game/connection/connection_to_host.h
+ ${BA_SRC_ROOT}/ballistica/game/connection/connection_to_host_udp.h
+ ${BA_SRC_ROOT}/ballistica/game/friend_score_set.h
+ ${BA_SRC_ROOT}/ballistica/game/game.h
+ ${BA_SRC_ROOT}/ballistica/game/game_stream.h
+ ${BA_SRC_ROOT}/ballistica/game/host_activity.h
+ ${BA_SRC_ROOT}/ballistica/game/player.h
+ ${BA_SRC_ROOT}/ballistica/game/player_spec.h
+ ${BA_SRC_ROOT}/ballistica/game/score_to_beat.h
+ ${BA_SRC_ROOT}/ballistica/game/session/client_session.h
+ ${BA_SRC_ROOT}/ballistica/game/session/host_session.h
+ ${BA_SRC_ROOT}/ballistica/game/session/net_client_session.h
+ ${BA_SRC_ROOT}/ballistica/game/session/replay_client_session.h
+ ${BA_SRC_ROOT}/ballistica/game/session/session.h
+ ${BA_SRC_ROOT}/ballistica/generic/base64.cc
+ ${BA_SRC_ROOT}/ballistica/generic/base64.h
+ ${BA_SRC_ROOT}/ballistica/generic/buffer.h
+ ${BA_SRC_ROOT}/ballistica/generic/huffman.cc
+ ${BA_SRC_ROOT}/ballistica/generic/huffman.h
+ ${BA_SRC_ROOT}/ballistica/generic/json.cc
+ ${BA_SRC_ROOT}/ballistica/generic/json.h
+ ${BA_SRC_ROOT}/ballistica/generic/lambda_runnable.h
+ ${BA_SRC_ROOT}/ballistica/generic/real_timer.h
+ ${BA_SRC_ROOT}/ballistica/generic/runnable.cc
+ ${BA_SRC_ROOT}/ballistica/generic/runnable.h
+ ${BA_SRC_ROOT}/ballistica/generic/timer.cc
+ ${BA_SRC_ROOT}/ballistica/generic/timer.h
+ ${BA_SRC_ROOT}/ballistica/generic/timer_list.cc
+ ${BA_SRC_ROOT}/ballistica/generic/timer_list.h
+ ${BA_SRC_ROOT}/ballistica/generic/utf8.cc
+ ${BA_SRC_ROOT}/ballistica/generic/utf8.h
+ ${BA_SRC_ROOT}/ballistica/generic/utils.cc
+ ${BA_SRC_ROOT}/ballistica/generic/utils.h
+ ${BA_SRC_ROOT}/ballistica/graphics/area_of_interest.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/area_of_interest.h
+ ${BA_SRC_ROOT}/ballistica/graphics/camera.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/camera.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/empty_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/object_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/object_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/post_process_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/post_process_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/render_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/render_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/shield_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/shield_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/simple_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/simple_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/smoke_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/smoke_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/special_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/special_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/component/sprite_component.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/component/sprite_component.h
+ ${BA_SRC_ROOT}/ballistica/graphics/frame_def.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/frame_def.h
+ ${BA_SRC_ROOT}/ballistica/graphics/framebuffer.h
+ ${BA_SRC_ROOT}/ballistica/graphics/gl/gl_sys.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/gl/gl_sys.h
+ ${BA_SRC_ROOT}/ballistica/graphics/gl/renderer_gl.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/gl/renderer_gl.h
+ ${BA_SRC_ROOT}/ballistica/graphics/graphics.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/graphics.h
+ ${BA_SRC_ROOT}/ballistica/graphics/graphics_server.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/graphics_server.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/image_mesh.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/image_mesh.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_buffer.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_buffer_base.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_buffer_vertex_simple_full.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_buffer_vertex_smoke_full.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_buffer_vertex_sprite.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_data.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_data.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_data_client_handle.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_data_client_handle.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_index_buffer_16.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_index_buffer_32.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_base.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_dual_texture_full.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_object_split.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_simple_full.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_simple_split.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_smoke_full.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_indexed_static_dynamic.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_non_indexed.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/mesh_renderer_data.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/sprite_mesh.h
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/text_mesh.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/mesh/text_mesh.h
+ ${BA_SRC_ROOT}/ballistica/graphics/net_graph.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/net_graph.h
+ ${BA_SRC_ROOT}/ballistica/graphics/render_command_buffer.h
+ ${BA_SRC_ROOT}/ballistica/graphics/render_pass.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/render_pass.h
+ ${BA_SRC_ROOT}/ballistica/graphics/render_target.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/render_target.h
+ ${BA_SRC_ROOT}/ballistica/graphics/renderer.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/renderer.h
+ ${BA_SRC_ROOT}/ballistica/graphics/text/font_page_map_data.h
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_graphics.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_graphics.h
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_group.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_group.h
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_packer.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/text/text_packer.h
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/dds.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/dds.h
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/ktx.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/ktx.h
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/pvr.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/texture/pvr.h
+ ${BA_SRC_ROOT}/ballistica/graphics/vr_graphics.cc
+ ${BA_SRC_ROOT}/ballistica/graphics/vr_graphics.h
+ ${BA_SRC_ROOT}/ballistica/input/device/client_input_device.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/client_input_device.h
+ ${BA_SRC_ROOT}/ballistica/input/device/input_device.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/input_device.h
+ ${BA_SRC_ROOT}/ballistica/input/device/joystick.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/joystick.h
+ ${BA_SRC_ROOT}/ballistica/input/device/keyboard_input.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/keyboard_input.h
+ ${BA_SRC_ROOT}/ballistica/input/device/test_input.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/test_input.h
+ ${BA_SRC_ROOT}/ballistica/input/device/touch_input.cc
+ ${BA_SRC_ROOT}/ballistica/input/device/touch_input.h
+ ${BA_SRC_ROOT}/ballistica/input/input.cc
+ ${BA_SRC_ROOT}/ballistica/input/input.h
+ ${BA_SRC_ROOT}/ballistica/input/remote_app.cc
+ ${BA_SRC_ROOT}/ballistica/input/remote_app.h
+ ${BA_SRC_ROOT}/ballistica/input/std_input_module.cc
+ ${BA_SRC_ROOT}/ballistica/input/std_input_module.h
+ ${BA_SRC_ROOT}/ballistica/math/matrix44f.cc
+ ${BA_SRC_ROOT}/ballistica/math/matrix44f.h
+ ${BA_SRC_ROOT}/ballistica/math/point2d.h
+ ${BA_SRC_ROOT}/ballistica/math/random.cc
+ ${BA_SRC_ROOT}/ballistica/math/random.h
+ ${BA_SRC_ROOT}/ballistica/math/rect.h
+ ${BA_SRC_ROOT}/ballistica/math/vector2f.h
+ ${BA_SRC_ROOT}/ballistica/math/vector3f.cc
+ ${BA_SRC_ROOT}/ballistica/math/vector3f.h
+ ${BA_SRC_ROOT}/ballistica/math/vector4f.h
+ ${BA_SRC_ROOT}/ballistica/media/component/collide_model.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/collide_model.h
+ ${BA_SRC_ROOT}/ballistica/media/component/cube_map_texture.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/cube_map_texture.h
+ ${BA_SRC_ROOT}/ballistica/media/component/data.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/data.h
+ ${BA_SRC_ROOT}/ballistica/media/component/media_component.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/media_component.h
+ ${BA_SRC_ROOT}/ballistica/media/component/model.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/model.h
+ ${BA_SRC_ROOT}/ballistica/media/component/sound.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/sound.h
+ ${BA_SRC_ROOT}/ballistica/media/component/texture.cc
+ ${BA_SRC_ROOT}/ballistica/media/component/texture.h
+ ${BA_SRC_ROOT}/ballistica/media/data/collide_model_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/collide_model_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/data_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/data_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/media_component_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/media_component_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/model_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/model_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/model_renderer_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/sound_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/sound_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/texture_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/texture_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/texture_preload_data.cc
+ ${BA_SRC_ROOT}/ballistica/media/data/texture_preload_data.h
+ ${BA_SRC_ROOT}/ballistica/media/data/texture_renderer_data.h
+ ${BA_SRC_ROOT}/ballistica/media/media.cc
+ ${BA_SRC_ROOT}/ballistica/media/media.h
+ ${BA_SRC_ROOT}/ballistica/media/media_server.cc
+ ${BA_SRC_ROOT}/ballistica/media/media_server.h
+ ${BA_SRC_ROOT}/ballistica/networking/network_reader.h
+ ${BA_SRC_ROOT}/ballistica/networking/network_write_module.h
+ ${BA_SRC_ROOT}/ballistica/networking/networking.h
+ ${BA_SRC_ROOT}/ballistica/networking/networking_sys.h
+ ${BA_SRC_ROOT}/ballistica/networking/sockaddr.h
+ ${BA_SRC_ROOT}/ballistica/networking/telnet_server.cc
+ ${BA_SRC_ROOT}/ballistica/networking/telnet_server.h
+ ${BA_SRC_ROOT}/ballistica/platform/apple/platform_apple.h
+ ${BA_SRC_ROOT}/ballistica/platform/linux/platform_linux.cc
+ ${BA_SRC_ROOT}/ballistica/platform/linux/platform_linux.h
+ ${BA_SRC_ROOT}/ballistica/platform/min_sdl.h
+ ${BA_SRC_ROOT}/ballistica/platform/platform.cc
+ ${BA_SRC_ROOT}/ballistica/platform/platform.h
+ ${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.cc
+ ${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_activity_data.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_activity_data.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_collide_model.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_collide_model.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_context.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_context.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_context_call.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_context_call.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_data.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_data.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_input_device.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_input_device.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_material.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_material.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_model.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_model.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_node.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_node.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_session_data.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_session_data.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_session_player.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_session_player.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_sound.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_sound.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_texture.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_texture.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_timer.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_timer.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_vec3.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_vec3.h
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_widget.cc
+ ${BA_SRC_ROOT}/ballistica/python/class/python_class_widget.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_app.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_app.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_gameplay.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_gameplay.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_graphics.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_graphics.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_input.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_input.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_media.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_media.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_system.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_system.h
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_ui.cc
+ ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_ui.h
+ ${BA_SRC_ROOT}/ballistica/python/python.h
+ ${BA_SRC_ROOT}/ballistica/python/python_command.cc
+ ${BA_SRC_ROOT}/ballistica/python/python_command.h
+ ${BA_SRC_ROOT}/ballistica/python/python_context_call.cc
+ ${BA_SRC_ROOT}/ballistica/python/python_context_call.h
+ ${BA_SRC_ROOT}/ballistica/python/python_context_call_runnable.h
+ ${BA_SRC_ROOT}/ballistica/python/python_ref.cc
+ ${BA_SRC_ROOT}/ballistica/python/python_ref.h
+ ${BA_SRC_ROOT}/ballistica/python/python_sys.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/anim_curve_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/anim_curve_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/bomb_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/bomb_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/combine_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/combine_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/explosion_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/explosion_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/flag_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/flag_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/flash_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/flash_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/globals_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/globals_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/image_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/image_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/light_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/light_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/locator_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/locator_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/math_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/math_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/node_attribute.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/node_attribute.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/node_attribute_connection.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/node_attribute_connection.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/node_type.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/null_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/null_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/player_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/player_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/prop_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/prop_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/region_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/region_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/scorch_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/scorch_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/session_globals_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/session_globals_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/shield_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/shield_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/sound_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/sound_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/spaz_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/spaz_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/terrain_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/terrain_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/text_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/text_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/texture_sequence_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/texture_sequence_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/node/time_display_node.cc
+ ${BA_SRC_ROOT}/ballistica/scene/node/time_display_node.h
+ ${BA_SRC_ROOT}/ballistica/scene/scene.cc
+ ${BA_SRC_ROOT}/ballistica/scene/scene.h
+ ${BA_SRC_ROOT}/ballistica/ui/console.cc
+ ${BA_SRC_ROOT}/ballistica/ui/console.h
+ ${BA_SRC_ROOT}/ballistica/ui/root_ui.cc
+ ${BA_SRC_ROOT}/ballistica/ui/root_ui.h
+ ${BA_SRC_ROOT}/ballistica/ui/ui.cc
+ ${BA_SRC_ROOT}/ballistica/ui/ui.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/button_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/button_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/check_box_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/check_box_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/column_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/column_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/container_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/container_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/h_scroll_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/h_scroll_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/image_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/image_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/root_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/root_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/row_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/row_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/scroll_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/scroll_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/stack_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/stack_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/text_widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/text_widget.h
+ ${BA_SRC_ROOT}/ballistica/ui/widget/widget.cc
+ ${BA_SRC_ROOT}/ballistica/ui/widget/widget.h
# AUTOGENERATED_PUBLIC_END
)
diff --git a/src/ballistica/audio/al_sys.cc b/src/ballistica/audio/al_sys.cc
new file mode 100644
index 00000000..11518df6
--- /dev/null
+++ b/src/ballistica/audio/al_sys.cc
@@ -0,0 +1,51 @@
+// Released under the MIT License. See LICENSE for details.
+
+#include "ballistica/audio/al_sys.h"
+
+#include "ballistica/audio/audio_server.h"
+#include "ballistica/generic/utils.h"
+
+// Need to move away from OpenAL on Apple stuff.
+#if __clang__
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+#if BA_ENABLE_AUDIO
+
+namespace ballistica {
+
+void _check_al_error(const char* file, int line) {
+ if (g_audio_server->paused()) {
+ Log(Utils::BaseName(file) + ":" + std::to_string(line)
+ + ": Checking OpenAL error while paused.");
+ }
+ ALenum al_err = alGetError();
+ if (al_err != AL_NO_ERROR) {
+ Log(Utils::BaseName(file) + ":" + std::to_string(line)
+ + ": OpenAL Error: " + GetALErrorString(al_err) + ";");
+ }
+}
+
+auto GetALErrorString(ALenum err) -> const char* {
+ static char undefErrStr[128];
+#define DO_AL_ERR_CASE(a) \
+ case a: \
+ return #a
+ switch (err) {
+ DO_AL_ERR_CASE(AL_INVALID_NAME);
+ DO_AL_ERR_CASE(AL_ILLEGAL_ENUM);
+ DO_AL_ERR_CASE(AL_INVALID_VALUE);
+ DO_AL_ERR_CASE(AL_ILLEGAL_COMMAND);
+ DO_AL_ERR_CASE(AL_OUT_OF_MEMORY);
+ default: {
+ snprintf(undefErrStr, sizeof(undefErrStr), "(unrecognized: 0x%X (%d))",
+ err, err);
+ return undefErrStr;
+ }
+ }
+#undef DO_AL_ERR_CASE
+}
+
+} // namespace ballistica
+
+#endif // BA_ENABLE_AUDIO
diff --git a/src/ballistica/audio/al_sys.h b/src/ballistica/audio/al_sys.h
new file mode 100644
index 00000000..44b1c740
--- /dev/null
+++ b/src/ballistica/audio/al_sys.h
@@ -0,0 +1,41 @@
+// Released under the MIT License. See LICENSE for details.
+
+#ifndef BALLISTICA_AUDIO_AL_SYS_H_
+#define BALLISTICA_AUDIO_AL_SYS_H_
+
+#include
+
+#include "ballistica/ballistica.h"
+
+#if BA_ENABLE_AUDIO
+
+#if HAVE_FRAMEWORK_OPENAL
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#define CHECK_AL_ERROR _check_al_error(__FILE__, __LINE__)
+#if BA_DEBUG_BUILD
+#define DEBUG_CHECK_AL_ERROR CHECK_AL_ERROR
+#else
+#define DEBUG_CHECK_AL_ERROR ((void)0)
+#endif
+
+namespace ballistica {
+
+const int kAudioStreamBufferSize = 4096 * 8;
+const int kAudioStreamBufferCount = 7;
+
+// Some OpenAL Error handling utils.
+auto GetALErrorString(ALenum err) -> const char*;
+
+void _check_al_error(const char* file, int line);
+
+} // namespace ballistica
+
+#endif // BA_ENABLE_AUDIO
+
+#endif // BALLISTICA_AUDIO_AL_SYS_H_
diff --git a/src/ballistica/audio/audio.cc b/src/ballistica/audio/audio.cc
new file mode 100644
index 00000000..4fcb6e2e
--- /dev/null
+++ b/src/ballistica/audio/audio.cc
@@ -0,0 +1,180 @@
+// Released under the MIT License. See LICENSE for details.
+
+#include "ballistica/audio/audio.h"
+
+#include "ballistica/audio/audio_server.h"
+#include "ballistica/audio/audio_source.h"
+#include "ballistica/media/data/sound_data.h"
+
+namespace ballistica {
+
+Audio::Audio() { assert(InGameThread()); }
+
+void Audio::Init() {
+ // Init our singleton.
+ assert(g_audio == nullptr);
+ g_audio = new Audio();
+}
+
+void Audio::Reset() {
+ assert(InGameThread());
+ g_audio_server->PushResetCall();
+}
+
+void Audio::SetVolumes(float music_volume, float sound_volume) {
+ g_audio_server->PushSetVolumesCall(music_volume, sound_volume);
+}
+
+void Audio::SetSoundPitch(float pitch) {
+ g_audio_server->PushSetSoundPitchCall(pitch);
+}
+
+void Audio::SetListenerPosition(const Vector3f& p) {
+ g_audio_server->PushSetListenerPositionCall(p);
+}
+
+void Audio::SetListenerOrientation(const Vector3f& forward,
+ const Vector3f& up) {
+ g_audio_server->PushSetListenerOrientationCall(forward, up);
+}
+
+// This stops a particular sound play ID only.
+void Audio::PushSourceStopSoundCall(uint32_t play_id) {
+ g_audio_server->PushCall(
+ [this, play_id] { g_audio_server->StopSound(play_id); });
+}
+
+void Audio::PushSourceFadeOutCall(uint32_t play_id, uint32_t time) {
+ g_audio_server->PushCall(
+ [this, play_id, time] { g_audio_server->FadeSoundOut(play_id, time); });
+}
+
+auto Audio::SourceBeginNew() -> AudioSource* {
+ BA_DEBUG_FUNCTION_TIMER_BEGIN();
+
+ AudioSource* s = nullptr;
+ {
+ // Gotta make sure to hold this until we've locked the source.
+ // Otherwise theoretically the audio thread could make our source available
+ // again before we can use it.
+ std::lock_guard lock(available_sources_mutex_);
+
+ // If there's an available source, reserve and return it.
+ auto i = available_sources_.begin();
+ if (i != available_sources_.end()) {
+ s = *i;
+ available_sources_.erase(i);
+ assert(s->available());
+ assert(s->client_queue_size() == 0);
+ s->set_available(false);
+ }
+ if (s) {
+ s->Lock(1);
+ assert(!s->available());
+ s->set_client_queue_size(s->client_queue_size() + 1);
+ }
+ }
+ BA_DEBUG_FUNCTION_TIMER_END_THREAD(20);
+ return s;
+}
+
+auto Audio::IsSoundPlaying(uint32_t play_id) -> bool {
+ uint32_t source_id = AudioServer::source_id_from_play_id(play_id);
+ assert(client_sources_.size() > source_id);
+ client_sources_[source_id]->Lock(2);
+ bool result = (client_sources_[source_id]->play_id() == play_id);
+ client_sources_[source_id]->Unlock();
+ return result;
+}
+
+auto Audio::SourceBeginExisting(uint32_t play_id, uint32_t debug_id)
+ -> AudioSource* {
+ BA_DEBUG_FUNCTION_TIMER_BEGIN();
+ uint32_t source_id = AudioServer::source_id_from_play_id(play_id);
+
+ // Ok, the audio thread fills in this source list,
+ // so theoretically a client could call this before the audio thread
+ // has set it up. However no one should be trying to get a playing
+ // sound unless they've already started playing one which implies
+ // everything was set up already. I think we're good.
+ assert(g_audio->client_sources_.size() > source_id);
+
+ // If this guy's still got the play id they're asking about, lock/return it.
+ client_sources_[source_id]->Lock(debug_id);
+
+ if (client_sources_[source_id]->play_id() == play_id) {
+ assert(!client_sources_[source_id]->available());
+ client_sources_[source_id]->set_client_queue_size(
+ client_sources_[source_id]->client_queue_size() + 1);
+ BA_DEBUG_FUNCTION_TIMER_END_THREAD(20);
+ return client_sources_[source_id];
+ }
+
+ // No-go; unlock and return empty-handed.
+ client_sources_[source_id]->Unlock();
+
+ BA_DEBUG_FUNCTION_TIMER_END_THREAD(20);
+ return nullptr;
+}
+
+auto Audio::ShouldPlay(SoundData* sound) -> bool {
+ millisecs_t time = GetRealTime();
+ assert(sound);
+ return (time - sound->last_play_time() > 50);
+}
+
+void Audio::PlaySound(SoundData* sound, float volume) {
+ assert(InGameThread());
+ BA_DEBUG_FUNCTION_TIMER_BEGIN();
+ assert(sound);
+ if (!ShouldPlay(sound)) {
+ return;
+ }
+ AudioSource* s = SourceBeginNew();
+ if (s) {
+ // In vr mode, play non-positional sounds positionally in space roughly
+ // where the menu is.
+ if (IsVRMode()) {
+ s->SetGain(volume);
+ s->SetPositional(true);
+ float x = 0.0f;
+ float y = 4.5f;
+ float z = -3.0f;
+ s->SetPosition(x, y, z);
+ s->Play(sound);
+ s->End();
+ } else {
+ s->SetGain(volume);
+ s->SetPositional(false);
+ s->Play(sound);
+ s->End();
+ }
+ }
+ BA_DEBUG_FUNCTION_TIMER_END(20);
+}
+
+void Audio::PlaySoundAtPosition(SoundData* sound, float volume, float x,
+ float y, float z) {
+ assert(sound);
+ if (!ShouldPlay(sound)) {
+ return;
+ }
+ // Run locally.
+ if (AudioSource* source = SourceBeginNew()) {
+ source->SetGain(volume);
+ source->SetPositional(true);
+ source->SetPosition(x, y, z);
+ source->Play(sound);
+ source->End();
+ }
+}
+
+void Audio::AddClientSource(AudioSource* source) {
+ client_sources_.push_back(source);
+}
+
+void Audio::MakeSourceAvailable(AudioSource* source) {
+ available_sources_.push_back(source);
+}
+
+} // namespace ballistica
diff --git a/src/ballistica/audio/audio.h b/src/ballistica/audio/audio.h
new file mode 100644
index 00000000..20ec7060
--- /dev/null
+++ b/src/ballistica/audio/audio.h
@@ -0,0 +1,82 @@
+// Released under the MIT License. See LICENSE for details.
+
+#ifndef BALLISTICA_AUDIO_AUDIO_H_
+#define BALLISTICA_AUDIO_AUDIO_H_
+
+#include