Merge branch 'master' into fairydust

This commit is contained in:
Eric Froemling 2022-09-22 13:55:49 -07:00 committed by GitHub
commit 7663b9aafe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
322 changed files with 5856 additions and 5575 deletions

View File

@ -420,8 +420,8 @@
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/60/ad/38269b7f1c7dc20cb9a506cd0681", "assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/60/ad/38269b7f1c7dc20cb9a506cd0681",
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/72/85/d6fc4d16b7081d91fba2850b5b10", "assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/72/85/d6fc4d16b7081d91fba2850b5b10",
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/e9/ae/1d674d0c086eaa0bd1c3b1db0505", "assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/e9/ae/1d674d0c086eaa0bd1c3b1db0505",
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/e8/42/a43c158be7fa45f2c0c3d4b84a1f", "assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/5a/10/dae249cdd589b795fd341ebbec42",
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/5b/cf/4501b151257c3d8d6ee8d0497d14", "assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/e2/24/5e7ea9ca5c9de4d3b7a28e53564d",
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/61/03/89070ca765e06da3a419a579f503", "assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/61/03/89070ca765e06da3a419a579f503",
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/f8/15/e1a2fa38697417bcf2cf19cd34ef", "assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/f8/15/e1a2fa38697417bcf2cf19cd34ef",
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/44/aa/c12568afb4558dc7f9f2fa155467", "assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/44/aa/c12568afb4558dc7f9f2fa155467",
@ -431,17 +431,17 @@
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/68/93/da8e9874f41a786edf52ba4ccaad", "assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/68/93/da8e9874f41a786edf52ba4ccaad",
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/72/80/d6395c8a168558750c0d79ce769b", "assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/72/80/d6395c8a168558750c0d79ce769b",
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/4c/c7/0184b8178869d1a3827a1bfcd5bb", "assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/4c/c7/0184b8178869d1a3827a1bfcd5bb",
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/8f/73/093120ae2241d8f4b899ccda2d75", "assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/e9/07/b2dc862601bcd70701b083d43279",
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/25/65/1cb03566e73811fc6e1b841d9072", "assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/2e/48/b0a8fafc5e5436e99d9a3d697d23",
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/ef/e6/d4909f571d7473fd04055728490e", "assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/8a/09/3e0fa9e44913b53f4dab195d3fae",
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/8a/2a/b2bc00eed0608b2199b2bc379b2e", "assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/8a/2a/b2bc00eed0608b2199b2bc379b2e",
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/82/eb/37ff44af76812097f9c98f05c730", "assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/e0/04/6be14bff785255719756e0906ea9",
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/50/e8/837be1324c8128507b3df89b689f", "assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/91/98/42701cd595c2f70b7484614a8f49",
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/d8/f2/aa16bc336bd7660cc86c3264bfc4", "assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/d8/f2/aa16bc336bd7660cc86c3264bfc4",
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/e3/85/14e57e3f49505e5a190daf7fe276", "assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/7f/a9/db86d4c8b70f06fd8a1fe0c0511b",
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/1a/10/9563348e729d1e5c8ae8c9cbc1f2", "assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/1a/10/9563348e729d1e5c8ae8c9cbc1f2",
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/a8/e9/171a904f1331fdb7b1918a0f2598", "assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/a8/e9/171a904f1331fdb7b1918a0f2598",
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/83/4a/ec10142ac479bf8d80455b47a62b", "assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/df/b1/b2c9ebaad5e873ebedd365726d3d",
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/19/e9/59c891b1fb85f3ba9f19283c233d", "assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/19/e9/59c891b1fb85f3ba9f19283c233d",
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/da/95/36797ec53a697a04e55b225a701d", "assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/da/95/36797ec53a697a04e55b225a701d",
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/d7/06/9d70642d0a4d1e3b1c2149d7a17c", "assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/d7/06/9d70642d0a4d1e3b1c2149d7a17c",
@ -452,7 +452,7 @@
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/91/0a/35c4baf539d5951fc03a794c0e0b", "assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/91/0a/35c4baf539d5951fc03a794c0e0b",
"assets/build/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/94/1a/533bc718e676191bafc25e2dc98f", "assets/build/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/94/1a/533bc718e676191bafc25e2dc98f",
"assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/f7/df/7ba5f99c5c2c4c86fc0503fcf0b7", "assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/f7/df/7ba5f99c5c2c4c86fc0503fcf0b7",
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/14/a0/783cc6da2d122e9a7482c6a5ef8c", "assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/9a/90/8e2ed626def09f88c3b9ab5215a3",
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/ab/35/644e4239cfa62a597a905412b90c", "assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/ab/35/644e4239cfa62a597a905412b90c",
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/53/9e/068074156b38bab7f732977a4031", "assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/53/9e/068074156b38bab7f732977a4031",
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/25/13/b64b849fc9fedcc18d81f6e08c4d", "assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/25/13/b64b849fc9fedcc18d81f6e08c4d",
@ -944,10 +944,10 @@
"assets/build/ba_data/models/zoeUpperArm.bob": "https://files.ballistica.net/cache/ba1/99/38/b7694cae0804260eeb337aa1676a", "assets/build/ba_data/models/zoeUpperArm.bob": "https://files.ballistica.net/cache/ba1/99/38/b7694cae0804260eeb337aa1676a",
"assets/build/ba_data/models/zoeUpperLeg.bob": "https://files.ballistica.net/cache/ba1/83/4f/28b2202d0109fa93272c0b09fa2d", "assets/build/ba_data/models/zoeUpperLeg.bob": "https://files.ballistica.net/cache/ba1/83/4f/28b2202d0109fa93272c0b09fa2d",
"assets/build/ba_data/python-site-packages/_yaml/__init__.py": "https://files.ballistica.net/cache/ba1/0d/45/65ba92f51d411dcffac8835b6130", "assets/build/ba_data/python-site-packages/_yaml/__init__.py": "https://files.ballistica.net/cache/ba1/0d/45/65ba92f51d411dcffac8835b6130",
"assets/build/ba_data/python-site-packages/certifi/__init__.py": "https://files.ballistica.net/cache/ba1/ca/90/4cf111df6bafc9735f6d2a05d6f2", "assets/build/ba_data/python-site-packages/certifi/__init__.py": "https://files.ballistica.net/cache/ba1/f0/50/dbe7d0065006ac12adf2eaa239fc",
"assets/build/ba_data/python-site-packages/certifi/__main__.py": "https://files.ballistica.net/cache/ba1/b2/bb/d7d8216212bcf66cdc3067700fb7", "assets/build/ba_data/python-site-packages/certifi/__main__.py": "https://files.ballistica.net/cache/ba1/b2/bb/d7d8216212bcf66cdc3067700fb7",
"assets/build/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/c9/f9/e2d0dd61a7f4e36a3309a3981d07", "assets/build/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/eb/1c/18ef584961785d002a2550d389e0",
"assets/build/ba_data/python-site-packages/certifi/core.py": "https://files.ballistica.net/cache/ba1/8a/01/33e774b2ed89a56756f32d2f3bef", "assets/build/ba_data/python-site-packages/certifi/core.py": "https://files.ballistica.net/cache/ba1/ac/28/37f05b52df3806856bce2c0b9772",
"assets/build/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/a5/c3/66c408bfad73af8644f507d8ee17", "assets/build/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/a5/c3/66c408bfad73af8644f507d8ee17",
"assets/build/ba_data/python-site-packages/yaml/__init__.py": "https://files.ballistica.net/cache/ba1/e5/47/17715ca7620f3b9749558b9dcb2d", "assets/build/ba_data/python-site-packages/yaml/__init__.py": "https://files.ballistica.net/cache/ba1/e5/47/17715ca7620f3b9749558b9dcb2d",
"assets/build/ba_data/python-site-packages/yaml/composer.py": "https://files.ballistica.net/cache/ba1/3e/aa/d7fcfc4707ad19a6964d72654b82", "assets/build/ba_data/python-site-packages/yaml/composer.py": "https://files.ballistica.net/cache/ba1/3e/aa/d7fcfc4707ad19a6964d72654b82",
@ -3995,50 +3995,51 @@
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e", "assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34", "assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a", "ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/15/3b9d4eb830dd3f65266b90544461", "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/2a/10/01cc7af239cfca6d9abeb6e6deb5",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3f/94/ce703438b67755c530ca90d7147e", "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/49/6da409797f98e3834cdd2ba9a1e5",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/57/49/aef9dbd58c9638d2f57c61fa9dee", "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cd/ba/2e17df1379cd7f60708f1ec3aecb",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/53/73/7aee5551f9aa8c60bfa36ce86889", "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/72/0d/d953d2cda66ea47552c6a3f5dfee",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8d/cd/61b3022a6a3620bb9a0d288a3a07", "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/12/44/fac079140811eaf6b3dd1f1d0fe0",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/67/d3/7e7b3147c119bcf9edc62f271755", "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/00/74/a671dd7047610d8d555c4b0a303c",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/41/81/b4225f4df31a6bb482eee912d1e7", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/23/4a/40c6eb2af25a0a8f29530f8e63b0",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8a/3e/9a284ee8d8cb75fef73f31c95a8f", "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b3/ff/ced34572d1502e3ce393338810a9",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a5/a2/69829de7375f981ac01464d1271c", "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/73/54f48f6cb05f5dab5e32532b831a",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8f/de/c40022e95c0d51e3ea7d68713ac8", "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/26/ca/b667ad8ba524618e62ffc5a58c45",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2a/e3/74cdea89e9606f525ae01f5fb860", "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c9/f1/f92e2fd877e32f2364eb1656052b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/b3/8f5c7076b293ce6a961b23321ebe", "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/14/dc/d61b2e43131283a6049f203943bc",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/45/4b/43950780d121290a40cb444e86c4", "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b3/8b/84937c08100c035641764b95fe1d",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/74/6c/5c8a7cab586c813a07d5180e25c2", "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d0/59/e84165efa3367582461128db885a",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ca/36/94c0d402ec38ffdd74cd165f51c3", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/26/3f/da203a1eb557318e9abc5f76aac1",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b7/a9/14ea5150ad61a43b5780975551ac", "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/07/db/5d04f8f0736732cdba70bb85fb19",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/23/72/2bdc1106cdf2aa163a591e7c47b8", "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ad/79/b6fcb72c6ff1ac3d507dd938ce14",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/1e/d9/5a7fd190b86683bef223c1cdb0b6", "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/46/5a/582ca64edfc416e140f4b5b1827d",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/2e/f1/27b90831c9a25d2b9d06a266e931", "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/5b/b5/ca8b600f49d4c28108f4e16c2f00",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/17/ce/d3e33370c016fc8110e6dddd120f", "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/48/3f/8327430b9c194c14974bed19ea16",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/32/b0/df61f7b69d796fbdf2aa0d11974b", "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/41/b3/5a5813294b9281ca6bbb1f5caebe",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/42/31/a45e87e70e5d5232956586620f35", "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/28/05/b6cc01e7b6762a3c8d47851cd30c",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/94/5e/6ac9534c08e600201b04d28a6069", "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f7/8c/36acf6d02d7c322aed086cc4ec3f",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5f/5d/52e74182f459f5b7b55ae07b36c6", "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ca/65/de52706de6aa624f01c5907e5367",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7b/9d/367338622b31482a8ef87621f5aa", "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2d/3d/3e3e65846f42810c032cb5efd997",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a8/18/4dff9ab6b2529d258a2ee5607d0c", "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/da/bf/c4a1f6e6d2495723acbd93e1b22c",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/79/b9/e5e9d0f92f82f6cf35abf0c049cf", "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/34/6605f152207515d50174eca420e7",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/b4/2c65b84265e0b2d576317ca86e77", "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/b6/770c3d26d70edec763335c38de73",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d1/86/635b942e0837be18e6d9d859f2c4", "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/33/10/a753a671240f243b2351b5730917",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b0/f5/3da5acc926ca5e6c02307b8a16a6", "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1c/e4/05dc037f8669fc5ddc993dc8defc",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a3/51/d624ac150603304183ba23d369a2", "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7c/c9/879778a21f2403346adf8db17318",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/51/5eb2216e4cdc531c500244316f1d", "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/86/36/6d77a933a8126df4fde064fe881f",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b1/2b/c72179ed1d11ae7e11f429b90ae9", "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/80/e8/1c9c69d9fd5e47d0fd6e3c9b1134",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/52/78/cca5ff0fcc837467cd23239537c7", "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/e2/4208f2fc902ed0526bf4cb5bbc54",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/6e/eb7102dd939e85172d729ba471b8", "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/95/5fd6cede6b0e88753bb50b437110",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/92/b7c90b5dbf614aa056cf467f73e0", "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/87/0b/442839bc7a21c12ed6e173abf7ca",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/cf/d9/52c1c145efa1a24ebf54dd71f691", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b6/aa/0666c00d1751f934cc1b0907fa40",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/31/15/ef849aeaf5a9cc2169e6ec4998c8", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/aa/22/3afc115395a7909eac78d98cf856",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/86/a7/def29184cd6e947469726ae382e1", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/9f/e6/5097b01991ce22e1d3fd594808b2",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/5f/30/42705d0b580994d1345c34651170", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/d9/4f/7f2a34294f53378990487655f4ab",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/2f/b1/6a6e8cf45fc5afa4085bf90a526f", "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/18/d3/50bbe34de1862d8224dafa8792e7",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/7e/fb/e7eaee33c6196f9204a2997fc65c", "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/82/93/f80194878bfed43f58809a7e9823",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/5a/39/e00cddb91e8eca83b117235c1332", "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/73/54/88f193633990884b61719a481dec",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/07/dd/6e331996e6e6907f05a21abc20a6", "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/f4/23/2a4e21dc99e6135c1cb102f6ca37",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/7d/3e/229a581cb2454ed856f1d8b564a7", "src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/c0/32/b7907e3859a5c5013a3d97b6b523",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/98/12/571b2160d69d42580e8f31fa6a8d" "src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"
} }

View File

@ -64,9 +64,11 @@
<w>aiomain</w> <w>aiomain</w>
<w>alarmsound</w> <w>alarmsound</w>
<w>alibaba</w> <w>alibaba</w>
<w>allerrors</w>
<w>allpaths</w> <w>allpaths</w>
<w>allsettings</w> <w>allsettings</w>
<w>allteams</w> <w>allteams</w>
<w>allwarnings</w>
<w>aman</w> <w>aman</w>
<w>amazonaws</w> <w>amazonaws</w>
<w>aname</w> <w>aname</w>
@ -111,6 +113,7 @@
<w>appspot</w> <w>appspot</w>
<w>appstate</w> <w>appstate</w>
<w>appstore</w> <w>appstore</w>
<w>apptime</w>
<w>apputils</w> <w>apputils</w>
<w>archivepath</w> <w>archivepath</w>
<w>archivepathbase</w> <w>archivepathbase</w>
@ -234,6 +237,7 @@
<w>benning</w> <w>benning</w>
<w>bfiledir</w> <w>bfiledir</w>
<w>bfiles</w> <w>bfiles</w>
<w>bgdynamics</w>
<w>bgmodel</w> <w>bgmodel</w>
<w>bgrn</w> <w>bgrn</w>
<w>bgterrain</w> <w>bgterrain</w>
@ -415,6 +419,7 @@
<w>cleanlist</w> <w>cleanlist</w>
<w>cleanupcheck</w> <w>cleanupcheck</w>
<w>cleanupchecks</w> <w>cleanupchecks</w>
<w>clearsign</w>
<w>clientid</w> <w>clientid</w>
<w>clientlist</w> <w>clientlist</w>
<w>clienttobasn</w> <w>clienttobasn</w>
@ -433,6 +438,7 @@
<w>clrhdr</w> <w>clrhdr</w>
<w>clrnames</w> <w>clrnames</w>
<w>clrred</w> <w>clrred</w>
<w>cmakelist</w>
<w>cmakelists</w> <w>cmakelists</w>
<w>cmakeserver</w> <w>cmakeserver</w>
<w>cmath</w> <w>cmath</w>
@ -1341,6 +1347,7 @@
<w>levelgametype</w> <w>levelgametype</w>
<w>levelmodule</w> <w>levelmodule</w>
<w>levelname</w> <w>levelname</w>
<w>levelno</w>
<w>lfull</w> <w>lfull</w>
<w>lfval</w> <w>lfval</w>
<w>libballisticacore</w> <w>libballisticacore</w>
@ -1647,6 +1654,7 @@
<w>nettest</w> <w>nettest</w>
<w>nettesting</w> <w>nettesting</w>
<w>netutils</w> <w>netutils</w>
<w>networkwrite</w>
<w>nevermind</w> <w>nevermind</w>
<w>newactivity</w> <w>newactivity</w>
<w>newdamage</w> <w>newdamage</w>
@ -2380,6 +2388,7 @@
<w>startscan</w> <w>startscan</w>
<w>startsplits</w> <w>startsplits</w>
<w>starttime</w> <w>starttime</w>
<w>startupmsg</w>
<w>statestr</w> <w>statestr</w>
<w>statictest</w> <w>statictest</w>
<w>statictestfiles</w> <w>statictestfiles</w>
@ -2408,6 +2417,7 @@
<w>stot</w> <w>stot</w>
<w>strftime</w> <w>strftime</w>
<w>stringified</w> <w>stringified</w>
<w>stringifying</w>
<w>stringprep</w> <w>stringprep</w>
<w>stringptr</w> <w>stringptr</w>
<w>strippable</w> <w>strippable</w>

View File

@ -1,5 +1,14 @@
### 1.7.7 (build 20798, api 7, 2022-09-09) ### 1.7.9 (build 20877, api 7, 2022-09-21)
- Cleaned up the efro.message system to isolate response types that are used purely internally (via a new SysResponse type).
- Fixed bug with 'Disable Camera Shake' option. (GitHub #511)
- Fixed an issue where Co-op football would play no music.
- Accept "fairydust" as an emit type in `ba.emitfx()`. - Accept "fairydust" as an emit type in `ba.emitfx()`.
### 1.7.8 (build 20871, api 7, 2022-09-21)
- Fixed tournament scores submits which were broken in 1.7.7 (oops).
- Added @clear command to stdin command reader.
### 1.7.7 (build 20868, api 7, 2022-09-20)
- Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread. - Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread.
- Improved logging of missing playlist game types. - Improved logging of missing playlist game types.
- Some ba.Lstr functionality can now be used in background threads. - Some ba.Lstr functionality can now be used in background threads.
@ -9,7 +18,7 @@
- Added support for the console tool in the new devices section on ballistica.net. - Added support for the console tool in the new devices section on ballistica.net.
- Increased timeouts in net-testing gui and a few other places to be able to better diagnose/handle places with very poor connectivity. - Increased timeouts in net-testing gui and a few other places to be able to better diagnose/handle places with very poor connectivity.
- Removed `Platform::SetLastPyCall()` which was just for debugging and which has not been useful in a while. - Removed `Platform::SetLastPyCall()` which was just for debugging and which has not been useful in a while.
- Moved some app bootstrapping from the C++ layer to the ba._bootstrap module. - Moved some app bootstrapping from the C++ layer to the `ba._bootstrap` module.
- The game will now properly return to the stress-test window after a stress test finishes (thanks vishal332008!) - The game will now properly return to the stress-test window after a stress test finishes (thanks vishal332008!)
- Continue window will now pause the game to avoid running up times in the background (thanks vishal332008!) - Continue window will now pause the game to avoid running up times in the background (thanks vishal332008!)
- Keepaway and KingOfTheHill now have epic options (thanks FAL-Guys!) - Keepaway and KingOfTheHill now have epic options (thanks FAL-Guys!)
@ -17,14 +26,37 @@
- Starting to rename the 'game' thread to the 'logic' thread. This is the thread where most high level app logic happen, not only game logic. - Starting to rename the 'game' thread to the 'logic' thread. This is the thread where most high level app logic happen, not only game logic.
- `_ba.in_game_thread()` is now `_ba.in_logic_thread()`. - `_ba.in_game_thread()` is now `_ba.in_logic_thread()`.
- Misc C++ layer tidying/refactoring. - Misc C++ layer tidying/refactoring.
- Split out the `_ba` binary module into `_ba` and `_bainternal`. This will eventually allow running without the closed-source parts (_bainternal) present at all. - Split out the `_ba` binary module into `_ba` and `_bainternal`. This will eventually allow running without the closed-source parts (`_bainternal`) present at all.
- There is now a `_bainternal.py` dummy-module alongside the existing `_ba.py` one. Be sure to exclude it from any script collections used by the game (the same as `_ba.py`). - There is now a `_bainternal.py` dummy-module alongside the existing `_ba.py` one. Be sure to exclude it from any script collections used by the game (the same as `_ba.py`).
- Added checks to make sure _ba or _bainternal arent used outside of ba. Any 'internal' functionality needed outside of ba should be exposed through ba.internal. _ba and _bainternal are internal implementation details. - Added checks to make sure `_ba` or `_bainternal` arent used outside of ba. Any 'internal' functionality needed outside of ba should be exposed through ba.internal. `_ba` and `_bainternal` are internal implementation details.
- Removed C++ Module class and simplified Thread class. The Module class was an old relic of long ago before C++ had lambdas and its existence was pretty pointless and confusing these days. - Removed C++ Module class and simplified Thread class. The Module class was an old relic of long ago before C++ had lambdas and its existence was pretty pointless and confusing these days.
- Renamed C++ App to AppFlavor and AppGlobals to App.
- Renamed C++ Media to Assets.
- Removed 'scores to beat' list in coop which was only ever functional in limited cases on the Mac version. Perhaps that feature can reappear in a cross-platform way sometime.
- Simplified C++ bootstrapping to allocate all globals in one place.
- Renamed C++ Game classes to Logic.
- The app now bootstraps Python in the main thread instead of the logic thread. This will keep things more consistent later when we are able to run under an already-existing Python interpreter.
- As a side-effect of initing Python in the main thread, it seems that Python now catches segfaults in our debug builds and prints Python stack traces. (see https://docs.python.org/3/library/faulthandler.html). We'll have to experiment and see if this is a net positive or something we want to disable or make optional.
- Python and `_ba` are now completely initialized in public source code. Now we just need to enable the app to survive without `_bainternal` and it'll be possible to build a 100% open source app.
- `Logging::Log()` in the C++ layer now takes a LogLevel arg (kDebug, kWarning, kError, etc.) and simply calls the equivalent Python logging.XXX call. This unifies our C++ and Python logging to go through the same place.
- `ba.log()` is no more. Instead just use standard Python logging functions (logging.info(), logging.error(), etc.).
- `_ba.getlog()` is now `_ba.get_v1_cloud_log()`. Note that this functionality will go away eventually so you should use `ba.app.log_handler` and/or standard Python logging functions to get at app logs.
- Along the same lines, `_ba.get_log_file_path()` is now `_ba.get_v1_cloud_log_file_path()`.
- Added `_ba.display_log()` function which ships a log message to the in-game terminal and platform-specific places like the Android log. The engine wires up standard Python logging output to go through this.
- Added `_ba.v1_cloud_log()` which ships a message to the old v1-cloud-log (the log which is gathered and sent to the v1 master server to help me identify problems people are seeing). This is presently wired up to a subset of Python logging output to approximate how it used to work.
- Note: Previously in the C++ layer some code would mix Python print calls (such as `PyErr_PrintEx()`) with ballistica::Log() calls. Previously these all wound up going to the same place (Python's sys.stderr) so it worked, but now they no longer do and so this sort of mixing should be avoided. So if you see a weird combination of colored log output lines with non-colored lines that seem to go together, please holler as it means something needs to be fixed.
- Builds for Apple devices now explicitly set a thread stack size of 1MB. The default there is 512k and I was seeing some stack overflows for heavy physics sims or very recursive Python stuff.
- If you want to grab recent logs, you can now use `ba.app.log_handler.get_cached()`. This will give you everything that has gone through Python logging, Python stdout/stderr, and the C++ Log() call (up to the max cache size that is).
- LogHandler output now ALWAYS goes to stderr. Previously it only would if an interactive terminal was detected. This should make the binary easier to debug if run from scripts/etc. We can add a `--quiet` option if needed or whatnot.
- (build 20859) Fixed an error setting up asyncio loops under Windows related to the fact that Python is now inited in the main thread.
- (build 20864) Fatal-error message/traceback now properly prints to stderr again (I think the recent logging rejiggering caused it to stop).
- (build 20864) Fixed an issue where the app could crash when connected to the cloud console while in a network game.
- Added a simplified help() command which behaves reasonably under the in-game console or cloud-console.
### 1.7.6 (build 20687, api 7, 2022-08-11) ### 1.7.6 (build 20687, api 7, 2022-08-11)
- Cleaned up da MetaSubsystem code. - Cleaned up the MetaSubsystem code.
- It is now possible to tell the meta system about arbitrary classes (ba_meta export foo.bar.Class) instead of just the preset types 'plugin', 'game', etc. - It is now possible to tell the meta system about arbitrary classes (ba\_meta export foo.bar.Class) instead of just the preset types 'plugin', 'game', etc.
- Newly discovered plugins are now activated immediately instead of requiring a restart. - Newly discovered plugins are now activated immediately instead of requiring a restart.
### 1.7.5 (build 20672, api 7, 2022-07-25) ### 1.7.5 (build 20672, api 7, 2022-07-25)

View File

@ -20,6 +20,10 @@ help:
# Set env-var BA_ENABLE_IRONY_BUILD_DB=1 to enable creating/updating a # Set env-var BA_ENABLE_IRONY_BUILD_DB=1 to enable creating/updating a
# cmake compile-commands database for use with irony for emacs (and possibly # cmake compile-commands database for use with irony for emacs (and possibly
# other tools). # other tools).
# FIXME - this can break if we move/rename files and then run 'make update'
# because it tries to use the previous cmakelist with the no-longer-valid
# filename *before* it updates the cmakelist. Need to rethink order of
# operations there.
ifeq ($(BA_ENABLE_IRONY_BUILD_DB),1) ifeq ($(BA_ENABLE_IRONY_BUILD_DB),1)
PREREQ_IRONY = .cache/irony/compile_commands.json PREREQ_IRONY = .cache/irony/compile_commands.json
endif endif

View File

@ -1 +1 @@
126683827977798484003262787310231621875 137071025041513581787580065580079045765

View File

@ -1 +1 @@
27855823406376609779797608591198912121 139020022013133168311319486434408589898

View File

@ -1108,12 +1108,6 @@ def add_clean_frame_callback(call: Callable) -> None:
return None return None
def add_transaction(transaction: dict,
callback: Callable | None = None) -> None:
"""(internal)"""
return None
def android_get_external_files_dir() -> str: def android_get_external_files_dir() -> str:
"""(internal) """(internal)
@ -1137,6 +1131,11 @@ def android_show_wifi_settings() -> None:
return None return None
def app_instance_uuid() -> str:
"""(internal)"""
return str()
def apply_config() -> None: def apply_config() -> None:
"""(internal)""" """(internal)"""
return None return None
@ -1472,6 +1471,16 @@ def disconnect_from_host() -> None:
return None return None
def display_log(name: str, level: str, message: str) -> None:
"""(internal)
Sends a log message to the in-game console and any per-platform
log destinations (Android log, etc.). This generally is not called
directly and should instead be fed Python logging output.
"""
return None
def do_once() -> bool: def do_once() -> bool:
"""Return whether this is the first time running a line of code. """Return whether this is the first time running a line of code.
@ -1561,15 +1570,6 @@ def focus_window() -> None:
return None return None
def game_service_has_leaderboard(game: str, config: str) -> bool:
"""(internal)
Given a game and config string, returns whether there is a leaderboard
for it on the game service.
"""
return bool()
def get_appconfig_builtin_keys() -> list[str]: def get_appconfig_builtin_keys() -> list[str]:
"""(internal)""" """(internal)"""
return ['blah', 'blah2'] return ['blah', 'blah2']
@ -1700,29 +1700,11 @@ def get_local_active_input_devices_count() -> int:
return int() return int()
def get_log_file_path() -> str:
"""(internal)
Return the path to the app log file.
"""
return str()
def get_low_level_config_value(key: str, default_value: int) -> int: def get_low_level_config_value(key: str, default_value: int) -> int:
"""(internal)""" """(internal)"""
return int() return int()
def get_master_server_address(source: int = -1,
version: int = 1,
internal: bool = False) -> str:
"""(internal)
Return the address of the master server.
"""
return str()
def get_max_graphics_quality() -> str: def get_max_graphics_quality() -> str:
"""(internal) """(internal)
@ -1731,11 +1713,6 @@ def get_max_graphics_quality() -> str:
return str() return str()
def get_news_show() -> str:
"""(internal)"""
return str()
def get_package_collide_model(package: ba.AssetPackage, def get_package_collide_model(package: ba.AssetPackage,
name: str) -> ba.CollideModel: name: str) -> ba.CollideModel:
"""(internal)""" """(internal)"""
@ -1767,16 +1744,6 @@ def get_package_texture(package: ba.AssetPackage, name: str) -> ba.Texture:
return ba.Texture() return ba.Texture()
def get_price(item: str) -> str | None:
"""(internal)"""
return ''
def get_public_login_id() -> str | None:
"""(internal)"""
return ''
def get_public_party_enabled() -> bool: def get_public_party_enabled() -> bool:
"""(internal)""" """(internal)"""
return bool() return bool()
@ -1787,16 +1754,6 @@ def get_public_party_max_size() -> int:
return int() return int()
def get_purchased(item: str) -> bool:
"""(internal)"""
return bool()
def get_purchases_state() -> int:
"""(internal)"""
return int()
def get_qrcode_texture(url: str) -> ba.Texture: def get_qrcode_texture(url: str) -> ba.Texture:
"""(internal)""" """(internal)"""
import ba # pylint: disable=cyclic-import import ba # pylint: disable=cyclic-import
@ -1824,11 +1781,6 @@ def get_replays_dir() -> str:
return str() return str()
def get_scores_to_beat(level: str, config: str, callback: Callable) -> None:
"""(internal)"""
return None
def get_special_widget(name: str) -> Widget: def get_special_widget(name: str) -> Widget:
"""(internal)""" """(internal)"""
return Widget() return Widget()
@ -1872,56 +1824,16 @@ def get_ui_input_device() -> ba.InputDevice:
return ba.InputDevice() return ba.InputDevice()
def get_v1_account_display_string(full: bool = True) -> str: def get_v1_cloud_log() -> str:
"""(internal)""" """(internal)"""
return str() return str()
def get_v1_account_misc_read_val(name: str, default_value: Any) -> Any: def get_v1_cloud_log_file_path() -> str:
"""(internal)"""
return _uninferrable()
def get_v1_account_misc_read_val_2(name: str, default_value: Any) -> Any:
"""(internal)"""
return _uninferrable()
def get_v1_account_misc_val(name: str, default_value: Any) -> Any:
"""(internal)"""
return _uninferrable()
def get_v1_account_name() -> str:
"""(internal)"""
return str()
def get_v1_account_state() -> str:
"""(internal)"""
return str()
def get_v1_account_state_num() -> int:
"""(internal)"""
return int()
def get_v1_account_ticket_count() -> int:
"""(internal) """(internal)
Returns the number of tickets for the current account. Return the path to the app log file.
""" """
return int()
def get_v1_account_type() -> str:
"""(internal)"""
return str()
def get_v2_fleet() -> str:
"""(internal)"""
return str() return str()
@ -2015,11 +1927,6 @@ def getinputdevice(name: str, unique_id: str, doraise: bool = True) -> Any:
return None return None
def getlog() -> str:
"""(internal)"""
return str()
def getmodel(name: str) -> ba.Model: def getmodel(name: str) -> ba.Model:
"""Return a model, loading it if necessary. """Return a model, loading it if necessary.
@ -2129,11 +2036,6 @@ def have_incentivized_ad() -> bool:
return bool() return bool()
def have_outstanding_transactions() -> bool:
"""(internal)"""
return bool()
def have_permission(permission: ba.Permission) -> bool: def have_permission(permission: ba.Permission) -> bool:
"""(internal)""" """(internal)"""
return bool() return bool()
@ -2210,15 +2112,10 @@ def imagewidget(edit: ba.Widget | None = None,
return ba.Widget() return ba.Widget()
def in_game_purchase(item: str, price: int) -> None:
"""(internal)"""
return None
def in_logic_thread() -> bool: def in_logic_thread() -> bool:
"""(internal) """(internal)
Returns whether or not the current thread is the game thread. Returns whether or not the current thread is the logic thread.
""" """
return bool() return bool()
@ -2240,11 +2137,6 @@ def increment_analytics_counts_raw(name: str, increment: int = 1) -> None:
return None return None
def is_blessed() -> bool:
"""(internal)"""
return bool()
def is_in_replay() -> bool: def is_in_replay() -> bool:
"""(internal)""" """(internal)"""
return bool() return bool()
@ -2301,22 +2193,6 @@ def lock_all_input() -> None:
return None return None
def log(message: str, to_stdout: bool = True, to_server: bool = True) -> None:
"""Category: **General Utility Functions**
Log a message. This goes to the default logging mechanism depending
on the platform (stdout on mac, android log on android, etc).
Log messages also go to the in-game console unless 'to_console'
is False. They are also sent to the master-server for use in analyzing
issues unless to_server is False.
Python's standard print() is wired to call this (with default values)
so in most cases you can just use that.
"""
return None
def mac_music_app_get_library_source() -> None: def mac_music_app_get_library_source() -> None:
"""(internal)""" """(internal)"""
return None return None
@ -2352,14 +2228,6 @@ def mac_music_app_stop() -> None:
return None return None
def mark_config_dirty() -> None:
"""(internal)
Category: General Utility Functions
"""
return None
def mark_log_sent() -> None: def mark_log_sent() -> None:
"""(internal)""" """(internal)"""
return None return None
@ -2488,11 +2356,6 @@ def playsound(sound: Sound,
return None return None
def power_ranking_query(callback: Callable, season: Any = None) -> None:
"""(internal)"""
return None
def print_context() -> None: def print_context() -> None:
"""(internal) """(internal)
@ -2509,23 +2372,6 @@ def print_load_info() -> None:
return None return None
def print_stderr(message: str) -> None:
"""(internal)
Print to system stderr.
Also forwards to the internal console, etc.
"""
return None
def print_stdout(message: str) -> None:
"""(internal)
Print to system stdout.
Also forwards to the internal console, etc.
"""
return None
def printnodes() -> None: def printnodes() -> None:
"""Print various info about existing nodes; useful for debugging. """Print various info about existing nodes; useful for debugging.
@ -2545,14 +2391,10 @@ def printobjects() -> None:
return None return None
def purchase(item: str) -> None:
"""(internal)"""
return None
def pushcall(call: Callable, def pushcall(call: Callable,
from_other_thread: bool = False, from_other_thread: bool = False,
suppress_other_thread_warning: bool = False) -> None: suppress_other_thread_warning: bool = False,
other_thread_use_fg_context: bool = False) -> None:
"""Pushes a call onto the event loop to be run during the next cycle. """Pushes a call onto the event loop to be run during the next cycle.
Category: **General Utility Functions** Category: **General Utility Functions**
@ -2560,12 +2402,14 @@ def pushcall(call: Callable,
This can be handy for calls that are disallowed from within other This can be handy for calls that are disallowed from within other
callbacks, etc. callbacks, etc.
This call expects to be used in the game thread, and will automatically This call expects to be used in the logic thread, and will automatically
save and restore the ba.Context to behave seamlessly. save and restore the ba.Context to behave seamlessly.
If you want to push a call from outside of the game thread, If you want to push a call from outside of the logic thread,
however, you can pass 'from_other_thread' as True. In this case however, you can pass 'from_other_thread' as True. In this case
the call will always run in the UI context on the game thread. the call will always run in the UI context on the logic thread
or whichever context is in the foreground if
other_thread_use_fg_context is True.
""" """
return None return None
@ -2616,21 +2460,11 @@ def reload_media() -> None:
return None return None
def report_achievement(achievement: str, pass_to_account: bool = True) -> None:
"""(internal)"""
return None
def request_permission(permission: ba.Permission) -> None: def request_permission(permission: ba.Permission) -> None:
"""(internal)""" """(internal)"""
return None return None
def reset_achievements() -> None:
"""(internal)"""
return None
def reset_game_activity_tracking() -> None: def reset_game_activity_tracking() -> None:
"""(internal)""" """(internal)"""
return None return None
@ -2646,11 +2480,6 @@ def resolve_appconfig_value(key: str) -> Any:
return _uninferrable() return _uninferrable()
def restore_purchases() -> None:
"""(internal)"""
return None
def rowwidget(edit: ba.Widget | None = None, def rowwidget(edit: ba.Widget | None = None,
parent: ba.Widget | None = None, parent: ba.Widget | None = None,
size: Sequence[float] | None = None, size: Sequence[float] | None = None,
@ -2673,11 +2502,6 @@ def rowwidget(edit: ba.Widget | None = None,
return ba.Widget() return ba.Widget()
def run_transactions() -> None:
"""(internal)"""
return None
def safecolor(color: Sequence[float], def safecolor(color: Sequence[float],
target_intensity: float = 0.6) -> tuple[float, ...]: target_intensity: float = 0.6) -> tuple[float, ...]:
"""Given a color tuple, return a color safe to display as text. """Given a color tuple, return a color safe to display as text.
@ -2702,11 +2526,12 @@ def screenmessage(message: str | ba.Lstr,
Category: **General Utility Functions** Category: **General Utility Functions**
If 'top' is True, the message will go to the top message area. If 'top' is True, the message will go to the top message area.
For 'top' messages, 'image' can be a texture to display alongside the For 'top' messages, 'image' must be a dict containing 'texture'
message. and 'tint_texture' textures and 'tint_color' and 'tint2_color'
If 'log' is True, the message will also be printed to the output log colors. This defines an icon to display alongside the message.
'clients' can be a list of client-ids the message should be sent to, If 'log' is True, the message will also be submitted to the log.
or None to specify that everyone should receive it. 'clients' can be a list of client-ids the message should be sent
to, or None to specify that everyone should receive it.
If 'transient' is True, the message will not be included in the If 'transient' is True, the message will not be included in the
game-stream and thus will not show up when viewing replays. game-stream and thus will not show up when viewing replays.
Currently the 'clients' option only works for transient messages. Currently the 'clients' option only works for transient messages.
@ -2953,48 +2778,11 @@ def show_progress_bar() -> None:
return None return None
def sign_in_v1(account_type: str) -> None:
"""(internal)
Category: General Utility Functions
"""
return None
def sign_out_v1(v2_embedded: bool = False) -> None:
"""(internal)
Category: General Utility Functions
"""
return None
def submit_analytics_counts() -> None: def submit_analytics_counts() -> None:
"""(internal)""" """(internal)"""
return None return None
def submit_score(game: str,
config: str,
name: Any,
score: int | None,
callback: Callable,
friend_callback: Callable | None,
order: str = 'increasing',
tournament_id: str | None = None,
score_type: str = 'points',
campaign: str | None = None,
level: str | None = None) -> None:
"""(internal)
Submit a score to the server; callback will be called with the results.
As a courtesy, please don't send fake scores to the server. I'd prefer
to devote my time to improving the game instead of trying to make the
score server more mischief-proof.
"""
return None
def textwidget(edit: ba.Widget | None = None, def textwidget(edit: ba.Widget | None = None,
parent: ba.Widget | None = None, parent: ba.Widget | None = None,
size: Sequence[float] | None = None, size: Sequence[float] | None = None,
@ -3173,12 +2961,6 @@ def timer(time: float,
return None return None
def tournament_query(callback: Callable[[dict | None], None],
args: dict) -> None:
"""(internal)"""
return None
def uibounds() -> tuple[float, float, float, float]: def uibounds() -> tuple[float, float, float, float]:
"""(internal) """(internal)
@ -3198,6 +2980,19 @@ def unlock_all_input() -> None:
return None return None
def user_ran_commands() -> None:
"""(internal)"""
return None
def v1_cloud_log(message: str) -> None:
"""(internal)
Push messages to the old v1 cloud log.
"""
return None
def value_test(arg: str, def value_test(arg: str,
change: float | None = None, change: float | None = None,
absolute: float | None = None) -> float: absolute: float | None = None) -> float:

View File

@ -13,12 +13,11 @@ from _ba import (
Node, SessionPlayer, Sound, Texture, Timer, Vec3, Widget, buttonwidget, Node, SessionPlayer, Sound, Texture, Timer, Vec3, Widget, buttonwidget,
camerashake, checkboxwidget, columnwidget, containerwidget, do_once, camerashake, checkboxwidget, columnwidget, containerwidget, do_once,
emitfx, getactivity, getcollidemodel, getmodel, getnodes, getsession, emitfx, getactivity, getcollidemodel, getmodel, getnodes, getsession,
getsound, gettexture, hscrollwidget, imagewidget, log, newactivity, getsound, gettexture, hscrollwidget, imagewidget, newactivity, newnode,
newnode, playsound, printnodes, printobjects, pushcall, quit, rowwidget, playsound, printnodes, printobjects, pushcall, quit, rowwidget, safecolor,
safecolor, screenmessage, scrollwidget, set_analytics_screen, charstr, screenmessage, scrollwidget, set_analytics_screen, charstr, textwidget,
textwidget, time, timer, open_url, widget, clipboard_is_supported, time, timer, open_url, widget, clipboard_is_supported, clipboard_has_text,
clipboard_has_text, clipboard_get_text, clipboard_set_text, getdata, clipboard_get_text, clipboard_set_text, getdata, in_logic_thread)
in_logic_thread)
from ba._activity import Activity from ba._activity import Activity
from ba._plugin import PotentialPlugin, Plugin, PluginSubsystem from ba._plugin import PotentialPlugin, Plugin, PluginSubsystem
from ba._actor import Actor from ba._actor import Actor
@ -103,7 +102,7 @@ __all__ = [
'ImpactDamageMessage', 'in_logic_thread', 'InputDevice', 'ImpactDamageMessage', 'in_logic_thread', 'InputDevice',
'InputDeviceNotFoundError', 'InputType', 'IntChoiceSetting', 'IntSetting', 'InputDeviceNotFoundError', 'InputType', 'IntChoiceSetting', 'IntSetting',
'is_browser_likely_available', 'is_point_in_box', 'Keyboard', 'is_browser_likely_available', 'is_point_in_box', 'Keyboard',
'LanguageSubsystem', 'Level', 'Lobby', 'log', 'Lstr', 'Map', 'Material', 'LanguageSubsystem', 'Level', 'Lobby', 'Lstr', 'Map', 'Material',
'MetadataSubsystem', 'Model', 'MultiTeamSession', 'MusicPlayer', 'MetadataSubsystem', 'Model', 'MultiTeamSession', 'MusicPlayer',
'MusicPlayMode', 'MusicSubsystem', 'MusicType', 'newactivity', 'newnode', 'MusicPlayMode', 'MusicSubsystem', 'MusicType', 'newactivity', 'newnode',
'Node', 'NodeActor', 'NodeNotFoundError', 'normalized_color', 'Node', 'NodeActor', 'NodeNotFoundError', 'normalized_color',

View File

@ -26,6 +26,7 @@ if TYPE_CHECKING:
import asyncio import asyncio
from typing import Any, Callable from typing import Any, Callable
import efro.log
import ba import ba
from ba._cloud import CloudSubsystem from ba._cloud import CloudSubsystem
from bastd.actor import spazappearance from bastd.actor import spazappearance
@ -49,6 +50,7 @@ class App:
# Implementations for these will be filled in by internal libs. # Implementations for these will be filled in by internal libs.
accounts_v2: AccountV2Subsystem accounts_v2: AccountV2Subsystem
cloud: CloudSubsystem cloud: CloudSubsystem
log_handler: efro.log.LogHandler
class State(Enum): class State(Enum):
"""High level state the app can be in.""" """High level state the app can be in."""
@ -384,7 +386,7 @@ class App:
# If there's a leftover log file, attempt to upload it to the # If there's a leftover log file, attempt to upload it to the
# master-server and/or get rid of it. # master-server and/or get rid of it.
_apputils.handle_leftover_log_file() _apputils.handle_leftover_v1_cloud_log_file()
# Only do this stuff if our config file is healthy so we don't # Only do this stuff if our config file is healthy so we don't
# overwrite a broken one or whatnot and wipe out data. # overwrite a broken one or whatnot and wipe out data.

View File

@ -128,12 +128,6 @@ def read_config() -> tuple[AppConfig, bool]:
shutil.copyfile(config_file_path, config_file_path + '.broken') shutil.copyfile(config_file_path, config_file_path + '.broken')
except Exception as exc2: except Exception as exc2:
print('EXC copying broken config:', exc2) print('EXC copying broken config:', exc2)
try:
_ba.log('broken config contents:\n' +
config_contents.replace('\000', '<NULL_BYTE>'),
to_stdout=False)
except Exception as exc2:
print('EXC logging broken config contents:', exc2)
config = AppConfig() config = AppConfig()
# Now attempt to read one of our 'prev' backup copies. # Now attempt to read one of our 'prev' backup copies.

View File

@ -50,7 +50,7 @@ def should_submit_debug_info() -> bool:
return _ba.app.config.get('Submit Debug Info', True) return _ba.app.config.get('Submit Debug Info', True)
def handle_log() -> None: def handle_v1_cloud_log() -> None:
"""Called on debug log prints. """Called on debug log prints.
When this happens, we can upload our log to the server When this happens, we can upload our log to the server
@ -74,7 +74,7 @@ def handle_log() -> None:
activityname = 'unavailable' activityname = 'unavailable'
info = { info = {
'log': _ba.getlog(), 'log': _ba.get_v1_cloud_log(),
'version': app.version, 'version': app.version,
'build': app.build_number, 'build': app.build_number,
'userAgentString': app.user_agent_string, 'userAgentString': app.user_agent_string,
@ -108,7 +108,7 @@ def handle_log() -> None:
def _reset() -> None: def _reset() -> None:
app.log_upload_timer_started = False app.log_upload_timer_started = False
if app.log_have_new: if app.log_have_new:
handle_log() handle_v1_cloud_log()
if not _ba.is_log_full(): if not _ba.is_log_full():
with _ba.Context('ui'): with _ba.Context('ui'):
@ -118,14 +118,15 @@ def handle_log() -> None:
suppress_format_warning=True) suppress_format_warning=True)
def handle_leftover_log_file() -> None: def handle_leftover_v1_cloud_log_file() -> None:
"""Handle an un-uploaded log from a previous run.""" """Handle an un-uploaded v1-cloud-log from a previous run."""
try: try:
import json import json
from ba._net import master_server_post from ba._net import master_server_post
if os.path.exists(_ba.get_log_file_path()): if os.path.exists(_ba.get_v1_cloud_log_file_path()):
with open(_ba.get_log_file_path(), encoding='utf-8') as infile: with open(_ba.get_v1_cloud_log_file_path(),
encoding='utf-8') as infile:
info = json.loads(infile.read()) info = json.loads(infile.read())
infile.close() infile.close()
do_send = should_submit_debug_info() do_send = should_submit_debug_info()
@ -136,7 +137,7 @@ def handle_leftover_log_file() -> None:
# lets kill it. # lets kill it.
if data is not None: if data is not None:
try: try:
os.remove(_ba.get_log_file_path()) os.remove(_ba.get_v1_cloud_log_file_path())
except FileNotFoundError: except FileNotFoundError:
# Saw this in the wild. The file just existed # Saw this in the wild. The file just existed
# a moment ago but I suppose something could have # a moment ago but I suppose something could have
@ -146,7 +147,7 @@ def handle_leftover_log_file() -> None:
master_server_post('bsLog', info, response) master_server_post('bsLog', info, response)
else: else:
# If they don't want logs uploaded just kill it. # If they don't want logs uploaded just kill it.
os.remove(_ba.get_log_file_path()) os.remove(_ba.get_v1_cloud_log_file_path())
except Exception: except Exception:
from ba import _error from ba import _error
_error.print_exception('Error handling leftover log file.') _error.print_exception('Error handling leftover log file.')

View File

@ -18,7 +18,7 @@ import os
if TYPE_CHECKING: if TYPE_CHECKING:
import ba import ba
# Our timer and event loop for the ballistica game thread. # Our timer and event loop for the ballistica logic thread.
_asyncio_timer: ba.Timer | None = None _asyncio_timer: ba.Timer | None = None
_asyncio_event_loop: asyncio.AbstractEventLoop | None = None _asyncio_event_loop: asyncio.AbstractEventLoop | None = None

View File

@ -5,14 +5,14 @@ from __future__ import annotations
import os import os
import sys import sys
import signal
import threading
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.log import setup_logging, LogLevel
import _ba import _ba
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, TextIO, Callable from typing import Any
from efro.log import LogEntry
_g_did_bootstrap = False # pylint: disable=invalid-name _g_did_bootstrap = False # pylint: disable=invalid-name
@ -20,25 +20,32 @@ _g_did_bootstrap = False # pylint: disable=invalid-name
def bootstrap() -> None: def bootstrap() -> None:
"""Run bootstrapping logic. """Run bootstrapping logic.
This is the very first userland code that runs. This is the very first ballistica code that runs (aside from imports).
It sets up low level environment bits and creates the app instance. It sets up low level environment bits and creates the app instance.
""" """
global _g_did_bootstrap # pylint: disable=global-statement, invalid-name global _g_did_bootstrap # pylint: disable=global-statement, invalid-name
if _g_did_bootstrap: if _g_did_bootstrap:
raise RuntimeError('Bootstrap has already been called.') raise RuntimeError('Bootstrap has already been called.')
_g_did_bootstrap = True _g_did_bootstrap = True
# The first thing we set up is capturing/redirecting Python # The first thing we do is set up our logging system and feed
# stdout/stderr so we can at least debug problems on systems where # Python's stdout/stderr into it. Then we can at least debug problems
# native stdout/stderr is not easily accessible (looking at you, Android). # on systems where native stdout/stderr is not easily accessible
sys.stdout = _Redirect(sys.stdout, _ba.print_stdout) # type: ignore # such as Android.
sys.stderr = _Redirect(sys.stderr, _ba.print_stderr) # type: ignore log_handler = setup_logging(log_path=None,
level=LogLevel.DEBUG,
suppress_non_root_debug=True,
log_stdout_stderr=True,
cache_size_limit=1024 * 1024)
log_handler.add_callback(_on_log)
env = _ba.env() env = _ba.env()
# Give a soft warning if we're being used with a different binary # Give a soft warning if we're being used with a different binary
# version than we expect. # version than we expect.
expected_build = 20798 expected_build = 20877
running_build: int = env['build_number'] running_build: int = env['build_number']
if running_build != expected_build: if running_build != expected_build:
print( print(
@ -48,16 +55,11 @@ def bootstrap() -> None:
f' This might cause the app to error or misbehave.', f' This might cause the app to error or misbehave.',
file=sys.stderr) file=sys.stderr)
# Tell Python to not handle SIGINT itself (it normally generates # In bootstrap_monolithic.py we told Python not to handle SIGINT itself
# KeyboardInterrupts which make a mess; we want to intercept them # (because that must be done in the main thread). Now we finish the
# for simple clean exit). We capture interrupts per-platform in # job by adding our own handler to replace it.
# the C++ layer.
# Note: I tried creating a handler in Python but it seemed to often have
# a delay of up to a second before getting called. (not a huge deal
# but I'm picky).
signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.
# ..though it turns out we need to set up our C signal handling AFTER # Note: I've found we need to set up our C signal handling AFTER
# we've told Python to disable its own; otherwise (on Mac at least) it # we've told Python to disable its own; otherwise (on Mac at least) it
# wipes out our existing C handler. # wipes out our existing C handler.
_ba.setup_sigint() _ba.setup_sigint()
@ -91,101 +93,83 @@ def bootstrap() -> None:
os.environ['SSL_CERT_FILE'] = os.environ['REQUESTS_CA_BUNDLE'] = ( os.environ['SSL_CERT_FILE'] = os.environ['REQUESTS_CA_BUNDLE'] = (
certifi.where()) certifi.where())
# FIXME: I think we should init Python in the main thread, which should # On Windows I'm seeing the following error creating asyncio loops in
# also avoid these issues. (and also might help us play better with # background threads with the default proactor setup:
# Python debuggers?) # ValueError: set_wakeup_fd only works in main thread of the main
# interpreter
# So let's explicitly request selector loops.
# Interestingly this error only started showing up once I moved
# Python init to the main thread; previously the various asyncio
# bg thread loops were working fine (maybe something caused them
# to default to selector in that case?..
if sys.platform == 'win32':
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
# Gloriously hacky workaround here:
# Our 'main' Python thread is the game thread (not the app's main
# thread) which means it has a small stack compared to the main
# thread (at least on apple). Sadly it turns out this causes the
# debug build of Python to blow its stack immediately when doing
# some big imports.
# Normally we'd just give the game thread the same stack size as
# the main thread and that'd be the end of it. However
# we're using std::threads which it turns out have no way to set
# the stack size (as of fall '19). Grumble.
#
# However python threads *can* take custom stack sizes.
# (and it appears they might use the main thread's by default?..)
# ...so as a workaround in the debug version, we can run problematic
# heavy imports here in another thread and all is well.
# If we ever see stack overflows in our release build we'll have
# to take more drastic measures like switching from std::threads
# to pthreads.
if debug_build:
# noinspection PyUnresolvedReferences
def _thread_func() -> None:
# pylint: disable=unused-import
import json
import urllib.request
testthread = threading.Thread(target=_thread_func)
testthread.start()
testthread.join()
del testthread
# Clear out the standard quit/exit messages since they don't work for us.
# pylint: disable=c-extension-no-member # pylint: disable=c-extension-no-member
if not TYPE_CHECKING: if not TYPE_CHECKING:
import __main__ import __main__
# Clear out the standard quit/exit messages since they don't
# work for us.
del __main__.__builtins__.quit del __main__.__builtins__.quit
del __main__.__builtins__.exit del __main__.__builtins__.exit
# Also replace standard interactive help with our simplified
# one which is more friendly to cloud/in-game console situations.
__main__.__builtins__.help = _CustomHelper()
# Now spin up our App instance and store it on both _ba and ba. # Now spin up our App instance and store it on both _ba and ba.
from ba._app import App from ba._app import App
import ba import ba
_ba.app = ba.app = App() _ba.app = ba.app = App()
_ba.app.log_handler = log_handler
class _Redirect: class _CustomHelper:
"""Replacement 'help' that behaves better for our setup."""
def __init__(self, original: TextIO, call: Callable[[str], None]) -> None: def __repr__(self) -> str:
self._lock = threading.Lock() return 'Type help(object) for help about object.'
self._linebits: list[str] = []
self._original = original
self._call = call
self._pending_ship = False
def write(self, sval: Any) -> None: def __call__(self, *args: Any, **kwds: Any) -> Any:
"""Override standard write call.""" # We get an ugly error importing pydoc on our embedded
# platforms due to _sysconfigdata_xxx.py not being present
# (but then things mostly work). Let's get the ugly error out
# of the way explicitly.
import sysconfig
try:
# This errors once but seems to run cleanly after, so let's
# get the error out of the way.
sysconfig.get_path('stdlib')
except ModuleNotFoundError:
pass
self._call(sval) import pydoc
# Disable pager and interactive help since neither works well
# with our funky multi-threaded setup or in-game/cloud consoles.
# Let's just do simple text dumps.
pydoc.pager = pydoc.plainpager
if not args and not kwds:
print('Interactive help is not available in this environment.\n'
'Type help(object) for help about object.')
return None
return pydoc.help(*args, **kwds)
# Now do logging:
# Add it to our accumulated line.
# If the message ends in a newline, we can ship it
# immediately as a log entry. Otherwise, schedule a ship
# next cycle (if it hasn't yet at that point) so that we
# can accumulate subsequent prints.
# (so stuff like print('foo', 123, 'bar') will ship as one entry)
with self._lock:
self._linebits.append(sval)
if sval.endswith('\n'):
self._shiplog()
else:
_ba.pushcall(self._shiplog,
from_other_thread=True,
suppress_other_thread_warning=True)
def _shiplog(self) -> None: def _on_log(entry: LogEntry) -> None:
with self._lock:
line = ''.join(self._linebits)
if not line:
return
self._linebits = []
# Log messages aren't expected to have trailing newlines. # Just forward this along to the engine to display in the in-game console,
if line.endswith('\n'): # in the Android log, etc.
line = line[:-1] _ba.display_log(
_ba.log(line, to_stdout=False) name=entry.name,
level=entry.level.name,
message=entry.message,
)
def flush(self) -> None: # We also want to feed some logs to the old V1-cloud-log system.
"""Flush the file.""" # Let's go with anything warning or higher as well as the stdout/stderr
self._original.flush() # log messages that ba.app.log_handler creates for us.
if entry.level.value >= LogLevel.WARNING.value or entry.name in ('stdout',
def isatty(self) -> bool: 'stderr'):
"""Are we a terminal?""" _ba.v1_cloud_log(entry.message)
return self._original.isatty()

View File

@ -55,19 +55,6 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
# Preload achievement images in case we get some. # Preload achievement images in case we get some.
_ba.timer(2.0, WeakCall(self._preload_achievements)) _ba.timer(2.0, WeakCall(self._preload_achievements))
# Let's ask the server for a 'time-to-beat' value.
levelname = self._get_coop_level_name()
campaign = self.session.campaign
assert campaign is not None
config_str = (str(len(self.players)) + 'p' + campaign.getlevel(
self.settings_raw['name']).get_score_version_string().replace(
' ', '_'))
_ba.get_scores_to_beat(levelname, config_str,
WeakCall(self._on_got_scores_to_beat))
def _on_got_scores_to_beat(self, scores: list[dict[str, Any]]) -> None:
pass
def _show_standard_scores_to_beat_ui(self, def _show_standard_scores_to_beat_ui(self,
scores: list[dict[str, Any]]) -> None: scores: list[dict[str, Any]]) -> None:
from efro.util import asserttype from efro.util import asserttype

View File

@ -125,6 +125,11 @@ class WidgetNotFoundError(NotFoundError):
""" """
# TODO: Should integrate some sort of context printing into our
# log handling so we can just use logging.exception() and kill these
# two functions.
def print_exception(*args: Any, **keywds: Any) -> None: def print_exception(*args: Any, **keywds: Any) -> None:
"""Print info about an exception along with pertinent context state. """Print info about an exception along with pertinent context state.

View File

@ -28,7 +28,7 @@ def finish_bootstrapping() -> None:
assert _ba.in_logic_thread() assert _ba.in_logic_thread()
# Kick off our asyncio event handling, allowing us to use coroutines # Kick off our asyncio event handling, allowing us to use coroutines
# in our game thread alongside our internal event handling. # in our logic thread alongside our internal event handling.
# setup_asyncio() # setup_asyncio()
# Ok, bootstrapping is done; time to get the show started. # Ok, bootstrapping is done; time to get the show started.

View File

@ -192,13 +192,13 @@ class MetadataSubsystem:
color=(1, 0, 0)) color=(1, 0, 0))
_ba.playsound(_ba.getsound('error')) _ba.playsound(_ba.getsound('error'))
if results.warnings: if results.warnings:
_ba.log(textwrap.indent('\n'.join(results.warnings), allwarnings = textwrap.indent('\n'.join(results.warnings),
'Warning (meta-scan): '), 'Warning (meta-scan): ')
to_server=False) logging.warning(allwarnings)
if results.errors: if results.errors:
_ba.log( allerrors = textwrap.indent('\n'.join(results.errors),
textwrap.indent('\n'.join(results.errors), 'Error (meta-scan): ')
'Error (meta-scan): ')) logging.error(allerrors)
# Let the game know we're done. # Let the game know we're done.
assert self._scan_complete_cb is not None assert self._scan_complete_cb is not None

View File

@ -5,6 +5,7 @@
from __future__ import annotations from __future__ import annotations
import copy import copy
import logging
from typing import Any, TYPE_CHECKING from typing import Any, TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -29,7 +30,6 @@ def filter_playlist(playlist: PlaylistType,
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
import _ba
from ba._map import get_filtered_map_name from ba._map import get_filtered_map_name
from ba._store import get_unowned_maps, get_unowned_game_types from ba._store import get_unowned_maps, get_unowned_game_types
from ba._general import getclass from ba._general import getclass
@ -140,8 +140,8 @@ def filter_playlist(playlist: PlaylistType,
entry['settings'][setting.name] = setting.default entry['settings'][setting.name] = setting.default
goodlist.append(entry) goodlist.append(entry)
except ImportError as exc: except ImportError as exc:
_ba.log(f'Import failed while scanning playlist \'{name}\': {exc}', logging.warning('Import failed while scanning playlist \'%s\': %s',
to_server=False) name, exc)
except Exception: except Exception:
from ba import _error from ba import _error
_error.print_exception() _error.print_exception()

View File

@ -4,6 +4,7 @@
from __future__ import annotations from __future__ import annotations
import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from dataclasses import dataclass from dataclasses import dataclass
@ -127,8 +128,7 @@ class PluginSubsystem:
subs=[('${PLUGIN}', plugkey), subs=[('${PLUGIN}', plugkey),
('${ERROR}', str(exc))]), ('${ERROR}', str(exc))]),
color=(1, 0, 0)) color=(1, 0, 0))
_ba.log(f"Error loading plugin class '{plugkey}': {exc}", logging.exception("Error loading plugin class '%s'", plugkey)
to_server=False)
continue continue
try: try:
plugin = cls() plugin = cls()
@ -155,10 +155,8 @@ class PluginSubsystem:
color=(1, 1, 0), color=(1, 1, 0),
) )
plugnames = ', '.join(disappeared_plugs) plugnames = ', '.join(disappeared_plugs)
_ba.log( logging.warning('%d plugin(s) no longer found: %s.',
f'{len(disappeared_plugs)} plugin(s) no longer found:' len(disappeared_plugs), plugnames)
f' {plugnames}.',
to_server=False)
for goneplug in disappeared_plugs: for goneplug in disappeared_plugs:
del _ba.app.config['Plugins'][goneplug] del _ba.app.config['Plugins'][goneplug]
_ba.app.config.commit() _ba.app.config.commit()

View File

@ -5,6 +5,7 @@ from __future__ import annotations
import sys import sys
import time import time
import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.terminal import Clr from efro.terminal import Clr
@ -334,11 +335,11 @@ class ServerController:
if self._first_run: if self._first_run:
curtimestr = time.strftime('%c') curtimestr = time.strftime('%c')
_ba.log( startupmsg = (
f'{Clr.BLD}{Clr.BLU}{_ba.appnameupper()} {app.version}' f'{Clr.BLD}{Clr.BLU}{_ba.appnameupper()} {app.version}'
f' ({app.build_number})' f' ({app.build_number})'
f' entering server-mode {curtimestr}{Clr.RST}', f' entering server-mode {curtimestr}{Clr.RST}')
to_server=False) logging.info(startupmsg)
if sessiontype is FreeForAllSession: if sessiontype is FreeForAllSession:
appcfg['Free-for-All Playlist Selection'] = self._playlist_name appcfg['Free-for-All Playlist Selection'] = self._playlist_name

View File

@ -9,16 +9,16 @@ defensively) in mods.
from __future__ import annotations from __future__ import annotations
from _ba import ( from _ba import (
get_scores_to_beat, show_online_score_ui, set_ui_input_device, show_online_score_ui, set_ui_input_device, is_party_icon_visible,
is_party_icon_visible, getinputdevice, add_clean_frame_callback, getinputdevice, add_clean_frame_callback, unlock_all_input,
unlock_all_input, increment_analytics_count, set_debug_speed_exponent, increment_analytics_count, set_debug_speed_exponent, get_special_widget,
get_special_widget, get_qrcode_texture, get_string_height, get_qrcode_texture, get_string_height, get_string_width, show_app_invite,
get_string_width, show_app_invite, appnameupper, lock_all_input, appnameupper, lock_all_input, open_file_externally, fade_screen, appname,
open_file_externally, fade_screen, appname, have_incentivized_ad, have_incentivized_ad, has_video_ads, workspaces_in_use,
has_video_ads, workspaces_in_use, set_party_icon_always_visible, set_party_icon_always_visible, connect_to_party, get_game_port,
connect_to_party, get_game_port, end_host_scanning, host_scan_cycle, end_host_scanning, host_scan_cycle, charstr, get_public_party_enabled,
charstr, get_public_party_enabled, get_public_party_max_size, get_public_party_max_size, set_public_party_name,
set_public_party_name, set_public_party_max_size, set_authenticate_clients, set_public_party_max_size, set_authenticate_clients,
set_public_party_enabled, reset_random_player_names, new_host_session, set_public_party_enabled, reset_random_player_names, new_host_session,
get_foreground_host_session, get_local_active_input_devices_count, get_foreground_host_session, get_local_active_input_devices_count,
get_ui_input_device, is_in_replay, set_replay_speed_exponent, get_ui_input_device, is_in_replay, set_replay_speed_exponent,
@ -78,7 +78,6 @@ from ba._internal import (
sign_out_v1, sign_in_v1, mark_config_dirty) sign_out_v1, sign_in_v1, mark_config_dirty)
__all__ = [ __all__ = [
'get_scores_to_beat',
'show_online_score_ui', 'show_online_score_ui',
'set_ui_input_device', 'set_ui_input_device',
'is_party_icon_visible', 'is_party_icon_visible',

View File

@ -10,7 +10,7 @@ import ba
from ba.internal import JoinActivity from ba.internal import JoinActivity
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Sequence pass
class CoopJoinActivity(JoinActivity): class CoopJoinActivity(JoinActivity):
@ -24,17 +24,6 @@ class CoopJoinActivity(JoinActivity):
session = self.session session = self.session
assert isinstance(session, ba.CoopSession) assert isinstance(session, ba.CoopSession)
# Let's show a list of scores-to-beat for 1 player at least.
assert session.campaign is not None
level_name_full = (session.campaign.name + ':' +
session.campaign_level_name)
config_str = ('1p' + session.campaign.getlevel(
session.campaign_level_name).get_score_version_string().replace(
' ', '_'))
ba.internal.get_scores_to_beat(
level_name_full, config_str,
ba.WeakCall(self._on_got_scores_to_beat))
def on_transition_in(self) -> None: def on_transition_in(self) -> None:
from bastd.actor.controlsguide import ControlsGuide from bastd.actor.controlsguide import ControlsGuide
from bastd.actor.text import Text from bastd.actor.text import Text
@ -53,143 +42,61 @@ class CoopJoinActivity(JoinActivity):
position=(0, -95)).autoretain() position=(0, -95)).autoretain()
ControlsGuide(delay=1.0).autoretain() ControlsGuide(delay=1.0).autoretain()
def _on_got_scores_to_beat(self, ba.pushcall(self._show_remaining_achievements)
scores: list[dict[str, Any]] | None) -> None:
# pylint: disable=too-many-locals
# pylint: disable=too-many-statements
from efro.util import asserttype
from bastd.actor.text import Text
# Sort by originating date so that the most recent is first. def _show_remaining_achievements(self) -> None:
if scores is not None: from bastd.actor.text import Text
scores.sort(reverse=True,
key=lambda score: asserttype(score['time'], int))
# We only show achievements and challenges for CoopGameActivities. # We only show achievements and challenges for CoopGameActivities.
session = self.session session = self.session
assert isinstance(session, ba.CoopSession) assert isinstance(session, ba.CoopSession)
gameinstance = session.get_current_game_instance() gameinstance = session.get_current_game_instance()
if isinstance(gameinstance, ba.CoopGameActivity): if not isinstance(gameinstance, ba.CoopGameActivity):
score_type = gameinstance.get_score_type() return
if scores is not None:
achievement_challenges = [
a for a in scores if a['type'] == 'achievement_challenge'
]
score_challenges = [
a for a in scores if a['type'] == 'score_challenge'
]
else:
achievement_challenges = score_challenges = []
delay = 1.0 delay = 1.0
vpos = -140.0 vpos = -140.0
spacing = 25
delay_inc = 0.1
def _add_t( # Now list our remaining achievements for this level.
text: str | ba.Lstr, assert self.session.campaign is not None
h_offs: float = 0.0, assert isinstance(self.session, ba.CoopSession)
scale: float = 1.0, levelname = (self.session.campaign.name + ':' +
color: Sequence[float] = (1.0, 1.0, 1.0, 0.46) self.session.campaign_level_name)
) -> None: ts_h_offs = 60
Text(text,
scale=scale * 0.76, if not (ba.app.demo_mode or ba.app.arcade_mode):
h_align=Text.HAlign.LEFT, achievements = [
a for a in ba.app.ach.achievements_for_coop_level(levelname)
if not a.complete
]
have_achievements = bool(achievements)
achievements = [a for a in achievements if not a.complete]
vrmode = ba.app.vr_mode
if have_achievements:
Text(ba.Lstr(resource='achievementsRemainingText'),
host_only=True,
position=(ts_h_offs - 10, vpos),
transition=Text.Transition.FADE_IN,
scale=1.1 * 0.76,
h_attach=Text.HAttach.LEFT, h_attach=Text.HAttach.LEFT,
v_attach=Text.VAttach.TOP, v_attach=Text.VAttach.TOP,
transition=Text.Transition.FADE_IN, color=(1, 1, 1.2, 1) if vrmode else (0.8, 0.8, 1, 1),
transition_delay=delay, shadow=1.0,
color=color, flatness=1.0 if vrmode else 0.6,
position=(60 + h_offs, vpos)).autoretain() transition_delay=delay).autoretain()
hval = ts_h_offs + 50
if score_challenges: vpos -= 35
_add_t(ba.Lstr(value='${A}:', for ach in achievements:
subs=[('${A}', delay += 0.05
ba.Lstr(resource='scoreChallengesText')) ach.create_display(hval, vpos, delay, style='in_game')
]), vpos -= 55
scale=1.1) if not achievements:
delay += delay_inc Text(ba.Lstr(resource='noAchievementsRemainingText'),
vpos -= spacing
for chal in score_challenges:
_add_t(str(chal['value'] if score_type == 'points' else ba.
timestring(int(chal['value']) * 10,
timeformat=ba.TimeFormat.MILLISECONDS
).evaluate()) + ' (1 player)',
h_offs=30,
color=(0.9, 0.7, 1.0, 0.8))
delay += delay_inc
vpos -= 0.6 * spacing
_add_t(chal['player'],
h_offs=40,
color=(0.8, 1, 0.8, 0.6),
scale=0.8)
delay += delay_inc
vpos -= 1.2 * spacing
vpos -= 0.5 * spacing
if achievement_challenges:
_add_t(ba.Lstr(
value='${A}:',
subs=[('${A}',
ba.Lstr(resource='achievementChallengesText'))]),
scale=1.1)
delay += delay_inc
vpos -= spacing
for chal in achievement_challenges:
_add_t(str(chal['value']),
h_offs=30,
color=(0.9, 0.7, 1.0, 0.8))
delay += delay_inc
vpos -= 0.6 * spacing
_add_t(chal['player'],
h_offs=40,
color=(0.8, 1, 0.8, 0.6),
scale=0.8)
delay += delay_inc
vpos -= 1.2 * spacing
vpos -= 0.5 * spacing
# Now list our remaining achievements for this level.
assert self.session.campaign is not None
assert isinstance(self.session, ba.CoopSession)
levelname = (self.session.campaign.name + ':' +
self.session.campaign_level_name)
ts_h_offs = 60
if not (ba.app.demo_mode or ba.app.arcade_mode):
achievements = [
a
for a in ba.app.ach.achievements_for_coop_level(levelname)
if not a.complete
]
have_achievements = bool(achievements)
achievements = [a for a in achievements if not a.complete]
vrmode = ba.app.vr_mode
if have_achievements:
Text(ba.Lstr(resource='achievementsRemainingText'),
host_only=True, host_only=True,
position=(ts_h_offs - 10, vpos), position=(ts_h_offs + 15, vpos + 10),
transition=Text.Transition.FADE_IN, transition=Text.Transition.FADE_IN,
scale=1.1 * 0.76, scale=0.7,
h_attach=Text.HAttach.LEFT, h_attach=Text.HAttach.LEFT,
v_attach=Text.VAttach.TOP, v_attach=Text.VAttach.TOP,
color=(1, 1, 1.2, 1) if vrmode else (0.8, 0.8, 1, 1), color=(1, 1, 1, 0.5),
shadow=1.0, transition_delay=delay + 0.5).autoretain()
flatness=1.0 if vrmode else 0.6,
transition_delay=delay).autoretain()
hval = ts_h_offs + 50
vpos -= 35
for ach in achievements:
delay += 0.05
ach.create_display(hval, vpos, delay, style='in_game')
vpos -= 55
if not achievements:
Text(ba.Lstr(resource='noAchievementsRemainingText'),
host_only=True,
position=(ts_h_offs + 15, vpos + 10),
transition=Text.Transition.FADE_IN,
scale=0.7,
h_attach=Text.HAttach.LEFT,
v_attach=Text.VAttach.TOP,
color=(1, 1, 1, 0.5),
transition_delay=delay + 0.5).autoretain()

View File

@ -44,7 +44,10 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]):
name = 'Easter Egg Hunt' name = 'Easter Egg Hunt'
description = 'Gather eggs!' description = 'Gather eggs!'
available_settings = [ba.BoolSetting('Pro Mode', default=False)] available_settings = [
ba.BoolSetting('Pro Mode', default=False),
ba.BoolSetting('Epic Mode', default=False),
]
scoreconfig = ba.ScoreConfig(label='Score', scoretype=ba.ScoreType.POINTS) scoreconfig = ba.ScoreConfig(label='Score', scoretype=ba.ScoreType.POINTS)
# We're currently hard-coded for one map. # We're currently hard-coded for one map.
@ -70,6 +73,7 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]):
self.egg_tex_3 = ba.gettexture('eggTex3') self.egg_tex_3 = ba.gettexture('eggTex3')
self._collect_sound = ba.getsound('powerup01') self._collect_sound = ba.getsound('powerup01')
self._pro_mode = settings.get('Pro Mode', False) self._pro_mode = settings.get('Pro Mode', False)
self._epic_mode = settings.get('Epic Mode', False)
self._max_eggs = 1.0 self._max_eggs = 1.0
self.egg_material = ba.Material() self.egg_material = ba.Material()
self.egg_material.add_actions( self.egg_material.add_actions(
@ -81,7 +85,9 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]):
self._bots: SpazBotSet | None = None self._bots: SpazBotSet | None = None
# Base class overrides # Base class overrides
self.default_music = ba.MusicType.FORWARD_MARCH self.slow_motion = self._epic_mode
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
ba.MusicType.FORWARD_MARCH)
def on_team_join(self, team: Team) -> None: def on_team_join(self, team: Team) -> None:
if self.has_begun(): if self.has_begun():

View File

@ -335,6 +335,8 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]):
scoreconfig = ba.ScoreConfig(scoretype=ba.ScoreType.MILLISECONDS, scoreconfig = ba.ScoreConfig(scoretype=ba.ScoreType.MILLISECONDS,
version='B') version='B')
default_music = ba.MusicType.FOOTBALL
# FIXME: Need to update co-op games to use getscoreconfig. # FIXME: Need to update co-op games to use getscoreconfig.
def get_score_type(self) -> str: def get_score_type(self) -> str:
return 'time' return 'time'

View File

@ -41,7 +41,9 @@
<w>airborn</w> <w>airborn</w>
<w>alext</w> <w>alext</w>
<w>alibaba</w> <w>alibaba</w>
<w>allerrors</w>
<w>allocs</w> <w>allocs</w>
<w>allwarnings</w>
<w>alot</w> <w>alot</w>
<w>alphaimg</w> <w>alphaimg</w>
<w>alphapixels</w> <w>alphapixels</w>
@ -67,6 +69,7 @@
<w>appnameupper</w> <w>appnameupper</w>
<w>appspot</w> <w>appspot</w>
<w>appstate</w> <w>appstate</w>
<w>apptime</w>
<w>argsjoined</w> <w>argsjoined</w>
<w>argstr</w> <w>argstr</w>
<w>armcap</w> <w>armcap</w>
@ -119,6 +122,7 @@
<w>bdea</w> <w>bdea</w>
<w>benning</w> <w>benning</w>
<w>bezanson</w> <w>bezanson</w>
<w>bgdynamics</w>
<w>bgra</w> <w>bgra</w>
<w>bigendian</w> <w>bigendian</w>
<w>bilinear</w> <w>bilinear</w>
@ -226,10 +230,12 @@
<w>classdict</w> <w>classdict</w>
<w>classline</w> <w>classline</w>
<w>cleanupcheck</w> <w>cleanupcheck</w>
<w>clearsign</w>
<w>clientid</w> <w>clientid</w>
<w>clientinfo</w> <w>clientinfo</w>
<w>clienttobasn</w> <w>clienttobasn</w>
<w>clipcount</w> <w>clipcount</w>
<w>cmakelist</w>
<w>cmath</w> <w>cmath</w>
<w>cmds</w> <w>cmds</w>
<w>cmdvals</w> <w>cmdvals</w>
@ -697,6 +703,7 @@
<w>leaderboard</w> <w>leaderboard</w>
<w>leaderboards</w> <w>leaderboards</w>
<w>lenval</w> <w>lenval</w>
<w>levelno</w>
<w>lgui</w> <w>lgui</w>
<w>lhalf</w> <w>lhalf</w>
<w>libbz</w> <w>libbz</w>
@ -848,6 +855,7 @@
<w>netcode</w> <w>netcode</w>
<w>netplay</w> <w>netplay</w>
<w>nettest</w> <w>nettest</w>
<w>networkwrite</w>
<w>newactivity</w> <w>newactivity</w>
<w>newchild</w> <w>newchild</w>
<w>newimg</w> <w>newimg</w>
@ -1239,6 +1247,7 @@
<w>startpos</w> <w>startpos</w>
<w>startsplits</w> <w>startsplits</w>
<w>starttime</w> <w>starttime</w>
<w>startupmsg</w>
<w>startx</w> <w>startx</w>
<w>starty</w> <w>starty</w>
<w>statestr</w> <w>statestr</w>
@ -1258,6 +1267,7 @@
<w>strdup</w> <w>strdup</w>
<w>stringi</w> <w>stringi</w>
<w>stringified</w> <w>stringified</w>
<w>stringifying</w>
<w>strlen</w> <w>strlen</w>
<w>strs</w> <w>strs</w>
<w>strtof</w> <w>strtof</w>

View File

@ -58,6 +58,7 @@
<inspection_tool class="NotAssignable" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="NotAssignable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NotImplementedFunctions" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="NotImplementedFunctions" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NotSuperclass" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="NotSuperclass" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NullDereference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCDFA" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="OCDFA" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCLoopDoesntUseConditionVariable" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="OCLoopDoesntUseConditionVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCUnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="OCUnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />

View File

@ -210,6 +210,40 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/app/app_flavor_vr.h ${BA_SRC_ROOT}/ballistica/app/app_flavor_vr.h
${BA_SRC_ROOT}/ballistica/app/stress_test.cc ${BA_SRC_ROOT}/ballistica/app/stress_test.cc
${BA_SRC_ROOT}/ballistica/app/stress_test.h ${BA_SRC_ROOT}/ballistica/app/stress_test.h
${BA_SRC_ROOT}/ballistica/assets/assets.cc
${BA_SRC_ROOT}/ballistica/assets/assets.h
${BA_SRC_ROOT}/ballistica/assets/assets_server.cc
${BA_SRC_ROOT}/ballistica/assets/assets_server.h
${BA_SRC_ROOT}/ballistica/assets/component/asset_component.cc
${BA_SRC_ROOT}/ballistica/assets/component/asset_component.h
${BA_SRC_ROOT}/ballistica/assets/component/collide_model.cc
${BA_SRC_ROOT}/ballistica/assets/component/collide_model.h
${BA_SRC_ROOT}/ballistica/assets/component/cube_map_texture.cc
${BA_SRC_ROOT}/ballistica/assets/component/cube_map_texture.h
${BA_SRC_ROOT}/ballistica/assets/component/data.cc
${BA_SRC_ROOT}/ballistica/assets/component/data.h
${BA_SRC_ROOT}/ballistica/assets/component/model.cc
${BA_SRC_ROOT}/ballistica/assets/component/model.h
${BA_SRC_ROOT}/ballistica/assets/component/sound.cc
${BA_SRC_ROOT}/ballistica/assets/component/sound.h
${BA_SRC_ROOT}/ballistica/assets/component/texture.cc
${BA_SRC_ROOT}/ballistica/assets/component/texture.h
${BA_SRC_ROOT}/ballistica/assets/data/asset_component_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/asset_component_data.h
${BA_SRC_ROOT}/ballistica/assets/data/collide_model_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/collide_model_data.h
${BA_SRC_ROOT}/ballistica/assets/data/data_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/data_data.h
${BA_SRC_ROOT}/ballistica/assets/data/model_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/model_data.h
${BA_SRC_ROOT}/ballistica/assets/data/model_renderer_data.h
${BA_SRC_ROOT}/ballistica/assets/data/sound_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/sound_data.h
${BA_SRC_ROOT}/ballistica/assets/data/texture_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/texture_data.h
${BA_SRC_ROOT}/ballistica/assets/data/texture_preload_data.cc
${BA_SRC_ROOT}/ballistica/assets/data/texture_preload_data.h
${BA_SRC_ROOT}/ballistica/assets/data/texture_renderer_data.h
${BA_SRC_ROOT}/ballistica/audio/al_sys.cc ${BA_SRC_ROOT}/ballistica/audio/al_sys.cc
${BA_SRC_ROOT}/ballistica/audio/al_sys.h ${BA_SRC_ROOT}/ballistica/audio/al_sys.h
${BA_SRC_ROOT}/ballistica/audio/audio.cc ${BA_SRC_ROOT}/ballistica/audio/audio.cc
@ -298,43 +332,6 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/dynamics/part.h ${BA_SRC_ROOT}/ballistica/dynamics/part.h
${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.cc ${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.cc
${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.h ${BA_SRC_ROOT}/ballistica/dynamics/rigid_body.h
${BA_SRC_ROOT}/ballistica/game/account.cc
${BA_SRC_ROOT}/ballistica/game/account.h
${BA_SRC_ROOT}/ballistica/game/client_controller_interface.h
${BA_SRC_ROOT}/ballistica/game/connection/connection.cc
${BA_SRC_ROOT}/ballistica/game/connection/connection.h
${BA_SRC_ROOT}/ballistica/game/connection/connection_set.cc
${BA_SRC_ROOT}/ballistica/game/connection/connection_set.h
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client.cc
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client.h
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client_udp.cc
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_client_udp.h
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_host.cc
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_host.h
${BA_SRC_ROOT}/ballistica/game/connection/connection_to_host_udp.cc
${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.cc
${BA_SRC_ROOT}/ballistica/game/game.h
${BA_SRC_ROOT}/ballistica/game/game_stream.cc
${BA_SRC_ROOT}/ballistica/game/game_stream.h
${BA_SRC_ROOT}/ballistica/game/host_activity.cc
${BA_SRC_ROOT}/ballistica/game/host_activity.h
${BA_SRC_ROOT}/ballistica/game/player.cc
${BA_SRC_ROOT}/ballistica/game/player.h
${BA_SRC_ROOT}/ballistica/game/player_spec.cc
${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.cc
${BA_SRC_ROOT}/ballistica/game/session/client_session.h
${BA_SRC_ROOT}/ballistica/game/session/host_session.cc
${BA_SRC_ROOT}/ballistica/game/session/host_session.h
${BA_SRC_ROOT}/ballistica/game/session/net_client_session.cc
${BA_SRC_ROOT}/ballistica/game/session/net_client_session.h
${BA_SRC_ROOT}/ballistica/game/session/replay_client_session.cc
${BA_SRC_ROOT}/ballistica/game/session/replay_client_session.h
${BA_SRC_ROOT}/ballistica/game/session/session.cc
${BA_SRC_ROOT}/ballistica/game/session/session.h
${BA_SRC_ROOT}/ballistica/generic/base64.cc ${BA_SRC_ROOT}/ballistica/generic/base64.cc
${BA_SRC_ROOT}/ballistica/generic/base64.h ${BA_SRC_ROOT}/ballistica/generic/base64.h
${BA_SRC_ROOT}/ballistica/generic/buffer.h ${BA_SRC_ROOT}/ballistica/generic/buffer.h
@ -453,9 +450,41 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/input/input.h ${BA_SRC_ROOT}/ballistica/input/input.h
${BA_SRC_ROOT}/ballistica/input/remote_app.cc ${BA_SRC_ROOT}/ballistica/input/remote_app.cc
${BA_SRC_ROOT}/ballistica/input/remote_app.h ${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/internal/app_internal.h ${BA_SRC_ROOT}/ballistica/internal/app_internal.h
${BA_SRC_ROOT}/ballistica/logic/client_controller_interface.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection_set.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection_set.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_client.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_client.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_client_udp.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_client_udp.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_host.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_host.h
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_host_udp.cc
${BA_SRC_ROOT}/ballistica/logic/connection/connection_to_host_udp.h
${BA_SRC_ROOT}/ballistica/logic/friend_score_set.h
${BA_SRC_ROOT}/ballistica/logic/host_activity.cc
${BA_SRC_ROOT}/ballistica/logic/host_activity.h
${BA_SRC_ROOT}/ballistica/logic/logic.cc
${BA_SRC_ROOT}/ballistica/logic/logic.h
${BA_SRC_ROOT}/ballistica/logic/player.cc
${BA_SRC_ROOT}/ballistica/logic/player.h
${BA_SRC_ROOT}/ballistica/logic/player_spec.cc
${BA_SRC_ROOT}/ballistica/logic/player_spec.h
${BA_SRC_ROOT}/ballistica/logic/session/client_session.cc
${BA_SRC_ROOT}/ballistica/logic/session/client_session.h
${BA_SRC_ROOT}/ballistica/logic/session/host_session.cc
${BA_SRC_ROOT}/ballistica/logic/session/host_session.h
${BA_SRC_ROOT}/ballistica/logic/session/net_client_session.cc
${BA_SRC_ROOT}/ballistica/logic/session/net_client_session.h
${BA_SRC_ROOT}/ballistica/logic/session/replay_client_session.cc
${BA_SRC_ROOT}/ballistica/logic/session/replay_client_session.h
${BA_SRC_ROOT}/ballistica/logic/session/session.cc
${BA_SRC_ROOT}/ballistica/logic/session/session.h
${BA_SRC_ROOT}/ballistica/logic/v1_account.cc
${BA_SRC_ROOT}/ballistica/logic/v1_account.h
${BA_SRC_ROOT}/ballistica/math/matrix44f.cc ${BA_SRC_ROOT}/ballistica/math/matrix44f.cc
${BA_SRC_ROOT}/ballistica/math/matrix44f.h ${BA_SRC_ROOT}/ballistica/math/matrix44f.h
${BA_SRC_ROOT}/ballistica/math/point2d.h ${BA_SRC_ROOT}/ballistica/math/point2d.h
@ -466,44 +495,10 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/math/vector3f.cc ${BA_SRC_ROOT}/ballistica/math/vector3f.cc
${BA_SRC_ROOT}/ballistica/math/vector3f.h ${BA_SRC_ROOT}/ballistica/math/vector3f.h
${BA_SRC_ROOT}/ballistica/math/vector4f.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.cc ${BA_SRC_ROOT}/ballistica/networking/network_reader.cc
${BA_SRC_ROOT}/ballistica/networking/network_reader.h ${BA_SRC_ROOT}/ballistica/networking/network_reader.h
${BA_SRC_ROOT}/ballistica/networking/network_write_module.cc ${BA_SRC_ROOT}/ballistica/networking/network_writer.cc
${BA_SRC_ROOT}/ballistica/networking/network_write_module.h ${BA_SRC_ROOT}/ballistica/networking/network_writer.h
${BA_SRC_ROOT}/ballistica/networking/networking.cc ${BA_SRC_ROOT}/ballistica/networking/networking.cc
${BA_SRC_ROOT}/ballistica/networking/networking.h ${BA_SRC_ROOT}/ballistica/networking/networking.h
${BA_SRC_ROOT}/ballistica/networking/networking_sys.h ${BA_SRC_ROOT}/ballistica/networking/networking_sys.h
@ -519,6 +514,8 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/platform/platform.h ${BA_SRC_ROOT}/ballistica/platform/platform.h
${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.cc ${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.cc
${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.h ${BA_SRC_ROOT}/ballistica/platform/sdl/sdl_app.h
${BA_SRC_ROOT}/ballistica/platform/stdio_console.cc
${BA_SRC_ROOT}/ballistica/platform/stdio_console.h
${BA_SRC_ROOT}/ballistica/platform/windows/platform_windows.cc ${BA_SRC_ROOT}/ballistica/platform/windows/platform_windows.cc
${BA_SRC_ROOT}/ballistica/platform/windows/platform_windows.h ${BA_SRC_ROOT}/ballistica/platform/windows/platform_windows.h
${BA_SRC_ROOT}/ballistica/python/class/python_class.cc ${BA_SRC_ROOT}/ballistica/python/class/python_class.cc
@ -557,14 +554,14 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/python/class/python_class_widget.h ${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.cc
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_app.h ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_app.h
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_assets.cc
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_assets.h
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_gameplay.cc ${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_gameplay.h
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_graphics.cc ${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_graphics.h
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_input.cc ${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_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_networking.cc ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_networking.cc
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_networking.h ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_networking.h
${BA_SRC_ROOT}/ballistica/python/methods/python_methods_system.cc ${BA_SRC_ROOT}/ballistica/python/methods/python_methods_system.cc
@ -638,6 +635,10 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/scene/node/time_display_node.h ${BA_SRC_ROOT}/ballistica/scene/node/time_display_node.h
${BA_SRC_ROOT}/ballistica/scene/scene.cc ${BA_SRC_ROOT}/ballistica/scene/scene.cc
${BA_SRC_ROOT}/ballistica/scene/scene.h ${BA_SRC_ROOT}/ballistica/scene/scene.h
${BA_SRC_ROOT}/ballistica/scene/scene_stream.cc
${BA_SRC_ROOT}/ballistica/scene/scene_stream.h
${BA_SRC_ROOT}/ballistica/scene/v1/scene_v1.cc
${BA_SRC_ROOT}/ballistica/scene/v1/scene_v1.h
${BA_SRC_ROOT}/ballistica/ui/console.cc ${BA_SRC_ROOT}/ballistica/ui/console.cc
${BA_SRC_ROOT}/ballistica/ui/console.h ${BA_SRC_ROOT}/ballistica/ui/console.h
${BA_SRC_ROOT}/ballistica/ui/root_ui.cc ${BA_SRC_ROOT}/ballistica/ui/root_ui.cc

View File

@ -201,6 +201,40 @@
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" /> <ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" />
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc" /> <ClCompile Include="..\..\src\ballistica\app\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\app\stress_test.h" /> <ClInclude Include="..\..\src\ballistica\app\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\assets\assets.cc" />
<ClInclude Include="..\..\src\ballistica\assets\assets.h" />
<ClCompile Include="..\..\src\ballistica\assets\assets_server.cc" />
<ClInclude Include="..\..\src\ballistica\assets\assets_server.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\asset_component.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\asset_component.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\collide_model.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\collide_model.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\cube_map_texture.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\cube_map_texture.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\data.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\model.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\model.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\sound.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\sound.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\texture.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\texture.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\asset_component_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\asset_component_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\collide_model_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\collide_model_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\data_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\data_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\model_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\model_data.h" />
<ClInclude Include="..\..\src\ballistica\assets\data\model_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\sound_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\sound_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\texture_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\texture_preload_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_preload_data.h" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" /> <ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" />
<ClInclude Include="..\..\src\ballistica\audio\al_sys.h" /> <ClInclude Include="..\..\src\ballistica\audio\al_sys.h" />
<ClCompile Include="..\..\src\ballistica\audio\audio.cc" /> <ClCompile Include="..\..\src\ballistica\audio\audio.cc" />
@ -289,43 +323,6 @@
<ClInclude Include="..\..\src\ballistica\dynamics\part.h" /> <ClInclude Include="..\..\src\ballistica\dynamics\part.h" />
<ClCompile Include="..\..\src\ballistica\dynamics\rigid_body.cc" /> <ClCompile Include="..\..\src\ballistica\dynamics\rigid_body.cc" />
<ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h" /> <ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h" />
<ClCompile Include="..\..\src\ballistica\game\account.cc" />
<ClInclude Include="..\..\src\ballistica\game\account.h" />
<ClInclude Include="..\..\src\ballistica\game\client_controller_interface.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_set.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_set.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client_udp.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client_udp.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host_udp.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host_udp.h" />
<ClInclude Include="..\..\src\ballistica\game\friend_score_set.h" />
<ClCompile Include="..\..\src\ballistica\game\game.cc" />
<ClInclude Include="..\..\src\ballistica\game\game.h" />
<ClCompile Include="..\..\src\ballistica\game\game_stream.cc" />
<ClInclude Include="..\..\src\ballistica\game\game_stream.h" />
<ClCompile Include="..\..\src\ballistica\game\host_activity.cc" />
<ClInclude Include="..\..\src\ballistica\game\host_activity.h" />
<ClCompile Include="..\..\src\ballistica\game\player.cc" />
<ClInclude Include="..\..\src\ballistica\game\player.h" />
<ClCompile Include="..\..\src\ballistica\game\player_spec.cc" />
<ClInclude Include="..\..\src\ballistica\game\player_spec.h" />
<ClInclude Include="..\..\src\ballistica\game\score_to_beat.h" />
<ClCompile Include="..\..\src\ballistica\game\session\client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\host_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\host_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\net_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\net_client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\replay_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\replay_client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\session.h" />
<ClCompile Include="..\..\src\ballistica\generic\base64.cc" /> <ClCompile Include="..\..\src\ballistica\generic\base64.cc" />
<ClInclude Include="..\..\src\ballistica\generic\base64.h" /> <ClInclude Include="..\..\src\ballistica\generic\base64.h" />
<ClInclude Include="..\..\src\ballistica\generic\buffer.h" /> <ClInclude Include="..\..\src\ballistica\generic\buffer.h" />
@ -444,9 +441,41 @@
<ClInclude Include="..\..\src\ballistica\input\input.h" /> <ClInclude Include="..\..\src\ballistica\input\input.h" />
<ClCompile Include="..\..\src\ballistica\input\remote_app.cc" /> <ClCompile Include="..\..\src\ballistica\input\remote_app.cc" />
<ClInclude Include="..\..\src\ballistica\input\remote_app.h" /> <ClInclude Include="..\..\src\ballistica\input\remote_app.h" />
<ClCompile Include="..\..\src\ballistica\input\std_input_module.cc" />
<ClInclude Include="..\..\src\ballistica\input\std_input_module.h" />
<ClInclude Include="..\..\src\ballistica\internal\app_internal.h" /> <ClInclude Include="..\..\src\ballistica\internal\app_internal.h" />
<ClInclude Include="..\..\src\ballistica\logic\client_controller_interface.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_set.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_set.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.h" />
<ClInclude Include="..\..\src\ballistica\logic\friend_score_set.h" />
<ClCompile Include="..\..\src\ballistica\logic\host_activity.cc" />
<ClInclude Include="..\..\src\ballistica\logic\host_activity.h" />
<ClCompile Include="..\..\src\ballistica\logic\logic.cc" />
<ClInclude Include="..\..\src\ballistica\logic\logic.h" />
<ClCompile Include="..\..\src\ballistica\logic\player.cc" />
<ClInclude Include="..\..\src\ballistica\logic\player.h" />
<ClCompile Include="..\..\src\ballistica\logic\player_spec.cc" />
<ClInclude Include="..\..\src\ballistica\logic\player_spec.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\host_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\host_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\net_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\net_client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\replay_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\replay_client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\session.h" />
<ClCompile Include="..\..\src\ballistica\logic\v1_account.cc" />
<ClInclude Include="..\..\src\ballistica\logic\v1_account.h" />
<ClCompile Include="..\..\src\ballistica\math\matrix44f.cc" /> <ClCompile Include="..\..\src\ballistica\math\matrix44f.cc" />
<ClInclude Include="..\..\src\ballistica\math\matrix44f.h" /> <ClInclude Include="..\..\src\ballistica\math\matrix44f.h" />
<ClInclude Include="..\..\src\ballistica\math\point2d.h" /> <ClInclude Include="..\..\src\ballistica\math\point2d.h" />
@ -457,44 +486,10 @@
<ClCompile Include="..\..\src\ballistica\math\vector3f.cc" /> <ClCompile Include="..\..\src\ballistica\math\vector3f.cc" />
<ClInclude Include="..\..\src\ballistica\math\vector3f.h" /> <ClInclude Include="..\..\src\ballistica\math\vector3f.h" />
<ClInclude Include="..\..\src\ballistica\math\vector4f.h" /> <ClInclude Include="..\..\src\ballistica\math\vector4f.h" />
<ClCompile Include="..\..\src\ballistica\media\component\collide_model.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\collide_model.h" />
<ClCompile Include="..\..\src\ballistica\media\component\cube_map_texture.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\cube_map_texture.h" />
<ClCompile Include="..\..\src\ballistica\media\component\data.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\data.h" />
<ClCompile Include="..\..\src\ballistica\media\component\media_component.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\media_component.h" />
<ClCompile Include="..\..\src\ballistica\media\component\model.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\model.h" />
<ClCompile Include="..\..\src\ballistica\media\component\sound.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\sound.h" />
<ClCompile Include="..\..\src\ballistica\media\component\texture.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\texture.h" />
<ClCompile Include="..\..\src\ballistica\media\data\collide_model_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\collide_model_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\data_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\data_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\media_component_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\media_component_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\model_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\model_data.h" />
<ClInclude Include="..\..\src\ballistica\media\data\model_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\sound_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\sound_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\texture_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\texture_preload_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_preload_data.h" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\media\media.cc" />
<ClInclude Include="..\..\src\ballistica\media\media.h" />
<ClCompile Include="..\..\src\ballistica\media\media_server.cc" />
<ClInclude Include="..\..\src\ballistica\media\media_server.h" />
<ClCompile Include="..\..\src\ballistica\networking\network_reader.cc" /> <ClCompile Include="..\..\src\ballistica\networking\network_reader.cc" />
<ClInclude Include="..\..\src\ballistica\networking\network_reader.h" /> <ClInclude Include="..\..\src\ballistica\networking\network_reader.h" />
<ClCompile Include="..\..\src\ballistica\networking\network_write_module.cc" /> <ClCompile Include="..\..\src\ballistica\networking\network_writer.cc" />
<ClInclude Include="..\..\src\ballistica\networking\network_write_module.h" /> <ClInclude Include="..\..\src\ballistica\networking\network_writer.h" />
<ClCompile Include="..\..\src\ballistica\networking\networking.cc" /> <ClCompile Include="..\..\src\ballistica\networking\networking.cc" />
<ClInclude Include="..\..\src\ballistica\networking\networking.h" /> <ClInclude Include="..\..\src\ballistica\networking\networking.h" />
<ClInclude Include="..\..\src\ballistica\networking\networking_sys.h" /> <ClInclude Include="..\..\src\ballistica\networking\networking_sys.h" />
@ -510,6 +505,8 @@
<ClInclude Include="..\..\src\ballistica\platform\platform.h" /> <ClInclude Include="..\..\src\ballistica\platform\platform.h" />
<ClCompile Include="..\..\src\ballistica\platform\sdl\sdl_app.cc" /> <ClCompile Include="..\..\src\ballistica\platform\sdl\sdl_app.cc" />
<ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h" /> <ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h" />
<ClCompile Include="..\..\src\ballistica\platform\stdio_console.cc" />
<ClInclude Include="..\..\src\ballistica\platform\stdio_console.h" />
<ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc" /> <ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc" />
<ClInclude Include="..\..\src\ballistica\platform\windows\platform_windows.h" /> <ClInclude Include="..\..\src\ballistica\platform\windows\platform_windows.h" />
<ClCompile Include="..\..\src\ballistica\python\class\python_class.cc" /> <ClCompile Include="..\..\src\ballistica\python\class\python_class.cc" />
@ -548,14 +545,14 @@
<ClInclude Include="..\..\src\ballistica\python\class\python_class_widget.h" /> <ClInclude Include="..\..\src\ballistica\python\class\python_class_widget.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_app.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_app.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_assets.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_assets.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_gameplay.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_gameplay.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_graphics.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_graphics.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_graphics.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_graphics.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_input.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_input.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_media.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_media.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_networking.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_networking.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_system.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_system.cc" />
@ -629,6 +626,10 @@
<ClInclude Include="..\..\src\ballistica\scene\node\time_display_node.h" /> <ClInclude Include="..\..\src\ballistica\scene\node\time_display_node.h" />
<ClCompile Include="..\..\src\ballistica\scene\scene.cc" /> <ClCompile Include="..\..\src\ballistica\scene\scene.cc" />
<ClInclude Include="..\..\src\ballistica\scene\scene.h" /> <ClInclude Include="..\..\src\ballistica\scene\scene.h" />
<ClCompile Include="..\..\src\ballistica\scene\scene_stream.cc" />
<ClInclude Include="..\..\src\ballistica\scene\scene_stream.h" />
<ClCompile Include="..\..\src\ballistica\scene\v1\scene_v1.cc" />
<ClInclude Include="..\..\src\ballistica\scene\v1\scene_v1.h" />
<ClCompile Include="..\..\src\ballistica\ui\console.cc" /> <ClCompile Include="..\..\src\ballistica\ui\console.cc" />
<ClInclude Include="..\..\src\ballistica\ui\console.h" /> <ClInclude Include="..\..\src\ballistica\ui\console.h" />
<ClCompile Include="..\..\src\ballistica\ui\root_ui.cc" /> <ClCompile Include="..\..\src\ballistica\ui\root_ui.cc" />

View File

@ -37,6 +37,108 @@
<ClInclude Include="..\..\src\ballistica\app\stress_test.h"> <ClInclude Include="..\..\src\ballistica\app\stress_test.h">
<Filter>ballistica\app</Filter> <Filter>ballistica\app</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\assets.cc">
<Filter>ballistica\assets</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\assets.h">
<Filter>ballistica\assets</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\assets_server.cc">
<Filter>ballistica\assets</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\assets_server.h">
<Filter>ballistica\assets</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\asset_component.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\asset_component.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\collide_model.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\collide_model.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\cube_map_texture.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\cube_map_texture.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\data.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\data.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\model.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\model.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\sound.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\sound.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\texture.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\texture.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\asset_component_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\asset_component_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\collide_model_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\collide_model_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\data_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\data_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\model_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\model_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\assets\data\model_renderer_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\sound_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\sound_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\texture_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\texture_preload_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_preload_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_renderer_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc"> <ClCompile Include="..\..\src\ballistica\audio\al_sys.cc">
<Filter>ballistica\audio</Filter> <Filter>ballistica\audio</Filter>
</ClCompile> </ClCompile>
@ -301,117 +403,6 @@
<ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h"> <ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h">
<Filter>ballistica\dynamics</Filter> <Filter>ballistica\dynamics</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\game\account.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\account.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\client_controller_interface.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_set.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_set.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client_udp.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client_udp.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host_udp.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host_udp.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\friend_score_set.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\game.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\game.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\game_stream.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\game_stream.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\host_activity.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\host_activity.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\player.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\player.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\player_spec.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\player_spec.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\score_to_beat.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\host_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\host_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\net_client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\net_client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\replay_client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\replay_client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\generic\base64.cc"> <ClCompile Include="..\..\src\ballistica\generic\base64.cc">
<Filter>ballistica\generic</Filter> <Filter>ballistica\generic</Filter>
</ClCompile> </ClCompile>
@ -766,15 +757,111 @@
<ClInclude Include="..\..\src\ballistica\input\remote_app.h"> <ClInclude Include="..\..\src\ballistica\input\remote_app.h">
<Filter>ballistica\input</Filter> <Filter>ballistica\input</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\input\std_input_module.cc">
<Filter>ballistica\input</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\input\std_input_module.h">
<Filter>ballistica\input</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\internal\app_internal.h"> <ClInclude Include="..\..\src\ballistica\internal\app_internal.h">
<Filter>ballistica\internal</Filter> <Filter>ballistica\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ballistica\logic\client_controller_interface.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_set.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_set.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\logic\friend_score_set.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\host_activity.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\host_activity.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\logic.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\logic.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\player.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\player.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\player_spec.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\player_spec.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\host_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\host_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\net_client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\net_client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\replay_client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\replay_client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\v1_account.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\v1_account.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\math\matrix44f.cc"> <ClCompile Include="..\..\src\ballistica\math\matrix44f.cc">
<Filter>ballistica\math</Filter> <Filter>ballistica\math</Filter>
</ClCompile> </ClCompile>
@ -805,118 +892,16 @@
<ClInclude Include="..\..\src\ballistica\math\vector4f.h"> <ClInclude Include="..\..\src\ballistica\math\vector4f.h">
<Filter>ballistica\math</Filter> <Filter>ballistica\math</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\collide_model.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\collide_model.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\cube_map_texture.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\cube_map_texture.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\data.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\data.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\media_component.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\media_component.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\model.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\model.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\sound.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\sound.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\texture.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\texture.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\collide_model_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\collide_model_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\data_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\data_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\media_component_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\media_component_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\model_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\model_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\media\data\model_renderer_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\sound_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\sound_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\texture_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\texture_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\texture_preload_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\texture_preload_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\media\data\texture_renderer_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\media.cc">
<Filter>ballistica\media</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\media.h">
<Filter>ballistica\media</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\media_server.cc">
<Filter>ballistica\media</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\media_server.h">
<Filter>ballistica\media</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\network_reader.cc"> <ClCompile Include="..\..\src\ballistica\networking\network_reader.cc">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ballistica\networking\network_reader.h"> <ClInclude Include="..\..\src\ballistica\networking\network_reader.h">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\network_write_module.cc"> <ClCompile Include="..\..\src\ballistica\networking\network_writer.cc">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ballistica\networking\network_write_module.h"> <ClInclude Include="..\..\src\ballistica\networking\network_writer.h">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\networking.cc"> <ClCompile Include="..\..\src\ballistica\networking\networking.cc">
@ -964,6 +949,12 @@
<ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h"> <ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h">
<Filter>ballistica\platform\sdl</Filter> <Filter>ballistica\platform\sdl</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\platform\stdio_console.cc">
<Filter>ballistica\platform</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\platform\stdio_console.h">
<Filter>ballistica\platform</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc"> <ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc">
<Filter>ballistica\platform\windows</Filter> <Filter>ballistica\platform\windows</Filter>
</ClCompile> </ClCompile>
@ -1078,6 +1069,12 @@
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h"> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_assets.cc">
<Filter>ballistica\python\methods</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_assets.h">
<Filter>ballistica\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc"> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClCompile> </ClCompile>
@ -1096,12 +1093,6 @@
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h"> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_media.cc">
<Filter>ballistica\python\methods</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_media.h">
<Filter>ballistica\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc"> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClCompile> </ClCompile>
@ -1321,6 +1312,18 @@
<ClInclude Include="..\..\src\ballistica\scene\scene.h"> <ClInclude Include="..\..\src\ballistica\scene\scene.h">
<Filter>ballistica\scene</Filter> <Filter>ballistica\scene</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\scene\scene_stream.cc">
<Filter>ballistica\scene</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\scene\scene_stream.h">
<Filter>ballistica\scene</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\scene\v1\scene_v1.cc">
<Filter>ballistica\scene\v1</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\scene\v1\scene_v1.h">
<Filter>ballistica\scene\v1</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\ui\console.cc"> <ClCompile Include="..\..\src\ballistica\ui\console.cc">
<Filter>ballistica\ui</Filter> <Filter>ballistica\ui</Filter>
</ClCompile> </ClCompile>
@ -1646,15 +1649,15 @@
<ItemGroup> <ItemGroup>
<Filter Include="ballistica" /> <Filter Include="ballistica" />
<Filter Include="ballistica\app" /> <Filter Include="ballistica\app" />
<Filter Include="ballistica\assets" />
<Filter Include="ballistica\assets\component" />
<Filter Include="ballistica\assets\data" />
<Filter Include="ballistica\audio" /> <Filter Include="ballistica\audio" />
<Filter Include="ballistica\config" /> <Filter Include="ballistica\config" />
<Filter Include="ballistica\core" /> <Filter Include="ballistica\core" />
<Filter Include="ballistica\dynamics" /> <Filter Include="ballistica\dynamics" />
<Filter Include="ballistica\dynamics\bg" /> <Filter Include="ballistica\dynamics\bg" />
<Filter Include="ballistica\dynamics\material" /> <Filter Include="ballistica\dynamics\material" />
<Filter Include="ballistica\game" />
<Filter Include="ballistica\game\connection" />
<Filter Include="ballistica\game\session" />
<Filter Include="ballistica\generic" /> <Filter Include="ballistica\generic" />
<Filter Include="ballistica\graphics" /> <Filter Include="ballistica\graphics" />
<Filter Include="ballistica\graphics\component" /> <Filter Include="ballistica\graphics\component" />
@ -1665,10 +1668,10 @@
<Filter Include="ballistica\input" /> <Filter Include="ballistica\input" />
<Filter Include="ballistica\input\device" /> <Filter Include="ballistica\input\device" />
<Filter Include="ballistica\internal" /> <Filter Include="ballistica\internal" />
<Filter Include="ballistica\logic" />
<Filter Include="ballistica\logic\connection" />
<Filter Include="ballistica\logic\session" />
<Filter Include="ballistica\math" /> <Filter Include="ballistica\math" />
<Filter Include="ballistica\media" />
<Filter Include="ballistica\media\component" />
<Filter Include="ballistica\media\data" />
<Filter Include="ballistica\networking" /> <Filter Include="ballistica\networking" />
<Filter Include="ballistica\platform" /> <Filter Include="ballistica\platform" />
<Filter Include="ballistica\platform\apple" /> <Filter Include="ballistica\platform\apple" />
@ -1680,6 +1683,7 @@
<Filter Include="ballistica\python\methods" /> <Filter Include="ballistica\python\methods" />
<Filter Include="ballistica\scene" /> <Filter Include="ballistica\scene" />
<Filter Include="ballistica\scene\node" /> <Filter Include="ballistica\scene\node" />
<Filter Include="ballistica\scene\v1" />
<Filter Include="ballistica\ui" /> <Filter Include="ballistica\ui" />
<Filter Include="ballistica\ui\widget" /> <Filter Include="ballistica\ui\widget" />
<Filter Include="external" /> <Filter Include="external" />

View File

@ -196,6 +196,40 @@
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" /> <ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" />
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc" /> <ClCompile Include="..\..\src\ballistica\app\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\app\stress_test.h" /> <ClInclude Include="..\..\src\ballistica\app\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\assets\assets.cc" />
<ClInclude Include="..\..\src\ballistica\assets\assets.h" />
<ClCompile Include="..\..\src\ballistica\assets\assets_server.cc" />
<ClInclude Include="..\..\src\ballistica\assets\assets_server.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\asset_component.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\asset_component.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\collide_model.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\collide_model.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\cube_map_texture.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\cube_map_texture.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\data.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\model.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\model.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\sound.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\sound.h" />
<ClCompile Include="..\..\src\ballistica\assets\component\texture.cc" />
<ClInclude Include="..\..\src\ballistica\assets\component\texture.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\asset_component_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\asset_component_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\collide_model_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\collide_model_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\data_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\data_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\model_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\model_data.h" />
<ClInclude Include="..\..\src\ballistica\assets\data\model_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\sound_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\sound_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\texture_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_data.h" />
<ClCompile Include="..\..\src\ballistica\assets\data\texture_preload_data.cc" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_preload_data.h" />
<ClInclude Include="..\..\src\ballistica\assets\data\texture_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" /> <ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" />
<ClInclude Include="..\..\src\ballistica\audio\al_sys.h" /> <ClInclude Include="..\..\src\ballistica\audio\al_sys.h" />
<ClCompile Include="..\..\src\ballistica\audio\audio.cc" /> <ClCompile Include="..\..\src\ballistica\audio\audio.cc" />
@ -284,43 +318,6 @@
<ClInclude Include="..\..\src\ballistica\dynamics\part.h" /> <ClInclude Include="..\..\src\ballistica\dynamics\part.h" />
<ClCompile Include="..\..\src\ballistica\dynamics\rigid_body.cc" /> <ClCompile Include="..\..\src\ballistica\dynamics\rigid_body.cc" />
<ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h" /> <ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h" />
<ClCompile Include="..\..\src\ballistica\game\account.cc" />
<ClInclude Include="..\..\src\ballistica\game\account.h" />
<ClInclude Include="..\..\src\ballistica\game\client_controller_interface.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_set.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_set.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client_udp.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client_udp.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host.h" />
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host_udp.cc" />
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host_udp.h" />
<ClInclude Include="..\..\src\ballistica\game\friend_score_set.h" />
<ClCompile Include="..\..\src\ballistica\game\game.cc" />
<ClInclude Include="..\..\src\ballistica\game\game.h" />
<ClCompile Include="..\..\src\ballistica\game\game_stream.cc" />
<ClInclude Include="..\..\src\ballistica\game\game_stream.h" />
<ClCompile Include="..\..\src\ballistica\game\host_activity.cc" />
<ClInclude Include="..\..\src\ballistica\game\host_activity.h" />
<ClCompile Include="..\..\src\ballistica\game\player.cc" />
<ClInclude Include="..\..\src\ballistica\game\player.h" />
<ClCompile Include="..\..\src\ballistica\game\player_spec.cc" />
<ClInclude Include="..\..\src\ballistica\game\player_spec.h" />
<ClInclude Include="..\..\src\ballistica\game\score_to_beat.h" />
<ClCompile Include="..\..\src\ballistica\game\session\client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\host_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\host_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\net_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\net_client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\replay_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\replay_client_session.h" />
<ClCompile Include="..\..\src\ballistica\game\session\session.cc" />
<ClInclude Include="..\..\src\ballistica\game\session\session.h" />
<ClCompile Include="..\..\src\ballistica\generic\base64.cc" /> <ClCompile Include="..\..\src\ballistica\generic\base64.cc" />
<ClInclude Include="..\..\src\ballistica\generic\base64.h" /> <ClInclude Include="..\..\src\ballistica\generic\base64.h" />
<ClInclude Include="..\..\src\ballistica\generic\buffer.h" /> <ClInclude Include="..\..\src\ballistica\generic\buffer.h" />
@ -439,9 +436,41 @@
<ClInclude Include="..\..\src\ballistica\input\input.h" /> <ClInclude Include="..\..\src\ballistica\input\input.h" />
<ClCompile Include="..\..\src\ballistica\input\remote_app.cc" /> <ClCompile Include="..\..\src\ballistica\input\remote_app.cc" />
<ClInclude Include="..\..\src\ballistica\input\remote_app.h" /> <ClInclude Include="..\..\src\ballistica\input\remote_app.h" />
<ClCompile Include="..\..\src\ballistica\input\std_input_module.cc" />
<ClInclude Include="..\..\src\ballistica\input\std_input_module.h" />
<ClInclude Include="..\..\src\ballistica\internal\app_internal.h" /> <ClInclude Include="..\..\src\ballistica\internal\app_internal.h" />
<ClInclude Include="..\..\src\ballistica\logic\client_controller_interface.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_set.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_set.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host.h" />
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.cc" />
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.h" />
<ClInclude Include="..\..\src\ballistica\logic\friend_score_set.h" />
<ClCompile Include="..\..\src\ballistica\logic\host_activity.cc" />
<ClInclude Include="..\..\src\ballistica\logic\host_activity.h" />
<ClCompile Include="..\..\src\ballistica\logic\logic.cc" />
<ClInclude Include="..\..\src\ballistica\logic\logic.h" />
<ClCompile Include="..\..\src\ballistica\logic\player.cc" />
<ClInclude Include="..\..\src\ballistica\logic\player.h" />
<ClCompile Include="..\..\src\ballistica\logic\player_spec.cc" />
<ClInclude Include="..\..\src\ballistica\logic\player_spec.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\host_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\host_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\net_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\net_client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\replay_client_session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\replay_client_session.h" />
<ClCompile Include="..\..\src\ballistica\logic\session\session.cc" />
<ClInclude Include="..\..\src\ballistica\logic\session\session.h" />
<ClCompile Include="..\..\src\ballistica\logic\v1_account.cc" />
<ClInclude Include="..\..\src\ballistica\logic\v1_account.h" />
<ClCompile Include="..\..\src\ballistica\math\matrix44f.cc" /> <ClCompile Include="..\..\src\ballistica\math\matrix44f.cc" />
<ClInclude Include="..\..\src\ballistica\math\matrix44f.h" /> <ClInclude Include="..\..\src\ballistica\math\matrix44f.h" />
<ClInclude Include="..\..\src\ballistica\math\point2d.h" /> <ClInclude Include="..\..\src\ballistica\math\point2d.h" />
@ -452,44 +481,10 @@
<ClCompile Include="..\..\src\ballistica\math\vector3f.cc" /> <ClCompile Include="..\..\src\ballistica\math\vector3f.cc" />
<ClInclude Include="..\..\src\ballistica\math\vector3f.h" /> <ClInclude Include="..\..\src\ballistica\math\vector3f.h" />
<ClInclude Include="..\..\src\ballistica\math\vector4f.h" /> <ClInclude Include="..\..\src\ballistica\math\vector4f.h" />
<ClCompile Include="..\..\src\ballistica\media\component\collide_model.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\collide_model.h" />
<ClCompile Include="..\..\src\ballistica\media\component\cube_map_texture.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\cube_map_texture.h" />
<ClCompile Include="..\..\src\ballistica\media\component\data.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\data.h" />
<ClCompile Include="..\..\src\ballistica\media\component\media_component.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\media_component.h" />
<ClCompile Include="..\..\src\ballistica\media\component\model.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\model.h" />
<ClCompile Include="..\..\src\ballistica\media\component\sound.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\sound.h" />
<ClCompile Include="..\..\src\ballistica\media\component\texture.cc" />
<ClInclude Include="..\..\src\ballistica\media\component\texture.h" />
<ClCompile Include="..\..\src\ballistica\media\data\collide_model_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\collide_model_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\data_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\data_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\media_component_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\media_component_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\model_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\model_data.h" />
<ClInclude Include="..\..\src\ballistica\media\data\model_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\sound_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\sound_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\texture_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_data.h" />
<ClCompile Include="..\..\src\ballistica\media\data\texture_preload_data.cc" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_preload_data.h" />
<ClInclude Include="..\..\src\ballistica\media\data\texture_renderer_data.h" />
<ClCompile Include="..\..\src\ballistica\media\media.cc" />
<ClInclude Include="..\..\src\ballistica\media\media.h" />
<ClCompile Include="..\..\src\ballistica\media\media_server.cc" />
<ClInclude Include="..\..\src\ballistica\media\media_server.h" />
<ClCompile Include="..\..\src\ballistica\networking\network_reader.cc" /> <ClCompile Include="..\..\src\ballistica\networking\network_reader.cc" />
<ClInclude Include="..\..\src\ballistica\networking\network_reader.h" /> <ClInclude Include="..\..\src\ballistica\networking\network_reader.h" />
<ClCompile Include="..\..\src\ballistica\networking\network_write_module.cc" /> <ClCompile Include="..\..\src\ballistica\networking\network_writer.cc" />
<ClInclude Include="..\..\src\ballistica\networking\network_write_module.h" /> <ClInclude Include="..\..\src\ballistica\networking\network_writer.h" />
<ClCompile Include="..\..\src\ballistica\networking\networking.cc" /> <ClCompile Include="..\..\src\ballistica\networking\networking.cc" />
<ClInclude Include="..\..\src\ballistica\networking\networking.h" /> <ClInclude Include="..\..\src\ballistica\networking\networking.h" />
<ClInclude Include="..\..\src\ballistica\networking\networking_sys.h" /> <ClInclude Include="..\..\src\ballistica\networking\networking_sys.h" />
@ -505,6 +500,8 @@
<ClInclude Include="..\..\src\ballistica\platform\platform.h" /> <ClInclude Include="..\..\src\ballistica\platform\platform.h" />
<ClCompile Include="..\..\src\ballistica\platform\sdl\sdl_app.cc" /> <ClCompile Include="..\..\src\ballistica\platform\sdl\sdl_app.cc" />
<ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h" /> <ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h" />
<ClCompile Include="..\..\src\ballistica\platform\stdio_console.cc" />
<ClInclude Include="..\..\src\ballistica\platform\stdio_console.h" />
<ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc" /> <ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc" />
<ClInclude Include="..\..\src\ballistica\platform\windows\platform_windows.h" /> <ClInclude Include="..\..\src\ballistica\platform\windows\platform_windows.h" />
<ClCompile Include="..\..\src\ballistica\python\class\python_class.cc" /> <ClCompile Include="..\..\src\ballistica\python\class\python_class.cc" />
@ -543,14 +540,14 @@
<ClInclude Include="..\..\src\ballistica\python\class\python_class_widget.h" /> <ClInclude Include="..\..\src\ballistica\python\class\python_class_widget.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_app.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_app.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_assets.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_assets.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_gameplay.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_gameplay.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_graphics.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_graphics.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_graphics.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_graphics.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_input.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_input.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_media.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_media.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc" />
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_networking.h" /> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_networking.h" />
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_system.cc" /> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_system.cc" />
@ -624,6 +621,10 @@
<ClInclude Include="..\..\src\ballistica\scene\node\time_display_node.h" /> <ClInclude Include="..\..\src\ballistica\scene\node\time_display_node.h" />
<ClCompile Include="..\..\src\ballistica\scene\scene.cc" /> <ClCompile Include="..\..\src\ballistica\scene\scene.cc" />
<ClInclude Include="..\..\src\ballistica\scene\scene.h" /> <ClInclude Include="..\..\src\ballistica\scene\scene.h" />
<ClCompile Include="..\..\src\ballistica\scene\scene_stream.cc" />
<ClInclude Include="..\..\src\ballistica\scene\scene_stream.h" />
<ClCompile Include="..\..\src\ballistica\scene\v1\scene_v1.cc" />
<ClInclude Include="..\..\src\ballistica\scene\v1\scene_v1.h" />
<ClCompile Include="..\..\src\ballistica\ui\console.cc" /> <ClCompile Include="..\..\src\ballistica\ui\console.cc" />
<ClInclude Include="..\..\src\ballistica\ui\console.h" /> <ClInclude Include="..\..\src\ballistica\ui\console.h" />
<ClCompile Include="..\..\src\ballistica\ui\root_ui.cc" /> <ClCompile Include="..\..\src\ballistica\ui\root_ui.cc" />

View File

@ -37,6 +37,108 @@
<ClInclude Include="..\..\src\ballistica\app\stress_test.h"> <ClInclude Include="..\..\src\ballistica\app\stress_test.h">
<Filter>ballistica\app</Filter> <Filter>ballistica\app</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\assets.cc">
<Filter>ballistica\assets</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\assets.h">
<Filter>ballistica\assets</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\assets_server.cc">
<Filter>ballistica\assets</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\assets_server.h">
<Filter>ballistica\assets</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\asset_component.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\asset_component.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\collide_model.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\collide_model.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\cube_map_texture.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\cube_map_texture.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\data.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\data.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\model.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\model.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\sound.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\sound.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\component\texture.cc">
<Filter>ballistica\assets\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\component\texture.h">
<Filter>ballistica\assets\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\asset_component_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\asset_component_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\collide_model_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\collide_model_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\data_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\data_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\model_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\model_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\assets\data\model_renderer_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\sound_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\sound_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\texture_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\assets\data\texture_preload_data.cc">
<Filter>ballistica\assets\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_preload_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\assets\data\texture_renderer_data.h">
<Filter>ballistica\assets\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc"> <ClCompile Include="..\..\src\ballistica\audio\al_sys.cc">
<Filter>ballistica\audio</Filter> <Filter>ballistica\audio</Filter>
</ClCompile> </ClCompile>
@ -301,117 +403,6 @@
<ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h"> <ClInclude Include="..\..\src\ballistica\dynamics\rigid_body.h">
<Filter>ballistica\dynamics</Filter> <Filter>ballistica\dynamics</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\game\account.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\account.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\client_controller_interface.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_set.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_set.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_client_udp.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_client_udp.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\connection\connection_to_host_udp.cc">
<Filter>ballistica\game\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\connection\connection_to_host_udp.h">
<Filter>ballistica\game\connection</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\friend_score_set.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\game.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\game.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\game_stream.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\game_stream.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\host_activity.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\host_activity.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\player.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\player.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\player_spec.cc">
<Filter>ballistica\game</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\player_spec.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\game\score_to_beat.h">
<Filter>ballistica\game</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\host_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\host_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\net_client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\net_client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\replay_client_session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\replay_client_session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\game\session\session.cc">
<Filter>ballistica\game\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\game\session\session.h">
<Filter>ballistica\game\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\generic\base64.cc"> <ClCompile Include="..\..\src\ballistica\generic\base64.cc">
<Filter>ballistica\generic</Filter> <Filter>ballistica\generic</Filter>
</ClCompile> </ClCompile>
@ -766,15 +757,111 @@
<ClInclude Include="..\..\src\ballistica\input\remote_app.h"> <ClInclude Include="..\..\src\ballistica\input\remote_app.h">
<Filter>ballistica\input</Filter> <Filter>ballistica\input</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\input\std_input_module.cc">
<Filter>ballistica\input</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\input\std_input_module.h">
<Filter>ballistica\input</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\internal\app_internal.h"> <ClInclude Include="..\..\src\ballistica\internal\app_internal.h">
<Filter>ballistica\internal</Filter> <Filter>ballistica\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ballistica\logic\client_controller_interface.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_set.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_set.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_client_udp.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.cc">
<Filter>ballistica\logic\connection</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\connection\connection_to_host_udp.h">
<Filter>ballistica\logic\connection</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\logic\friend_score_set.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\host_activity.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\host_activity.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\logic.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\logic.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\player.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\player.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\player_spec.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\player_spec.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\host_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\host_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\net_client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\net_client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\replay_client_session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\replay_client_session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\session\session.cc">
<Filter>ballistica\logic\session</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\session\session.h">
<Filter>ballistica\logic\session</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\logic\v1_account.cc">
<Filter>ballistica\logic</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\logic\v1_account.h">
<Filter>ballistica\logic</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\math\matrix44f.cc"> <ClCompile Include="..\..\src\ballistica\math\matrix44f.cc">
<Filter>ballistica\math</Filter> <Filter>ballistica\math</Filter>
</ClCompile> </ClCompile>
@ -805,118 +892,16 @@
<ClInclude Include="..\..\src\ballistica\math\vector4f.h"> <ClInclude Include="..\..\src\ballistica\math\vector4f.h">
<Filter>ballistica\math</Filter> <Filter>ballistica\math</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\collide_model.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\collide_model.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\cube_map_texture.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\cube_map_texture.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\data.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\data.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\media_component.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\media_component.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\model.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\model.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\sound.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\sound.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\component\texture.cc">
<Filter>ballistica\media\component</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\component\texture.h">
<Filter>ballistica\media\component</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\collide_model_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\collide_model_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\data_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\data_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\media_component_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\media_component_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\model_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\model_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\media\data\model_renderer_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\sound_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\sound_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\texture_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\texture_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\data\texture_preload_data.cc">
<Filter>ballistica\media\data</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\data\texture_preload_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\media\data\texture_renderer_data.h">
<Filter>ballistica\media\data</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\media.cc">
<Filter>ballistica\media</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\media.h">
<Filter>ballistica\media</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\media\media_server.cc">
<Filter>ballistica\media</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\media\media_server.h">
<Filter>ballistica\media</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\network_reader.cc"> <ClCompile Include="..\..\src\ballistica\networking\network_reader.cc">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ballistica\networking\network_reader.h"> <ClInclude Include="..\..\src\ballistica\networking\network_reader.h">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\network_write_module.cc"> <ClCompile Include="..\..\src\ballistica\networking\network_writer.cc">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\..\src\ballistica\networking\network_write_module.h"> <ClInclude Include="..\..\src\ballistica\networking\network_writer.h">
<Filter>ballistica\networking</Filter> <Filter>ballistica\networking</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\networking\networking.cc"> <ClCompile Include="..\..\src\ballistica\networking\networking.cc">
@ -964,6 +949,12 @@
<ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h"> <ClInclude Include="..\..\src\ballistica\platform\sdl\sdl_app.h">
<Filter>ballistica\platform\sdl</Filter> <Filter>ballistica\platform\sdl</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\platform\stdio_console.cc">
<Filter>ballistica\platform</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\platform\stdio_console.h">
<Filter>ballistica\platform</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc"> <ClCompile Include="..\..\src\ballistica\platform\windows\platform_windows.cc">
<Filter>ballistica\platform\windows</Filter> <Filter>ballistica\platform\windows</Filter>
</ClCompile> </ClCompile>
@ -1078,6 +1069,12 @@
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h"> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_app.h">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_assets.cc">
<Filter>ballistica\python\methods</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_assets.h">
<Filter>ballistica\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc"> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_gameplay.cc">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClCompile> </ClCompile>
@ -1096,12 +1093,6 @@
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h"> <ClInclude Include="..\..\src\ballistica\python\methods\python_methods_input.h">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_media.cc">
<Filter>ballistica\python\methods</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\python\methods\python_methods_media.h">
<Filter>ballistica\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc"> <ClCompile Include="..\..\src\ballistica\python\methods\python_methods_networking.cc">
<Filter>ballistica\python\methods</Filter> <Filter>ballistica\python\methods</Filter>
</ClCompile> </ClCompile>
@ -1321,6 +1312,18 @@
<ClInclude Include="..\..\src\ballistica\scene\scene.h"> <ClInclude Include="..\..\src\ballistica\scene\scene.h">
<Filter>ballistica\scene</Filter> <Filter>ballistica\scene</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ballistica\scene\scene_stream.cc">
<Filter>ballistica\scene</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\scene\scene_stream.h">
<Filter>ballistica\scene</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\scene\v1\scene_v1.cc">
<Filter>ballistica\scene\v1</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\scene\v1\scene_v1.h">
<Filter>ballistica\scene\v1</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\ui\console.cc"> <ClCompile Include="..\..\src\ballistica\ui\console.cc">
<Filter>ballistica\ui</Filter> <Filter>ballistica\ui</Filter>
</ClCompile> </ClCompile>
@ -1646,15 +1649,15 @@
<ItemGroup> <ItemGroup>
<Filter Include="ballistica" /> <Filter Include="ballistica" />
<Filter Include="ballistica\app" /> <Filter Include="ballistica\app" />
<Filter Include="ballistica\assets" />
<Filter Include="ballistica\assets\component" />
<Filter Include="ballistica\assets\data" />
<Filter Include="ballistica\audio" /> <Filter Include="ballistica\audio" />
<Filter Include="ballistica\config" /> <Filter Include="ballistica\config" />
<Filter Include="ballistica\core" /> <Filter Include="ballistica\core" />
<Filter Include="ballistica\dynamics" /> <Filter Include="ballistica\dynamics" />
<Filter Include="ballistica\dynamics\bg" /> <Filter Include="ballistica\dynamics\bg" />
<Filter Include="ballistica\dynamics\material" /> <Filter Include="ballistica\dynamics\material" />
<Filter Include="ballistica\game" />
<Filter Include="ballistica\game\connection" />
<Filter Include="ballistica\game\session" />
<Filter Include="ballistica\generic" /> <Filter Include="ballistica\generic" />
<Filter Include="ballistica\graphics" /> <Filter Include="ballistica\graphics" />
<Filter Include="ballistica\graphics\component" /> <Filter Include="ballistica\graphics\component" />
@ -1665,10 +1668,10 @@
<Filter Include="ballistica\input" /> <Filter Include="ballistica\input" />
<Filter Include="ballistica\input\device" /> <Filter Include="ballistica\input\device" />
<Filter Include="ballistica\internal" /> <Filter Include="ballistica\internal" />
<Filter Include="ballistica\logic" />
<Filter Include="ballistica\logic\connection" />
<Filter Include="ballistica\logic\session" />
<Filter Include="ballistica\math" /> <Filter Include="ballistica\math" />
<Filter Include="ballistica\media" />
<Filter Include="ballistica\media\component" />
<Filter Include="ballistica\media\data" />
<Filter Include="ballistica\networking" /> <Filter Include="ballistica\networking" />
<Filter Include="ballistica\platform" /> <Filter Include="ballistica\platform" />
<Filter Include="ballistica\platform\apple" /> <Filter Include="ballistica\platform\apple" />
@ -1680,6 +1683,7 @@
<Filter Include="ballistica\python\methods" /> <Filter Include="ballistica\python\methods" />
<Filter Include="ballistica\scene" /> <Filter Include="ballistica\scene" />
<Filter Include="ballistica\scene\node" /> <Filter Include="ballistica\scene\node" />
<Filter Include="ballistica\scene\v1" />
<Filter Include="ballistica\ui" /> <Filter Include="ballistica\ui" />
<Filter Include="ballistica\ui\widget" /> <Filter Include="ballistica\ui\widget" />
<Filter Include="external" /> <Filter Include="external" />

View File

@ -13,24 +13,15 @@
namespace ballistica { namespace ballistica {
// The first thing the engine does is allocate an instance of this as g_globals. // The first thing the engine does is allocate an instance of this as g_app.
// As much as possible, previously static/global values should be moved to here,
// ideally as a temporary measure until they can be placed as non-static members
// in the proper classes.
// Any use of non-trivial global/static values such as class instances should be
// avoided since it can introduce ambiguities during init and teardown.
// For more explanation, see the 'Static and Global Variables' section in the
// Google C++ Style Guide.
class App { class App {
public: public:
App(int argc, char** argv); App(int argc, char** argv);
/// Program argument count (on applicable platforms). // The following are misc values that should be migrated to applicable
// subsystem classes.
int argc{}; int argc{};
/// Program argument values (on applicable platforms).
char** argv{}; char** argv{};
bool threads_paused{}; bool threads_paused{};
std::unordered_map<std::string, NodeType*> node_types; std::unordered_map<std::string, NodeType*> node_types;
std::unordered_map<int, NodeType*> node_types_by_id; std::unordered_map<int, NodeType*> node_types_by_id;
@ -41,10 +32,10 @@ class App {
std::vector<Thread*> pausable_threads; std::vector<Thread*> pausable_threads;
TouchInput* touch_input{}; TouchInput* touch_input{};
std::string console_startup_messages; std::string console_startup_messages;
std::mutex log_mutex; std::mutex v1_cloud_log_mutex;
std::string log; std::string v1_cloud_log;
bool put_log{}; bool did_put_v1_cloud_log{};
bool log_full{}; bool v1_cloud_log_full{};
int master_server_source{0}; int master_server_source{0};
int session_count{}; int session_count{};
bool shutting_down{}; bool shutting_down{};

View File

@ -8,8 +8,6 @@
namespace ballistica { namespace ballistica {
void AppConfig::Init() { new AppConfig(); }
auto AppConfig::Entry::FloatValue() const -> float { auto AppConfig::Entry::FloatValue() const -> float {
throw Exception("not a float entry"); throw Exception("not a float entry");
} }
@ -137,12 +135,7 @@ class AppConfig::BoolEntry : public AppConfig::Entry {
bool default_value_{}; bool default_value_{};
}; };
AppConfig::AppConfig() { AppConfig::AppConfig() { SetupEntries(); }
// (We're a singleton).
assert(g_app_config == nullptr);
g_app_config = this;
SetupEntries();
}
// Clion think all calls of this are unreachable. // Clion think all calls of this are unreachable.
#pragma clang diagnostic push #pragma clang diagnostic push

View File

@ -13,7 +13,7 @@ namespace ballistica {
// This class wrangles user config values for the app. // This class wrangles user config values for the app.
// The underlying config data currently lives in the Python layer, // The underlying config data currently lives in the Python layer,
// so at the moment these calls are only usable from the game thread, // so at the moment these calls are only usable from the logic thread,
// but that may change in the future. // but that may change in the future.
class AppConfig { class AppConfig {
public: public:
@ -94,7 +94,6 @@ class AppConfig {
std::string name_; std::string name_;
}; };
static void Init();
AppConfig(); AppConfig();
// Given specific ids, returns resolved values (fastest access). // Given specific ids, returns resolved values (fastest access).

View File

@ -4,11 +4,11 @@
#include "ballistica/app/stress_test.h" #include "ballistica/app/stress_test.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/renderer.h" #include "ballistica/graphics/renderer.h"
#include "ballistica/input/device/touch_input.h" #include "ballistica/input/device/touch_input.h"
#include "ballistica/input/input.h" #include "ballistica/input/input.h"
#include "ballistica/logic/logic.h"
#include "ballistica/networking/network_reader.h" #include "ballistica/networking/network_reader.h"
#include "ballistica/networking/networking.h" #include "ballistica/networking/networking.h"
#include "ballistica/networking/telnet_server.h" #include "ballistica/networking/telnet_server.h"
@ -18,20 +18,30 @@ namespace ballistica {
AppFlavor::AppFlavor(Thread* thread) AppFlavor::AppFlavor(Thread* thread)
: thread_(thread), stress_test_(std::make_unique<StressTest>()) { : thread_(thread), stress_test_(std::make_unique<StressTest>()) {
// assert(g_app_flavor == nullptr);
// g_app_flavor = this;
// We modify some app behavior when run under the server manager. // We modify some app behavior when run under the server manager.
auto* envval = getenv("BA_SERVER_WRAPPER_MANAGED"); auto* envval = getenv("BA_SERVER_WRAPPER_MANAGED");
server_wrapper_managed_ = (envval && strcmp(envval, "1") == 0); server_wrapper_managed_ = (envval && strcmp(envval, "1") == 0);
} }
void AppFlavor::PostInit() { void AppFlavor::PostInit() {
// If we've got a nice themed hardware cursor, show it. // Sanity check: make sure asserts are stripped out of release builds
// Otherwise, hide the hardware cursor; we'll draw it in software. // (NDEBUG should do this).
// (need to run this in postinit because SDL/etc. may not be inited yet #if !BA_DEBUG_BUILD
// as of AppFlavor::AppFlavor()). #ifndef NDEBUG
g_platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor()); #error Expected NDEBUG to be defined for release builds.
#endif // NDEBUG
assert(true);
#endif // !BA_DEBUG_BUILD
g_app->user_agent_string = g_platform->GetUserAgentString();
// Figure out where our data is and chdir there.
g_platform->SetupDataDirectory();
// Run these just to make sure these dirs exist.
// (otherwise they might not get made if nothing writes to them).
g_platform->GetConfigDirectory();
g_platform->GetUserPythonDirectory();
} }
auto AppFlavor::ManagesEventLoop() const -> bool { auto AppFlavor::ManagesEventLoop() const -> bool {
@ -186,7 +196,7 @@ void AppFlavor::OnResume() {
// Also let the Python layer do what it needs to // Also let the Python layer do what it needs to
// (starting/stopping music, etc.). // (starting/stopping music, etc.).
g_python->PushObjCall(Python::ObjID::kHandleAppResumeCall); g_python->PushObjCall(Python::ObjID::kHandleAppResumeCall);
g_game->PushOnAppResumeCall(); g_logic->PushOnAppResumeCall();
g_graphics->SetGyroEnabled(true); g_graphics->SetGyroEnabled(true);
@ -201,7 +211,7 @@ void AppFlavor::OnResume() {
// If we've been completely backgrounded, // If we've been completely backgrounded,
// send a menu-press command to the game; this will // send a menu-press command to the game; this will
// bring up a pause menu if we're in the game/etc. // bring up a pause menu if we're in the game/etc.
g_game->PushMainMenuPressCall(nullptr); g_logic->PushMainMenuPressCall(nullptr);
} }
} }
@ -268,11 +278,7 @@ void AppFlavor::PushNetworkSetupCall(int port, int telnet_port,
const std::string& telnet_password) { const std::string& telnet_password) {
thread()->PushCall([port, telnet_port, enable_telnet, telnet_password] { thread()->PushCall([port, telnet_port, enable_telnet, telnet_password] {
assert(InMainThread()); assert(InMainThread());
// Kick these off if they don't exist. g_network_reader->SetPort(port);
// (do we want to support changing ports on existing ones?)
if (g_network_reader == nullptr) {
new NetworkReader(port);
}
if (g_app->telnet_server == nullptr && enable_telnet) { if (g_app->telnet_server == nullptr && enable_telnet) {
new TelnetServer(telnet_port); new TelnetServer(telnet_port);
assert(g_app->telnet_server); assert(g_app->telnet_server);
@ -291,15 +297,6 @@ void AppFlavor::PushPurchaseAckCall(const std::string& purchase,
[purchase, order_id] { g_platform->PurchaseAck(purchase, order_id); }); [purchase, order_id] { g_platform->PurchaseAck(purchase, order_id); });
} }
void AppFlavor::PushGetScoresToBeatCall(const std::string& level,
const std::string& config,
void* py_callback) {
thread()->PushCall([level, config, py_callback] {
assert(InMainThread());
g_platform->GetScoresToBeat(level, config, py_callback);
});
}
void AppFlavor::PushPurchaseCall(const std::string& item) { void AppFlavor::PushPurchaseCall(const std::string& item) {
thread()->PushCall([item] { thread()->PushCall([item] {
assert(InMainThread()); assert(InMainThread());
@ -366,10 +363,31 @@ void AppFlavor::PushResetAchievementsCall() {
thread()->PushCall([] { g_platform->ResetAchievements(); }); thread()->PushCall([] { g_platform->ResetAchievements(); });
} }
void AppFlavor::OnBootstrapComplete() { void AppFlavor::OnAppStart() {
assert(InMainThread()); assert(InMainThread());
assert(g_input); assert(g_input);
// If we're running in a terminal, print some info.
// if (g_platform->is_stdin_a_terminal()) {
{
char buffer[256];
if (g_buildconfig.headless_build()) {
snprintf(buffer, sizeof(buffer), "BallisticaCore Headless %s build %d.",
kAppVersion, kAppBuildNumber);
} else {
snprintf(buffer, sizeof(buffer), "BallisticaCore %s build %d.",
kAppVersion, kAppBuildNumber);
}
Log(LogLevel::kInfo, buffer);
}
// }
// If we've got a nice themed hardware cursor, show it.
// Otherwise, hide the hardware cursor; we'll draw it in software.
// (need to run this in postinit because SDL/etc. may not be inited yet
// as of AppFlavor::AppFlavor()).
g_platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor());
if (!HeadlessMode()) { if (!HeadlessMode()) {
// On desktop systems we just assume keyboard input exists and add it // On desktop systems we just assume keyboard input exists and add it
// immediately. // immediately.

View File

@ -93,7 +93,7 @@ class AppFlavor {
return server_wrapper_managed_; return server_wrapper_managed_;
} }
virtual auto OnBootstrapComplete() -> void; virtual auto OnAppStart() -> void;
// Deferred calls that can be made from other threads. // Deferred calls that can be made from other threads.
@ -108,9 +108,6 @@ class AppFlavor {
const std::string& game_version, int64_t score) const std::string& game_version, int64_t score)
-> void; -> void;
auto PushAchievementReportCall(const std::string& achievement) -> void; auto PushAchievementReportCall(const std::string& achievement) -> void;
auto PushGetScoresToBeatCall(const std::string& level,
const std::string& config, void* py_callback)
-> void;
auto PushOpenURLCall(const std::string& url) -> void; auto PushOpenURLCall(const std::string& url) -> void;
auto PushStringEditCall(const std::string& name, const std::string& value, auto PushStringEditCall(const std::string& name, const std::string& value,
int max_chars) -> void; int max_chars) -> void;

View File

@ -4,9 +4,9 @@
#include "ballistica/app/app_flavor_vr.h" #include "ballistica/app/app_flavor_vr.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/renderer.h" #include "ballistica/graphics/renderer.h"
#include "ballistica/logic/logic.h"
namespace ballistica { namespace ballistica {
@ -87,7 +87,7 @@ auto AppFlavorVR::VRSetHands(const VRHandsState& state) -> void {
renderer->VRSetHands(state); renderer->VRSetHands(state);
// ALSO ship it off to the game/ui thread to actually handle input from it. // ALSO ship it off to the game/ui thread to actually handle input from it.
g_game->PushVRHandsState(state); g_logic->PushVRHandsState(state);
} }
auto AppFlavorVR::VRDrawEye(int eye, float yaw, float pitch, float roll, auto AppFlavorVR::VRDrawEye(int eye, float yaw, float pitch, float roll,

View File

@ -76,13 +76,13 @@ void StressTest::Update() {
uint32_t texture_count = 0; uint32_t texture_count = 0;
uint32_t sound_count = 0; uint32_t sound_count = 0;
uint32_t node_count = 0; uint32_t node_count = 0;
if (g_media) { if (g_assets) {
model_count = g_media->total_model_count(); model_count = g_assets->total_model_count();
collide_model_count = g_media->total_collide_model_count(); collide_model_count = g_assets->total_collide_model_count();
texture_count = g_media->total_texture_count(); texture_count = g_assets->total_texture_count();
sound_count = g_media->total_sound_count(); sound_count = g_assets->total_sound_count();
} }
assert(g_game); assert(g_logic);
std::string mem_usage = g_platform->GetMemUsageInfo(); std::string mem_usage = g_platform->GetMemUsageInfo();
fprintf(stress_test_stats_file_, "%d,%.1f,%d,%d,%d,%d,%d,%s\n", fprintf(stress_test_stats_file_, "%d,%.1f,%d,%d,%d,%d,%d,%s\n",
static_cast_check_fit<int>(GetRealTime()), avg, node_count, static_cast_check_fit<int>(GetRealTime()), avg, node_count,

View File

@ -1,33 +1,33 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/media.h" #include "ballistica/assets/assets.h"
#if !BA_OSTYPE_WINDOWS #if !BA_OSTYPE_WINDOWS
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include "ballistica/assets/assets_server.h"
#include "ballistica/assets/component/collide_model.h"
#include "ballistica/assets/component/data.h"
#include "ballistica/assets/component/model.h"
#include "ballistica/assets/component/texture.h"
#include "ballistica/assets/data/sound_data.h"
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/generic/timer.h" #include "ballistica/generic/timer.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/text/text_packer.h" #include "ballistica/graphics/text/text_packer.h"
#include "ballistica/media/component/collide_model.h" #include "ballistica/logic/logic.h"
#include "ballistica/media/component/data.h"
#include "ballistica/media/component/model.h"
#include "ballistica/media/component/texture.h"
#include "ballistica/media/data/sound_data.h"
#include "ballistica/media/media_server.h"
#include "ballistica/python/python_sys.h" #include "ballistica/python/python_sys.h"
namespace ballistica { namespace ballistica {
// Debug printing. // Debug printing:
#define BA_SHOW_LOADS_UNLOADS 0 #define BA_SHOW_LOADS_UNLOADS 0
#define SHOW_PRUNING_INFO 0 #define SHOW_PRUNING_INFO 0
// Standard prune time for unused media: 10 minutes (1000ms * 60 * 10). // Standard prune time for unused assets: 10 minutes (1000ms * 60 * 10).
#define STANDARD_MEDIA_PRUNE_TIME 600000 #define STANDARD_ASSET_PRUNE_TIME 600000
// More aggressive prune time for dynamically-generated text-textures: 10 // More aggressive prune time for dynamically-generated text-textures: 10
// seconds. // seconds.
@ -35,59 +35,53 @@ namespace ballistica {
#define QR_TEXTURE_PRUNE_TIME 10000 #define QR_TEXTURE_PRUNE_TIME 10000
// How long we should spend loading media in each runPendingLoads() call. // How long we should spend loading assets in each runPendingLoads() call.
#define PENDING_LOAD_PROCESS_TIME 5 #define PENDING_LOAD_PROCESS_TIME 5
void Media::Init() { Assets::Assets() {
// Just create our singleton. asset_paths_.emplace_back("ba_data");
assert(g_media == nullptr);
g_media = new Media();
}
Media::Media() {
media_paths_.emplace_back("ba_data");
for (bool& have_pending_load : have_pending_loads_) { for (bool& have_pending_load : have_pending_loads_) {
have_pending_load = false; have_pending_load = false;
} }
} }
void Media::LoadSystemTexture(SystemTextureID id, const char* name) { void Assets::LoadSystemTexture(SystemTextureID id, const char* name) {
assert(media_lists_locked_); assert(asset_lists_locked_);
system_textures_.push_back(GetTextureData(name)); system_textures_.push_back(GetTextureData(name));
assert(system_textures_.size() == static_cast<int>(id) + 1); assert(system_textures_.size() == static_cast<int>(id) + 1);
} }
void Media::LoadSystemCubeMapTexture(SystemCubeMapTextureID id, void Assets::LoadSystemCubeMapTexture(SystemCubeMapTextureID id,
const char* name) { const char* name) {
assert(media_lists_locked_); assert(asset_lists_locked_);
system_cube_map_textures_.push_back(GetCubeMapTextureData(name)); system_cube_map_textures_.push_back(GetCubeMapTextureData(name));
assert(system_cube_map_textures_.size() == static_cast<int>(id) + 1); assert(system_cube_map_textures_.size() == static_cast<int>(id) + 1);
} }
void Media::LoadSystemSound(SystemSoundID id, const char* name) { void Assets::LoadSystemSound(SystemSoundID id, const char* name) {
system_sounds_.push_back(GetSoundData(name)); system_sounds_.push_back(GetSoundData(name));
assert(system_sounds_.size() == static_cast<int>(id) + 1); assert(system_sounds_.size() == static_cast<int>(id) + 1);
} }
void Media::LoadSystemData(SystemDataID id, const char* name) { void Assets::LoadSystemData(SystemDataID id, const char* name) {
system_datas_.push_back(GetDataData(name)); system_datas_.push_back(GetDataData(name));
assert(system_datas_.size() == static_cast<int>(id) + 1); assert(system_datas_.size() == static_cast<int>(id) + 1);
} }
void Media::LoadSystemModel(SystemModelID id, const char* name) { void Assets::LoadSystemModel(SystemModelID id, const char* name) {
system_models_.push_back(GetModelData(name)); system_models_.push_back(GetModelData(name));
assert(system_models_.size() == static_cast<int>(id) + 1); assert(system_models_.size() == static_cast<int>(id) + 1);
} }
void Media::LoadSystemMedia() { void Assets::LoadSystemAssets() {
assert(InLogicThread()); assert(InLogicThread());
assert(g_audio_server && g_media_server && g_graphics_server); assert(g_audio_server && g_assets_server && g_graphics_server);
assert(g_graphics_server assert(g_graphics_server
&& g_graphics_server->texture_compression_types_are_set()); && g_graphics_server->texture_compression_types_are_set());
assert(g_graphics && g_graphics_server->texture_quality_set()); assert(g_graphics && g_graphics_server->texture_quality_set());
// Just grab the lock once for all this stuff for efficiency. // Just grab the lock once for all this stuff for efficiency.
MediaListsLock lock; AssetListLock lock;
// System textures: // System textures:
LoadSystemTexture(SystemTextureID::kUIAtlas, "uiAtlas"); LoadSystemTexture(SystemTextureID::kUIAtlas, "uiAtlas");
@ -286,26 +280,24 @@ void Media::LoadSystemMedia() {
LoadSystemModel(SystemModelID::kWing, "wing"); LoadSystemModel(SystemModelID::kWing, "wing");
// Hooray! // Hooray!
system_media_loaded_ = true; system_assets_loaded_ = true;
} }
Media::~Media() = default; void Assets::PrintLoadInfo() {
void Media::PrintLoadInfo() {
std::string s; std::string s;
char buffer[256]; char buffer[256];
int num = 1; int num = 1;
// Need to lock lists while iterating over them. // Need to lock lists while iterating over them.
MediaListsLock lock; AssetListLock lock;
s = "Media load results: (all times in milliseconds):\n"; s = "Assets load results: (all times in milliseconds):\n";
snprintf(buffer, sizeof(buffer), " %-50s %10s %10s", "FILE", snprintf(buffer, sizeof(buffer), " %-50s %10s %10s", "FILE",
"PRELOAD_TIME", "LOAD_TIME"); "PRELOAD_TIME", "LOAD_TIME");
s += buffer; s += buffer;
Log(s, true, false); Log(LogLevel::kInfo, s);
millisecs_t total_preload_time = 0; millisecs_t total_preload_time = 0;
millisecs_t total_load_time = 0; millisecs_t total_load_time = 0;
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : models_) { for (auto&& i : models_) {
millisecs_t preload_time = i.second->preload_time(); millisecs_t preload_time = i.second->preload_time();
millisecs_t load_time = i.second->load_time(); millisecs_t load_time = i.second->load_time();
@ -315,10 +307,10 @@ void Media::PrintLoadInfo() {
i.second->GetName().c_str(), i.second->GetName().c_str(),
static_cast_check_fit<int>(preload_time), static_cast_check_fit<int>(preload_time),
static_cast_check_fit<int>(load_time)); static_cast_check_fit<int>(load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
num++; num++;
} }
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : collide_models_) { for (auto&& i : collide_models_) {
millisecs_t preload_time = i.second->preload_time(); millisecs_t preload_time = i.second->preload_time();
millisecs_t load_time = i.second->load_time(); millisecs_t load_time = i.second->load_time();
@ -328,10 +320,10 @@ void Media::PrintLoadInfo() {
i.second->GetName().c_str(), i.second->GetName().c_str(),
static_cast_check_fit<int>(preload_time), static_cast_check_fit<int>(preload_time),
static_cast_check_fit<int>(load_time)); static_cast_check_fit<int>(load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
num++; num++;
} }
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : sounds_) { for (auto&& i : sounds_) {
millisecs_t preload_time = i.second->preload_time(); millisecs_t preload_time = i.second->preload_time();
millisecs_t load_time = i.second->load_time(); millisecs_t load_time = i.second->load_time();
@ -341,10 +333,10 @@ void Media::PrintLoadInfo() {
i.second->GetName().c_str(), i.second->GetName().c_str(),
static_cast_check_fit<int>(preload_time), static_cast_check_fit<int>(preload_time),
static_cast_check_fit<int>(load_time)); static_cast_check_fit<int>(load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
num++; num++;
} }
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : datas_) { for (auto&& i : datas_) {
millisecs_t preload_time = i.second->preload_time(); millisecs_t preload_time = i.second->preload_time();
millisecs_t load_time = i.second->load_time(); millisecs_t load_time = i.second->load_time();
@ -354,10 +346,10 @@ void Media::PrintLoadInfo() {
i.second->GetName().c_str(), i.second->GetName().c_str(),
static_cast_check_fit<int>(preload_time), static_cast_check_fit<int>(preload_time),
static_cast_check_fit<int>(load_time)); static_cast_check_fit<int>(load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
num++; num++;
} }
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : textures_) { for (auto&& i : textures_) {
millisecs_t preload_time = i.second->preload_time(); millisecs_t preload_time = i.second->preload_time();
millisecs_t load_time = i.second->load_time(); millisecs_t load_time = i.second->load_time();
@ -367,7 +359,7 @@ void Media::PrintLoadInfo() {
i.second->file_name_full().c_str(), i.second->file_name_full().c_str(),
static_cast_check_fit<int>(preload_time), static_cast_check_fit<int>(preload_time),
static_cast_check_fit<int>(load_time)); static_cast_check_fit<int>(load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
num++; num++;
} }
snprintf(buffer, sizeof(buffer), snprintf(buffer, sizeof(buffer),
@ -375,99 +367,100 @@ void Media::PrintLoadInfo() {
"(feeding data to OpenGL, etc): %i", "(feeding data to OpenGL, etc): %i",
static_cast<int>(total_preload_time), static_cast<int>(total_preload_time),
static_cast<int>(total_load_time)); static_cast<int>(total_load_time));
Log(buffer, true, false); Log(LogLevel::kInfo, buffer);
} }
void Media::MarkAllMediaForLoad() { void Assets::MarkAllAssetsForLoad() {
assert(InLogicThread()); assert(InLogicThread());
// Need to keep lists locked while iterating over them. // Need to keep lists locked while iterating over them.
MediaListsLock m_lock; AssetListLock m_lock;
for (auto&& i : textures_) { for (auto&& i : textures_) {
if (!i.second->preloaded()) { if (!i.second->preloaded()) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
have_pending_loads_[static_cast<int>(MediaType::kTexture)] = true; have_pending_loads_[static_cast<int>(AssetType::kTexture)] = true;
MarkComponentForLoad(i.second.get()); MarkComponentForLoad(i.second.get());
} }
} }
for (auto&& i : text_textures_) { for (auto&& i : text_textures_) {
if (!i.second->preloaded()) { if (!i.second->preloaded()) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
have_pending_loads_[static_cast<int>(MediaType::kTexture)] = true; have_pending_loads_[static_cast<int>(AssetType::kTexture)] = true;
MarkComponentForLoad(i.second.get()); MarkComponentForLoad(i.second.get());
} }
} }
for (auto&& i : qr_textures_) { for (auto&& i : qr_textures_) {
if (!i.second->preloaded()) { if (!i.second->preloaded()) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
have_pending_loads_[static_cast<int>(MediaType::kTexture)] = true; have_pending_loads_[static_cast<int>(AssetType::kTexture)] = true;
MarkComponentForLoad(i.second.get()); MarkComponentForLoad(i.second.get());
} }
} }
for (auto&& i : models_) { for (auto&& i : models_) {
if (!i.second->preloaded()) { if (!i.second->preloaded()) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
have_pending_loads_[static_cast<int>(MediaType::kModel)] = true; have_pending_loads_[static_cast<int>(AssetType::kModel)] = true;
MarkComponentForLoad(i.second.get()); MarkComponentForLoad(i.second.get());
} }
} }
} }
// Call this from the graphics thread to immediately unload all // Call this from the graphics thread to immediately unload all
// media used by it. (for when GL context gets lost, etc). // assets used by it. (for when GL context gets lost, etc).
void Media::UnloadRendererBits(bool do_textures, bool do_models) { void Assets::UnloadRendererBits(bool do_textures, bool do_models) {
assert(InGraphicsThread()); assert(InGraphicsThread());
// need to keep lists locked while iterating over them.. // need to keep lists locked while iterating over them..
MediaListsLock m_lock; AssetListLock m_lock;
if (do_textures) { if (do_textures) {
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto&& i : textures_) { for (auto&& i : textures_) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
i.second->Unload(true); i.second->Unload(true);
} }
for (auto&& i : text_textures_) { for (auto&& i : text_textures_) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
i.second->Unload(true); i.second->Unload(true);
} }
for (auto&& i : qr_textures_) { for (auto&& i : qr_textures_) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
i.second->Unload(true); i.second->Unload(true);
} }
} }
if (do_models) { if (do_models) {
for (auto&& i : models_) { for (auto&& i : models_) {
MediaComponentData::LockGuard lock(i.second.get()); AssetComponentData::LockGuard lock(i.second.get());
i.second->Unload(true); i.second->Unload(true);
} }
} }
} }
auto Media::GetModelData(const std::string& file_name) auto Assets::GetModelData(const std::string& file_name)
-> Object::Ref<ModelData> { -> Object::Ref<ModelData> {
return GetComponentData(file_name, &models_); return GetComponentData(file_name, &models_);
} }
auto Media::GetSoundData(const std::string& file_name) auto Assets::GetSoundData(const std::string& file_name)
-> Object::Ref<SoundData> { -> Object::Ref<SoundData> {
return GetComponentData(file_name, &sounds_); return GetComponentData(file_name, &sounds_);
} }
auto Media::GetDataData(const std::string& file_name) -> Object::Ref<DataData> { auto Assets::GetDataData(const std::string& file_name)
-> Object::Ref<DataData> {
return GetComponentData(file_name, &datas_); return GetComponentData(file_name, &datas_);
} }
auto Media::GetCollideModelData(const std::string& file_name) auto Assets::GetCollideModelData(const std::string& file_name)
-> Object::Ref<CollideModelData> { -> Object::Ref<CollideModelData> {
return GetComponentData(file_name, &collide_models_); return GetComponentData(file_name, &collide_models_);
} }
template <class T> template <class T>
auto Media::GetComponentData( auto Assets::GetComponentData(
const std::string& file_name, const std::string& file_name,
std::unordered_map<std::string, Object::Ref<T> >* c_list) std::unordered_map<std::string, Object::Ref<T> >* c_list)
-> Object::Ref<T> { -> Object::Ref<T> {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
auto i = c_list->find(file_name); auto i = c_list->find(file_name);
if (i != c_list->end()) { if (i != c_list->end()) {
return Object::Ref<T>(i->second.get()); return Object::Ref<T>(i->second.get());
@ -475,8 +468,8 @@ auto Media::GetComponentData(
auto d(Object::New<T>(file_name)); auto d(Object::New<T>(file_name));
(*c_list)[file_name] = d; (*c_list)[file_name] = d;
{ {
MediaComponentData::LockGuard lock(d.get()); AssetComponentData::LockGuard lock(d.get());
have_pending_loads_[static_cast<int>(d->GetMediaType())] = true; have_pending_loads_[static_cast<int>(d->GetAssetType())] = true;
MarkComponentForLoad(d.get()); MarkComponentForLoad(d.get());
} }
d->set_last_used_time(GetRealTime()); d->set_last_used_time(GetRealTime());
@ -484,9 +477,9 @@ auto Media::GetComponentData(
} }
} }
auto Media::GetTextureData(TextPacker* packer) -> Object::Ref<TextureData> { auto Assets::GetTextureData(TextPacker* packer) -> Object::Ref<TextureData> {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
const std::string& hash(packer->hash()); const std::string& hash(packer->hash());
auto i = text_textures_.find(hash); auto i = text_textures_.find(hash);
if (i != text_textures_.end()) { if (i != text_textures_.end()) {
@ -495,8 +488,8 @@ auto Media::GetTextureData(TextPacker* packer) -> Object::Ref<TextureData> {
auto d(Object::New<TextureData>(packer)); auto d(Object::New<TextureData>(packer));
text_textures_[hash] = d; text_textures_[hash] = d;
{ {
MediaComponentData::LockGuard lock(d.get()); AssetComponentData::LockGuard lock(d.get());
have_pending_loads_[static_cast<int>(d->GetMediaType())] = true; have_pending_loads_[static_cast<int>(d->GetAssetType())] = true;
MarkComponentForLoad(d.get()); MarkComponentForLoad(d.get());
} }
d->set_last_used_time(GetRealTime()); d->set_last_used_time(GetRealTime());
@ -504,10 +497,10 @@ auto Media::GetTextureData(TextPacker* packer) -> Object::Ref<TextureData> {
} }
} }
auto Media::GetTextureDataQRCode(const std::string& url) auto Assets::GetTextureDataQRCode(const std::string& url)
-> Object::Ref<TextureData> { -> Object::Ref<TextureData> {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
auto i = qr_textures_.find(url); auto i = qr_textures_.find(url);
if (i != qr_textures_.end()) { if (i != qr_textures_.end()) {
return Object::Ref<TextureData>(i->second.get()); return Object::Ref<TextureData>(i->second.get());
@ -515,8 +508,8 @@ auto Media::GetTextureDataQRCode(const std::string& url)
auto d(Object::New<TextureData>(url)); auto d(Object::New<TextureData>(url));
qr_textures_[url] = d; qr_textures_[url] = d;
{ {
MediaComponentData::LockGuard lock(d.get()); AssetComponentData::LockGuard lock(d.get());
have_pending_loads_[static_cast<int>(d->GetMediaType())] = true; have_pending_loads_[static_cast<int>(d->GetAssetType())] = true;
MarkComponentForLoad(d.get()); MarkComponentForLoad(d.get());
} }
d->set_last_used_time(GetRealTime()); d->set_last_used_time(GetRealTime());
@ -526,10 +519,10 @@ auto Media::GetTextureDataQRCode(const std::string& url)
// Eww can't recycle GetComponent here since we need extra stuff (tex-type arg) // Eww can't recycle GetComponent here since we need extra stuff (tex-type arg)
// ..should fix. // ..should fix.
auto Media::GetCubeMapTextureData(const std::string& file_name) auto Assets::GetCubeMapTextureData(const std::string& file_name)
-> Object::Ref<TextureData> { -> Object::Ref<TextureData> {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
auto i = textures_.find(file_name); auto i = textures_.find(file_name);
if (i != textures_.end()) { if (i != textures_.end()) {
return Object::Ref<TextureData>(i->second.get()); return Object::Ref<TextureData>(i->second.get());
@ -538,8 +531,8 @@ auto Media::GetCubeMapTextureData(const std::string& file_name)
TextureMinQuality::kLow)); TextureMinQuality::kLow));
textures_[file_name] = d; textures_[file_name] = d;
{ {
MediaComponentData::LockGuard lock(d.get()); AssetComponentData::LockGuard lock(d.get());
have_pending_loads_[static_cast<int>(d->GetMediaType())] = true; have_pending_loads_[static_cast<int>(d->GetAssetType())] = true;
MarkComponentForLoad(d.get()); MarkComponentForLoad(d.get());
} }
d->set_last_used_time(GetRealTime()); d->set_last_used_time(GetRealTime());
@ -549,10 +542,10 @@ auto Media::GetCubeMapTextureData(const std::string& file_name)
// Eww; can't recycle GetComponent here since we need extra stuff (quality // Eww; can't recycle GetComponent here since we need extra stuff (quality
// settings, etc). Should fix. // settings, etc). Should fix.
auto Media::GetTextureData(const std::string& file_name) auto Assets::GetTextureData(const std::string& file_name)
-> Object::Ref<TextureData> { -> Object::Ref<TextureData> {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
auto i = textures_.find(file_name); auto i = textures_.find(file_name);
if (i != textures_.end()) { if (i != textures_.end()) {
return Object::Ref<TextureData>(i->second.get()); return Object::Ref<TextureData>(i->second.get());
@ -594,8 +587,8 @@ auto Media::GetTextureData(const std::string& file_name)
auto d(Object::New<TextureData>(file_name, TextureType::k2D, min_quality)); auto d(Object::New<TextureData>(file_name, TextureType::k2D, min_quality));
textures_[file_name] = d; textures_[file_name] = d;
{ {
MediaComponentData::LockGuard lock(d.get()); AssetComponentData::LockGuard lock(d.get());
have_pending_loads_[static_cast<int>(d->GetMediaType())] = true; have_pending_loads_[static_cast<int>(d->GetAssetType())] = true;
MarkComponentForLoad(d.get()); MarkComponentForLoad(d.get());
} }
d->set_last_used_time(GetRealTime()); d->set_last_used_time(GetRealTime());
@ -603,7 +596,7 @@ auto Media::GetTextureData(const std::string& file_name)
} }
} }
void Media::MarkComponentForLoad(MediaComponentData* c) { void Assets::MarkComponentForLoad(AssetComponentData* c) {
assert(InLogicThread()); assert(InLogicThread());
assert(c->locked()); assert(c->locked());
@ -614,111 +607,110 @@ void Media::MarkComponentForLoad(MediaComponentData* c) {
// once it makes it back to us we can delete the ref (in // once it makes it back to us we can delete the ref (in
// ClearPendingLoadsDoneList) // ClearPendingLoadsDoneList)
auto media_ptr = new Object::Ref<MediaComponentData>(c); auto asset_ref_ptr = new Object::Ref<AssetComponentData>(c);
g_media_server->thread()->PushRunnable( g_assets_server->PushPendingPreload(asset_ref_ptr);
Object::NewDeferred<PreloadRunnable>(media_ptr));
} }
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma ide diagnostic ignored "UnreachableCode" #pragma ide diagnostic ignored "UnreachableCode"
#pragma ide diagnostic ignored "ConstantFunctionResult" #pragma ide diagnostic ignored "ConstantFunctionResult"
auto Media::GetModelPendingLoadCount() -> int { auto Assets::GetModelPendingLoadCount() -> int {
if (!have_pending_loads_[static_cast<int>(MediaType::kModel)]) { if (!have_pending_loads_[static_cast<int>(AssetType::kModel)]) {
return 0; return 0;
} }
MediaListsLock lock; AssetListLock lock;
int total = GetComponentPendingLoadCount(&models_, MediaType::kModel); int total = GetComponentPendingLoadCount(&models_, AssetType::kModel);
if (total == 0) { if (total == 0) {
// When fully loaded, stop counting. // When fully loaded, stop counting.
have_pending_loads_[static_cast<int>(MediaType::kModel)] = false; have_pending_loads_[static_cast<int>(AssetType::kModel)] = false;
} }
return total; return total;
} }
auto Media::GetTexturePendingLoadCount() -> int { auto Assets::GetTexturePendingLoadCount() -> int {
if (!have_pending_loads_[static_cast<int>(MediaType::kTexture)]) { if (!have_pending_loads_[static_cast<int>(AssetType::kTexture)]) {
return 0; return 0;
} }
MediaListsLock lock; AssetListLock lock;
int total = int total =
(GetComponentPendingLoadCount(&textures_, MediaType::kTexture) (GetComponentPendingLoadCount(&textures_, AssetType::kTexture)
+ GetComponentPendingLoadCount(&text_textures_, MediaType::kTexture) + GetComponentPendingLoadCount(&text_textures_, AssetType::kTexture)
+ GetComponentPendingLoadCount(&qr_textures_, MediaType::kTexture)); + GetComponentPendingLoadCount(&qr_textures_, AssetType::kTexture));
if (total == 0) { if (total == 0) {
// When fully loaded, stop counting. // When fully loaded, stop counting.
have_pending_loads_[static_cast<int>(MediaType::kTexture)] = false; have_pending_loads_[static_cast<int>(AssetType::kTexture)] = false;
} }
return total; return total;
} }
auto Media::GetSoundPendingLoadCount() -> int { auto Assets::GetSoundPendingLoadCount() -> int {
if (!have_pending_loads_[static_cast<int>(MediaType::kSound)]) { if (!have_pending_loads_[static_cast<int>(AssetType::kSound)]) {
return 0; return 0;
} }
MediaListsLock lock; AssetListLock lock;
int total = GetComponentPendingLoadCount(&sounds_, MediaType::kSound); int total = GetComponentPendingLoadCount(&sounds_, AssetType::kSound);
if (total == 0) { if (total == 0) {
// When fully loaded, stop counting. // When fully loaded, stop counting.
have_pending_loads_[static_cast<int>(MediaType::kSound)] = false; have_pending_loads_[static_cast<int>(AssetType::kSound)] = false;
} }
return total; return total;
} }
auto Media::GetDataPendingLoadCount() -> int { auto Assets::GetDataPendingLoadCount() -> int {
if (!have_pending_loads_[static_cast<int>(MediaType::kData)]) { if (!have_pending_loads_[static_cast<int>(AssetType::kData)]) {
return 0; return 0;
} }
MediaListsLock lock; AssetListLock lock;
int total = GetComponentPendingLoadCount(&datas_, MediaType::kData); int total = GetComponentPendingLoadCount(&datas_, AssetType::kData);
if (total == 0) { if (total == 0) {
// When fully loaded, stop counting. // When fully loaded, stop counting.
have_pending_loads_[static_cast<int>(MediaType::kData)] = false; have_pending_loads_[static_cast<int>(AssetType::kData)] = false;
} }
return total; return total;
} }
auto Media::GetCollideModelPendingLoadCount() -> int { auto Assets::GetCollideModelPendingLoadCount() -> int {
if (!have_pending_loads_[static_cast<int>(MediaType::kCollideModel)]) { if (!have_pending_loads_[static_cast<int>(AssetType::kCollideModel)]) {
return 0; return 0;
} }
MediaListsLock lock; AssetListLock lock;
int total = int total =
GetComponentPendingLoadCount(&collide_models_, MediaType::kCollideModel); GetComponentPendingLoadCount(&collide_models_, AssetType::kCollideModel);
if (total == 0) { if (total == 0) {
// When fully loaded, stop counting. // When fully loaded, stop counting.
have_pending_loads_[static_cast<int>(MediaType::kCollideModel)] = false; have_pending_loads_[static_cast<int>(AssetType::kCollideModel)] = false;
} }
return total; return total;
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
auto Media::GetGraphicalPendingLoadCount() -> int { auto Assets::GetGraphicalPendingLoadCount() -> int {
// Each of these calls lock the media-lists so we don't. // Each of these calls lock the asset-lists so we don't.
return GetModelPendingLoadCount() + GetTexturePendingLoadCount(); return GetModelPendingLoadCount() + GetTexturePendingLoadCount();
} }
auto Media::GetPendingLoadCount() -> int { auto Assets::GetPendingLoadCount() -> int {
// Each of these calls lock the media-lists so we don't. // Each of these calls lock the asset-lists so we don't.
return GetModelPendingLoadCount() + GetTexturePendingLoadCount() return GetModelPendingLoadCount() + GetTexturePendingLoadCount()
+ GetDataPendingLoadCount() + GetSoundPendingLoadCount() + GetDataPendingLoadCount() + GetSoundPendingLoadCount()
+ GetCollideModelPendingLoadCount(); + GetCollideModelPendingLoadCount();
} }
template <class T> template <class T>
auto Media::GetComponentPendingLoadCount( auto Assets::GetComponentPendingLoadCount(
std::unordered_map<std::string, Object::Ref<T> >* t_list, MediaType type) std::unordered_map<std::string, Object::Ref<T> >* t_list, AssetType type)
-> int { -> int {
assert(InLogicThread()); assert(InLogicThread());
assert(media_lists_locked_); assert(asset_lists_locked_);
int c = 0; int c = 0;
for (auto&& i : (*t_list)) { for (auto&& i : (*t_list)) {
if (i.second.exists()) { if (i.second.exists()) {
if (i.second->TryLock()) { if (i.second->TryLock()) {
MediaComponentData::LockGuard lock( AssetComponentData::LockGuard lock(
i.second.get(), MediaComponentData::LockGuard::Type::kInheritLock); i.second.get(), AssetComponentData::LockGuard::Type::kInheritLock);
if (!i.second->loaded()) { if (!i.second->loaded()) {
c++; c++;
} }
@ -731,26 +723,26 @@ auto Media::GetComponentPendingLoadCount(
} }
// Runs the pending loads that need to run from the audio thread. // Runs the pending loads that need to run from the audio thread.
auto Media::RunPendingAudioLoads() -> bool { auto Assets::RunPendingAudioLoads() -> bool {
assert(InAudioThread()); assert(InAudioThread());
return RunPendingLoadList(&pending_loads_sounds_); return RunPendingLoadList(&pending_loads_sounds_);
} }
// Runs the pending loads that need to run from the graphics thread. // Runs the pending loads that need to run from the graphics thread.
auto Media::RunPendingGraphicsLoads() -> bool { auto Assets::RunPendingGraphicsLoads() -> bool {
assert(InGraphicsThread()); assert(InGraphicsThread());
return RunPendingLoadList(&pending_loads_graphics_); return RunPendingLoadList(&pending_loads_graphics_);
} }
// Runs the pending loads that run in the main thread. Also clears the list of // Runs the pending loads that run in the main thread. Also clears the list of
// done loads. // done loads.
auto Media::RunPendingLoadsLogicThread() -> bool { auto Assets::RunPendingLoadsLogicThread() -> bool {
assert(InLogicThread()); assert(InLogicThread());
return RunPendingLoadList(&pending_loads_other_); return RunPendingLoadList(&pending_loads_other_);
} }
template <class T> template <class T>
auto Media::RunPendingLoadList(std::vector<Object::Ref<T>*>* c_list) -> bool { auto Assets::RunPendingLoadList(std::vector<Object::Ref<T>*>* c_list) -> bool {
bool flush = false; bool flush = false;
millisecs_t starttime = GetRealTime(); millisecs_t starttime = GetRealTime();
@ -818,40 +810,40 @@ auto Media::RunPendingLoadList(std::vector<Object::Ref<T>*>* c_list) -> bool {
} }
} }
// if we dumped anything on the pending loads done list, shake the game thread // if we dumped anything on the pending loads done list, shake the logic
// to tell it to kill the reference.. // thread to tell it to kill the reference..
if (!l_finished.empty()) { if (!l_finished.empty()) {
assert(g_game); assert(g_logic);
g_game->PushHavePendingLoadsDoneCall(); g_logic->PushHavePendingLoadsDoneCall();
} }
return (!l.empty()); return (!l.empty());
} }
void Media::Prune(int level) { void Assets::Prune(int level) {
assert(InLogicThread()); assert(InLogicThread());
millisecs_t current_time = GetRealTime(); millisecs_t current_time = GetRealTime();
// need lists locked while accessing/modifying them // need lists locked while accessing/modifying them
MediaListsLock lock; AssetListLock lock;
// we can specify level for more aggressive pruning (during memory warnings // we can specify level for more aggressive pruning (during memory warnings
// and whatnot) // and whatnot)
millisecs_t standard_media_prune_time = STANDARD_MEDIA_PRUNE_TIME; millisecs_t standard_asset_prune_time = STANDARD_ASSET_PRUNE_TIME;
millisecs_t text_texture_prune_time = TEXT_TEXTURE_PRUNE_TIME; millisecs_t text_texture_prune_time = TEXT_TEXTURE_PRUNE_TIME;
millisecs_t qr_texture_prune_time = QR_TEXTURE_PRUNE_TIME; millisecs_t qr_texture_prune_time = QR_TEXTURE_PRUNE_TIME;
switch (level) { switch (level) {
case 1: case 1:
standard_media_prune_time = 120000; // 2 min standard_asset_prune_time = 120000; // 2 min
text_texture_prune_time = 1000; // 1 sec text_texture_prune_time = 1000; // 1 sec
qr_texture_prune_time = 1000; // 1 sec qr_texture_prune_time = 1000; // 1 sec
break; break;
case 2: case 2:
standard_media_prune_time = 30000; // 30 sec standard_asset_prune_time = 30000; // 30 sec
text_texture_prune_time = 1000; // 1 sec text_texture_prune_time = 1000; // 1 sec
qr_texture_prune_time = 1000; // 1 sec qr_texture_prune_time = 1000; // 1 sec
break; break;
case 3: case 3:
standard_media_prune_time = 5000; // 5 sec standard_asset_prune_time = 5000; // 5 sec
text_texture_prune_time = 1000; // 1 sec text_texture_prune_time = 1000; // 1 sec
qr_texture_prune_time = 1000; // 1 sec qr_texture_prune_time = 1000; // 1 sec
break; break;
@ -859,11 +851,11 @@ void Media::Prune(int level) {
break; break;
} }
std::vector<Object::Ref<MediaComponentData>*> graphics_thread_unloads; std::vector<Object::Ref<AssetComponentData>*> graphics_thread_unloads;
std::vector<Object::Ref<MediaComponentData>*> audio_thread_unloads; std::vector<Object::Ref<AssetComponentData>*> audio_thread_unloads;
#if SHOW_PRUNING_INFO #if SHOW_PRUNING_INFO
assert(media_lists_locked_); assert(asset_lists_locked_);
int old_texture_count = textures_.size(); int old_texture_count = textures_.size();
int old_text_texture_count = text_textures_.size(); int old_text_texture_count = text_textures_.size();
int old_qr_texture_count = qr_textures_.size(); int old_qr_texture_count = qr_textures_.size();
@ -873,13 +865,13 @@ void Media::Prune(int level) {
#endif // SHOW_PRUNING_INFO #endif // SHOW_PRUNING_INFO
// prune textures.. // prune textures..
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = textures_.begin(); i != textures_.end();) { for (auto i = textures_.begin(); i != textures_.end();) {
TextureData* texture_data = i->second.get(); TextureData* texture_data = i->second.get();
// attempt to prune if there are no references remaining except our own and // attempt to prune if there are no references remaining except our own and
// its been a while since it was used // its been a while since it was used
if (current_time - texture_data->last_used_time() if (current_time - texture_data->last_used_time()
> standard_media_prune_time > standard_asset_prune_time
&& (texture_data->object_strong_ref_count() <= 1)) { && (texture_data->object_strong_ref_count() <= 1)) {
// if its preloaded/loaded we need to ask the graphics thread to unload it // if its preloaded/loaded we need to ask the graphics thread to unload it
// first // first
@ -887,7 +879,7 @@ void Media::Prune(int level) {
// allocate a reference to keep this texture_data alive while the unload // allocate a reference to keep this texture_data alive while the unload
// is happening // is happening
graphics_thread_unloads.push_back( graphics_thread_unloads.push_back(
new Object::Ref<MediaComponentData>(texture_data)); new Object::Ref<AssetComponentData>(texture_data));
auto i_next = i; auto i_next = i;
i_next++; i_next++;
textures_.erase(i); textures_.erase(i);
@ -901,7 +893,7 @@ void Media::Prune(int level) {
// prune text-textures more aggressively since we may generate lots of them // prune text-textures more aggressively since we may generate lots of them
// FIXME - we may want to prune based on total number of these instead of // FIXME - we may want to prune based on total number of these instead of
// time.. // time..
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = text_textures_.begin(); i != text_textures_.end();) { for (auto i = text_textures_.begin(); i != text_textures_.end();) {
TextureData* texture_data = i->second.get(); TextureData* texture_data = i->second.get();
// attempt to prune if there are no references remaining except our own and // attempt to prune if there are no references remaining except our own and
@ -914,7 +906,7 @@ void Media::Prune(int level) {
// allocate a reference to keep this texture_data alive while the unload // allocate a reference to keep this texture_data alive while the unload
// is happening // is happening
graphics_thread_unloads.push_back( graphics_thread_unloads.push_back(
new Object::Ref<MediaComponentData>(texture_data)); new Object::Ref<AssetComponentData>(texture_data));
auto i_next = i; auto i_next = i;
i_next++; i_next++;
text_textures_.erase(i); text_textures_.erase(i);
@ -926,7 +918,7 @@ void Media::Prune(int level) {
} }
// prune textures // prune textures
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = qr_textures_.begin(); i != qr_textures_.end();) { for (auto i = qr_textures_.begin(); i != qr_textures_.end();) {
TextureData* texture_data = i->second.get(); TextureData* texture_data = i->second.get();
// attempt to prune if there are no references remaining except our own and // attempt to prune if there are no references remaining except our own and
@ -939,7 +931,7 @@ void Media::Prune(int level) {
// allocate a reference to keep this texture_data alive while the unload // allocate a reference to keep this texture_data alive while the unload
// is happening // is happening
graphics_thread_unloads.push_back( graphics_thread_unloads.push_back(
new Object::Ref<MediaComponentData>(texture_data)); new Object::Ref<AssetComponentData>(texture_data));
auto i_next = i; auto i_next = i;
i_next++; i_next++;
qr_textures_.erase(i); qr_textures_.erase(i);
@ -951,12 +943,12 @@ void Media::Prune(int level) {
} }
// prune models.. // prune models..
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = models_.begin(); i != models_.end();) { for (auto i = models_.begin(); i != models_.end();) {
ModelData* model_data = i->second.get(); ModelData* model_data = i->second.get();
// attempt to prune if there are no references remaining except our own and // attempt to prune if there are no references remaining except our own and
// its been a while since it was used // its been a while since it was used
if (current_time - model_data->last_used_time() > standard_media_prune_time if (current_time - model_data->last_used_time() > standard_asset_prune_time
&& (model_data->object_strong_ref_count() <= 1)) { && (model_data->object_strong_ref_count() <= 1)) {
// if its preloaded/loaded we need to ask the graphics thread to unload it // if its preloaded/loaded we need to ask the graphics thread to unload it
// first // first
@ -964,7 +956,7 @@ void Media::Prune(int level) {
// allocate a reference to keep this model_data alive while the unload // allocate a reference to keep this model_data alive while the unload
// is happening // is happening
graphics_thread_unloads.push_back( graphics_thread_unloads.push_back(
new Object::Ref<MediaComponentData>(model_data)); new Object::Ref<AssetComponentData>(model_data));
auto i_next = i; auto i_next = i;
i_next++; i_next++;
models_.erase(i); models_.erase(i);
@ -976,16 +968,16 @@ void Media::Prune(int level) {
} }
// Prune collide-models. // Prune collide-models.
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = collide_models_.begin(); i != collide_models_.end();) { for (auto i = collide_models_.begin(); i != collide_models_.end();) {
CollideModelData* collide_model_data = i->second.get(); CollideModelData* collide_model_data = i->second.get();
// attempt to prune if there are no references remaining except our own and // attempt to prune if there are no references remaining except our own and
// its been a while since it was used (unlike other media we never prune // its been a while since it was used (unlike other assets we never prune
// these if there's still references to them // these if there's still references to them
if (current_time - collide_model_data->last_used_time() if (current_time - collide_model_data->last_used_time()
> standard_media_prune_time > standard_asset_prune_time
&& (collide_model_data->object_strong_ref_count() <= 1)) { && (collide_model_data->object_strong_ref_count() <= 1)) {
// we can unload it immediately since that happens in the game thread... // we can unload it immediately since that happens in the logic thread...
collide_model_data->Unload(); collide_model_data->Unload();
auto i_next = i; auto i_next = i;
++i_next; ++i_next;
@ -1001,13 +993,13 @@ void Media::Prune(int level) {
// sounds are still in active use by OpenAL and ensure references exist for // sounds are still in active use by OpenAL and ensure references exist for
// them somewhere while that is the case // them somewhere while that is the case
if (explicit_bool(false)) { if (explicit_bool(false)) {
assert(media_lists_locked_); assert(asset_lists_locked_);
for (auto i = sounds_.begin(); i != sounds_.end();) { for (auto i = sounds_.begin(); i != sounds_.end();) {
SoundData* sound_data = i->second.get(); SoundData* sound_data = i->second.get();
// Attempt to prune if there are no references remaining except our own // Attempt to prune if there are no references remaining except our own
// and its been a while since it was used. // and its been a while since it was used.
if (current_time - sound_data->last_used_time() if (current_time - sound_data->last_used_time()
> standard_media_prune_time > standard_asset_prune_time
&& (sound_data->object_strong_ref_count() <= 1)) { && (sound_data->object_strong_ref_count() <= 1)) {
// If its preloaded/loaded we need to ask the graphics thread to unload // If its preloaded/loaded we need to ask the graphics thread to unload
// it first. // it first.
@ -1015,7 +1007,7 @@ void Media::Prune(int level) {
// Allocate a reference to keep this sound_data alive while the unload // Allocate a reference to keep this sound_data alive while the unload
// is happening. // is happening.
audio_thread_unloads.push_back( audio_thread_unloads.push_back(
new Object::Ref<MediaComponentData>(sound_data)); new Object::Ref<AssetComponentData>(sound_data));
auto i_next = i; auto i_next = i;
i_next++; i_next++;
sounds_.erase(i); sounds_.erase(i);
@ -1035,7 +1027,7 @@ void Media::Prune(int level) {
} }
#if SHOW_PRUNING_INFO #if SHOW_PRUNING_INFO
assert(media_lists_locked_); assert(asset_lists_locked_);
if (textures_.size() != old_texture_count) { if (textures_.size() != old_texture_count) {
Log("Textures pruned from " + std::to_string(old_texture_count) + " to " Log("Textures pruned from " + std::to_string(old_texture_count) + " to "
+ std::to_string(textures_.size())); + std::to_string(textures_.size()));
@ -1063,7 +1055,7 @@ void Media::Prune(int level) {
#endif // SHOW_PRUNING_INFO #endif // SHOW_PRUNING_INFO
} }
auto Media::FindMediaFile(FileType type, const std::string& name) auto Assets::FindAssetFile(FileType type, const std::string& name)
-> std::string { -> std::string {
std::string file_out; std::string file_out;
@ -1133,9 +1125,9 @@ auto Media::FindMediaFile(FileType type, const std::string& name)
break; break;
} }
const std::vector<std::string>& media_paths_used = media_paths_; const std::vector<std::string>& asset_paths_used = asset_paths_;
for (auto&& i : media_paths_used) { for (auto&& i : asset_paths_used) {
struct BA_STAT stats {}; struct BA_STAT stats {};
file_out = i + "/" + prefix + name + ext; // NOLINT file_out = i + "/" + prefix + name + ext; // NOLINT
int result; int result;
@ -1159,27 +1151,29 @@ auto Media::FindMediaFile(FileType type, const std::string& name)
// We wanna fail gracefully for some types. // We wanna fail gracefully for some types.
if (type == FileType::kSound && name != "blank") { if (type == FileType::kSound && name != "blank") {
Log("Unable to load audio: '" + name + "'; trying fallback..."); Log(LogLevel::kError,
return FindMediaFile(type, "blank"); "Unable to load audio: '" + name + "'; trying fallback...");
return FindAssetFile(type, "blank");
} else if (type == FileType::kTexture && name != "white") { } else if (type == FileType::kTexture && name != "white") {
Log("Unable to load texture: '" + name + "'; trying fallback..."); Log(LogLevel::kError,
return FindMediaFile(type, "white"); "Unable to load texture: '" + name + "'; trying fallback...");
return FindAssetFile(type, "white");
} }
throw Exception("Can't find media: \"" + name + "\""); throw Exception("Can't find asset: \"" + name + "\"");
// return file_out; // return file_out;
} }
void Media::AddPendingLoad(Object::Ref<MediaComponentData>* c) { void Assets::AddPendingLoad(Object::Ref<AssetComponentData>* c) {
switch ((**c).GetMediaType()) { switch ((**c).GetAssetType()) {
case MediaType::kTexture: case AssetType::kTexture:
case MediaType::kModel: { case AssetType::kModel: {
// Tell the graphics thread there's pending loads... // Tell the graphics thread there's pending loads...
std::scoped_lock lock(pending_load_list_mutex_); std::scoped_lock lock(pending_load_list_mutex_);
pending_loads_graphics_.push_back(c); pending_loads_graphics_.push_back(c);
break; break;
} }
case MediaType::kSound: { case AssetType::kSound: {
// Tell the audio thread there's pending loads. // Tell the audio thread there's pending loads.
{ {
std::scoped_lock lock(pending_load_list_mutex_); std::scoped_lock lock(pending_load_list_mutex_);
@ -1189,69 +1183,56 @@ void Media::AddPendingLoad(Object::Ref<MediaComponentData>* c) {
break; break;
} }
default: { default: {
// Tell the game thread there's pending loads. // Tell the logic thread there's pending loads.
{ {
std::scoped_lock lock(pending_load_list_mutex_); std::scoped_lock lock(pending_load_list_mutex_);
pending_loads_other_.push_back(c); pending_loads_other_.push_back(c);
} }
g_game->PushHavePendingLoadsCall(); g_logic->PushHavePendingLoadsCall();
break; break;
} }
} }
} }
void Media::ClearPendingLoadsDoneList() { void Assets::ClearPendingLoadsDoneList() {
assert(InLogicThread()); assert(InLogicThread());
std::scoped_lock lock(pending_load_list_mutex_); std::scoped_lock lock(pending_load_list_mutex_);
// Our explicitly-allocated reference pointer has made it back to us here in // Our explicitly-allocated reference pointer has made it back to us here in
// the game thread. // the logic thread.
// We can now kill the reference knowing that it's safe for this component // We can now kill the reference knowing that it's safe for this component
// to die at any time (anyone needing it to be alive now should be holding a // to die at any time (anyone needing it to be alive now should be holding a
// reference themselves). // reference themselves).
for (Object::Ref<MediaComponentData>* i : pending_loads_done_) { for (Object::Ref<AssetComponentData>* i : pending_loads_done_) {
delete i; delete i;
} }
pending_loads_done_.clear(); pending_loads_done_.clear();
} }
void Media::PreloadRunnable::Run() { void Assets::AddPackage(const std::string& name, const std::string& path) {
assert(InMediaThread());
// add our pointer to one of the preload lists and shake our preload thread to
// wake it up
if ((**c).GetMediaType() == MediaType::kSound) {
g_media_server->pending_preloads_audio_.push_back(c);
} else {
g_media_server->pending_preloads_.push_back(c);
}
g_media_server->process_timer_->SetLength(0);
}
void Media::AddPackage(const std::string& name, const std::string& path) {
// we don't protect package-path access so make sure its always from here.. // we don't protect package-path access so make sure its always from here..
assert(InLogicThread()); assert(InLogicThread());
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
if (packages_.find(name) != packages_.end()) { if (packages_.find(name) != packages_.end()) {
Log("WARNING: adding duplicate package: '" + name + "'"); Log(LogLevel::kWarning, "adding duplicate package: '" + name + "'");
} }
#endif // BA_DEBUG_BUILD #endif // BA_DEBUG_BUILD
packages_[name] = path; packages_[name] = path;
} }
Media::MediaListsLock::MediaListsLock() { Assets::AssetListLock::AssetListLock() {
BA_DEBUG_FUNCTION_TIMER_BEGIN(); BA_DEBUG_FUNCTION_TIMER_BEGIN();
g_media->media_lists_mutex_.lock(); g_assets->asset_lists_mutex_.lock();
assert(!g_media->media_lists_locked_); assert(!g_assets->asset_lists_locked_);
g_media->media_lists_locked_ = true; g_assets->asset_lists_locked_ = true;
BA_DEBUG_FUNCTION_TIMER_END_THREAD(20); BA_DEBUG_FUNCTION_TIMER_END_THREAD(20);
} }
Media::MediaListsLock::~MediaListsLock() { Assets::AssetListLock::~AssetListLock() {
assert(g_media->media_lists_locked_); assert(g_assets->asset_lists_locked_);
g_media->media_lists_locked_ = false; g_assets->asset_lists_locked_ = false;
g_media->media_lists_mutex_.unlock(); g_assets->asset_lists_mutex_.unlock();
} }
} // namespace ballistica } // namespace ballistica

View File

@ -1,29 +1,26 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_MEDIA_H_ #ifndef BALLISTICA_ASSETS_ASSETS_H_
#define BALLISTICA_MEDIA_MEDIA_H_ #define BALLISTICA_ASSETS_ASSETS_H_
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "ballistica/core/context.h"
#include "ballistica/core/object.h" #include "ballistica/core/object.h"
#include "ballistica/generic/runnable.h"
namespace ballistica { namespace ballistica {
/// Global media wrangling class. /// Global assets wrangling class.
class Media { class Assets {
public: public:
static void Init(); Assets();
~Media();
/// Handy function to try to return a bit of media from a std::unordered_map /// Handy function to try to return an asset from a std::unordered_map
/// of weak-refs, loading/adding it if need be. /// of weak-refs, loading/adding it if need be.
template <typename T> template <typename T>
static auto GetMedia( static auto GetAsset(
std::unordered_map<std::string, Object::WeakRef<T> >* list, std::unordered_map<std::string, Object::WeakRef<T> >* list,
const std::string& name, Scene* scene) -> Object::Ref<T> { const std::string& name, Scene* scene) -> Object::Ref<T> {
assert(InLogicThread()); assert(InLogicThread());
@ -43,10 +40,10 @@ class Media {
} }
} }
void AddPackage(const std::string& name, const std::string& path); auto AddPackage(const std::string& name, const std::string& path) -> void;
void Prune(int level = 0); auto Prune(int level = 0) -> void;
/// Finish loading any media that has been preloaded but still needs to be /// Finish loading any assets that have been preloaded but still need to be
/// loaded by the proper thread. /// loaded by the proper thread.
auto RunPendingLoadsLogicThread() -> bool; auto RunPendingLoadsLogicThread() -> bool;
@ -55,26 +52,25 @@ class Media {
/// Return true if graphics loads remain to be done. /// Return true if graphics loads remain to be done.
auto RunPendingGraphicsLoads() -> bool; auto RunPendingGraphicsLoads() -> bool;
void ClearPendingLoadsDoneList(); auto ClearPendingLoadsDoneList() -> void;
template <class T> template <class T>
auto RunPendingLoadList(std::vector<Object::Ref<T>*>* cList) -> bool; auto RunPendingLoadList(std::vector<Object::Ref<T>*>* cList) -> bool;
/// This function takes a newly allocated pointer which /// This function takes a newly allocated pointer which
/// is deleted once the load is completed. /// is deleted once the load is completed.
void AddPendingLoad(Object::Ref<MediaComponentData>* c); auto AddPendingLoad(Object::Ref<AssetComponentData>* c) -> void;
struct PreloadRunnable;
enum class FileType { kModel, kCollisionModel, kTexture, kSound, kData }; enum class FileType { kModel, kCollisionModel, kTexture, kSound, kData };
auto FindMediaFile(FileType fileType, const std::string& file_in) auto FindAssetFile(FileType fileType, const std::string& file_in)
-> std::string; -> std::string;
/// Unload renderer-specific bits only (gl display lists, etc) - used when /// Unload renderer-specific bits only (gl display lists, etc) - used when
/// recreating/adjusting the renderer. /// recreating/adjusting the renderer.
void UnloadRendererBits(bool textures, bool models); auto UnloadRendererBits(bool textures, bool models) -> void;
/// Should be called from the game thread after UnloadRendererBits(); /// Should be called from the logic thread after UnloadRendererBits();
/// kicks off bg loads for all existing unloaded media. /// kicks off bg loads for all existing unloaded assets.
void MarkAllMediaForLoad(); auto MarkAllAssetsForLoad() -> void;
void PrintLoadInfo(); auto PrintLoadInfo() -> void;
auto GetModelPendingLoadCount() -> int; auto GetModelPendingLoadCount() -> int;
auto GetTexturePendingLoadCount() -> int; auto GetTexturePendingLoadCount() -> int;
@ -89,13 +85,13 @@ class Media {
auto GetPendingLoadCount() -> int; auto GetPendingLoadCount() -> int;
/// You must hold one of these locks while calling Get*Data() below. /// You must hold one of these locks while calling Get*Data() below.
class MediaListsLock { class AssetListLock {
public: public:
MediaListsLock(); AssetListLock();
~MediaListsLock(); ~AssetListLock();
}; };
/// Load/cache media (make sure you hold a MediaListsLock). /// Load/cache assets (make sure you hold a AssetListLock).
auto GetTextureData(const std::string& file_name) -> Object::Ref<TextureData>; auto GetTextureData(const std::string& file_name) -> Object::Ref<TextureData>;
auto GetTextureData(TextPacker* packer) -> Object::Ref<TextureData>; auto GetTextureData(TextPacker* packer) -> Object::Ref<TextureData>;
auto GetTextureDataQRCode(const std::string& file_name) auto GetTextureDataQRCode(const std::string& file_name)
@ -110,32 +106,32 @@ class Media {
// Get system assets. // Get system assets.
auto GetTexture(SystemTextureID id) -> TextureData* { auto GetTexture(SystemTextureID id) -> TextureData* {
BA_PRECONDITION_FATAL(system_media_loaded_); // Revert to assert later. BA_PRECONDITION_FATAL(system_assets_loaded_); // Revert to assert later.
assert(InLogicThread()); assert(InLogicThread());
assert(static_cast<size_t>(id) < system_textures_.size()); assert(static_cast<size_t>(id) < system_textures_.size());
return system_textures_[static_cast<int>(id)].get(); return system_textures_[static_cast<int>(id)].get();
} }
auto GetCubeMapTexture(SystemCubeMapTextureID id) -> TextureData* { auto GetCubeMapTexture(SystemCubeMapTextureID id) -> TextureData* {
BA_PRECONDITION_FATAL(system_media_loaded_); // Revert to assert later. BA_PRECONDITION_FATAL(system_assets_loaded_); // Revert to assert later.
assert(InLogicThread()); assert(InLogicThread());
assert(static_cast<size_t>(id) < system_cube_map_textures_.size()); assert(static_cast<size_t>(id) < system_cube_map_textures_.size());
return system_cube_map_textures_[static_cast<int>(id)].get(); return system_cube_map_textures_[static_cast<int>(id)].get();
} }
auto GetSound(SystemSoundID id) -> SoundData* { auto GetSound(SystemSoundID id) -> SoundData* {
BA_PRECONDITION_FATAL(system_media_loaded_); // Revert to assert later. BA_PRECONDITION_FATAL(system_assets_loaded_); // Revert to assert later.
assert(InLogicThread()); assert(InLogicThread());
assert(static_cast<size_t>(id) < system_sounds_.size()); assert(static_cast<size_t>(id) < system_sounds_.size());
return system_sounds_[static_cast<int>(id)].get(); return system_sounds_[static_cast<int>(id)].get();
} }
auto GetModel(SystemModelID id) -> ModelData* { auto GetModel(SystemModelID id) -> ModelData* {
BA_PRECONDITION_FATAL(system_media_loaded_); // Revert to assert later. BA_PRECONDITION_FATAL(system_assets_loaded_); // Revert to assert later.
assert(InLogicThread()); assert(InLogicThread());
assert(static_cast<size_t>(id) < system_models_.size()); assert(static_cast<size_t>(id) < system_models_.size());
return system_models_[static_cast<int>(id)].get(); return system_models_[static_cast<int>(id)].get();
} }
/// Load up hard-coded media for interface, etc. /// Load up hard-coded assets for interface, etc.
void LoadSystemMedia(); auto LoadSystemAssets() -> void;
auto total_model_count() const -> uint32_t { auto total_model_count() const -> uint32_t {
return static_cast<uint32_t>(models_.size()); return static_cast<uint32_t>(models_.size());
@ -150,24 +146,19 @@ class Media {
auto total_collide_model_count() const -> uint32_t { auto total_collide_model_count() const -> uint32_t {
return static_cast<uint32_t>(collide_models_.size()); return static_cast<uint32_t>(collide_models_.size());
} }
struct PreloadRunnable : public Runnable {
explicit PreloadRunnable(Object::Ref<MediaComponentData>* c_in) : c(c_in) {}
void Run() override;
Object::Ref<MediaComponentData>* c;
};
private: private:
Media(); static auto MarkComponentForLoad(AssetComponentData* c) -> void;
static void MarkComponentForLoad(MediaComponentData* c); auto LoadSystemTexture(SystemTextureID id, const char* name) -> void;
void LoadSystemTexture(SystemTextureID id, const char* name); auto LoadSystemCubeMapTexture(SystemCubeMapTextureID id, const char* name)
void LoadSystemCubeMapTexture(SystemCubeMapTextureID id, const char* name); -> void;
void LoadSystemSound(SystemSoundID id, const char* name); auto LoadSystemSound(SystemSoundID id, const char* name) -> void;
void LoadSystemData(SystemDataID id, const char* name); auto LoadSystemData(SystemDataID id, const char* name) -> void;
void LoadSystemModel(SystemModelID id, const char* name); auto LoadSystemModel(SystemModelID id, const char* name) -> void;
template <class T> template <class T>
auto GetComponentPendingLoadCount( auto GetComponentPendingLoadCount(
std::unordered_map<std::string, Object::Ref<T> >* t_list, MediaType type) std::unordered_map<std::string, Object::Ref<T> >* t_list, AssetType type)
-> int; -> int;
template <class T> template <class T>
@ -176,26 +167,26 @@ class Media {
std::unordered_map<std::string, Object::Ref<T> >* c_list) std::unordered_map<std::string, Object::Ref<T> >* c_list)
-> Object::Ref<T>; -> Object::Ref<T>;
std::vector<std::string> media_paths_; std::vector<std::string> asset_paths_;
bool have_pending_loads_[static_cast<int>(MediaType::kLast)]{}; bool have_pending_loads_[static_cast<int>(AssetType::kLast)]{};
std::unordered_map<std::string, std::string> packages_; std::unordered_map<std::string, std::string> packages_;
// For use by MediaListsLock; don't manually acquire // For use by AssetListLock; don't manually acquire
std::mutex media_lists_mutex_; std::mutex asset_lists_mutex_;
// Will be true while a MediaListsLock exists. Good to debug-verify this // Will be true while a AssetListLock exists. Good to debug-verify this
// during any media list access. // during any asset list access.
bool media_lists_locked_{}; bool asset_lists_locked_{};
// 'hard-wired' internal media // 'hard-wired' internal assets
bool system_media_loaded_{}; bool system_assets_loaded_{};
std::vector<Object::Ref<TextureData> > system_textures_; std::vector<Object::Ref<TextureData> > system_textures_;
std::vector<Object::Ref<TextureData> > system_cube_map_textures_; std::vector<Object::Ref<TextureData> > system_cube_map_textures_;
std::vector<Object::Ref<SoundData> > system_sounds_; std::vector<Object::Ref<SoundData> > system_sounds_;
std::vector<Object::Ref<DataData> > system_datas_; std::vector<Object::Ref<DataData> > system_datas_;
std::vector<Object::Ref<ModelData> > system_models_; std::vector<Object::Ref<ModelData> > system_models_;
// All existing media by filename (including internal). // All existing assets by filename (including internal).
std::unordered_map<std::string, Object::Ref<TextureData> > textures_; std::unordered_map<std::string, Object::Ref<TextureData> > textures_;
std::unordered_map<std::string, Object::Ref<TextureData> > text_textures_; std::unordered_map<std::string, Object::Ref<TextureData> > text_textures_;
std::unordered_map<std::string, Object::Ref<TextureData> > qr_textures_; std::unordered_map<std::string, Object::Ref<TextureData> > qr_textures_;
@ -207,13 +198,13 @@ class Media {
// Components that have been preloaded but need to be loaded. // Components that have been preloaded but need to be loaded.
std::mutex pending_load_list_mutex_; std::mutex pending_load_list_mutex_;
std::vector<Object::Ref<MediaComponentData>*> pending_loads_graphics_; std::vector<Object::Ref<AssetComponentData>*> pending_loads_graphics_;
std::vector<Object::Ref<MediaComponentData>*> pending_loads_sounds_; std::vector<Object::Ref<AssetComponentData>*> pending_loads_sounds_;
std::vector<Object::Ref<MediaComponentData>*> pending_loads_datas_; std::vector<Object::Ref<AssetComponentData>*> pending_loads_datas_;
std::vector<Object::Ref<MediaComponentData>*> pending_loads_other_; std::vector<Object::Ref<AssetComponentData>*> pending_loads_other_;
std::vector<Object::Ref<MediaComponentData>*> pending_loads_done_; std::vector<Object::Ref<AssetComponentData>*> pending_loads_done_;
}; };
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_MEDIA_H_ #endif // BALLISTICA_ASSETS_ASSETS_H_

View File

@ -1,34 +1,54 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/media_server.h" #include "ballistica/assets/assets_server.h"
#include "ballistica/assets/assets.h"
#include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/generic/huffman.h" #include "ballistica/generic/huffman.h"
#include "ballistica/generic/timer.h" #include "ballistica/generic/timer.h"
#include "ballistica/generic/utils.h" #include "ballistica/generic/utils.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/media/data/media_component_data.h"
#include "ballistica/media/media.h"
namespace ballistica { namespace ballistica {
MediaServer::MediaServer(Thread* thread) AssetsServer::AssetsServer() {
: thread_(thread), // We're a singleton; make sure we don't already exist.
writing_replay_(false), assert(g_assets_server == nullptr);
replay_message_bytes_(0),
replays_broken_(false),
replay_out_file_(nullptr) {
assert(g_media_server == nullptr);
g_media_server = this;
// get our thread to give us periodic processing time... // Spin up our thread.
process_timer_ = this->thread()->NewTimer( thread_ = new Thread(ThreadTag::kAssets);
1000, true, NewLambdaRunnable([this] { Process(); })); g_app->pausable_threads.push_back(thread_);
} }
MediaServer::~MediaServer() = default; auto AssetsServer::OnAppStart() -> void {
thread_->PushCallSynchronous([this] { OnAppStartInThread(); });
}
void MediaServer::PushBeginWriteReplayCall() { auto AssetsServer::OnAppStartInThread() -> void {
assert(InAssetsThread());
// get our thread to give us periodic processing time...
process_timer_ =
thread()->NewTimer(1000, true, NewLambdaRunnable([this] { Process(); }));
}
auto AssetsServer::PushPendingPreload(
Object::Ref<AssetComponentData>* asset_ref_ptr) -> void {
thread()->PushCall([this, asset_ref_ptr] {
assert(InAssetsThread());
// Add our pointer to one of the preload lists and shake our preload thread
// to wake it up
if ((**asset_ref_ptr).GetAssetType() == AssetType::kSound) {
pending_preloads_audio_.push_back(asset_ref_ptr);
} else {
pending_preloads_.push_back(asset_ref_ptr);
}
process_timer_->SetLength(0);
});
}
void AssetsServer::PushBeginWriteReplayCall() {
thread()->PushCall([this] { thread()->PushCall([this] {
if (replays_broken_) { if (replays_broken_) {
return; return;
@ -37,7 +57,8 @@ void MediaServer::PushBeginWriteReplayCall() {
// we only allow writing one replay at once; make sure that's actually the // we only allow writing one replay at once; make sure that's actually the
// case // case
if (writing_replay_) { if (writing_replay_) {
Log("MediaServer got BeginWriteReplayCall while already writing"); Log(LogLevel::kError,
"AssetsServer got BeginWriteReplayCall while already writing");
WriteReplayMessages(); WriteReplayMessages();
if (replay_out_file_) { if (replay_out_file_) {
fclose(replay_out_file_); fclose(replay_out_file_);
@ -56,7 +77,8 @@ void MediaServer::PushBeginWriteReplayCall() {
replay_bytes_written_ = 0; replay_bytes_written_ = 0;
if (!replay_out_file_) { if (!replay_out_file_) {
Log("ERROR: unable to open output-stream file: '" + file_path + "'"); Log(LogLevel::kError,
"unable to open output-stream file: '" + file_path + "'");
} else { } else {
// write file id and protocol-version // write file id and protocol-version
// NOTE - we always write replays in our host protocol version // NOTE - we always write replays in our host protocol version
@ -67,19 +89,20 @@ void MediaServer::PushBeginWriteReplayCall() {
|| (fwrite(&version, sizeof(version), 1, replay_out_file_) != 1)) { || (fwrite(&version, sizeof(version), 1, replay_out_file_) != 1)) {
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
Log("error writing replay file header: " Log(LogLevel::kError, "error writing replay file header: "
+ g_platform->GetErrnoString()); + g_platform->GetErrnoString());
} }
replay_bytes_written_ = 5; replay_bytes_written_ = 5;
} }
// trigger our process timer to go off immediately // trigger our process timer to go off immediately
// (we may need to wake it up) // (we may need to wake it up)
g_media_server->process_timer_->SetLength(0); g_assets_server->process_timer_->SetLength(0);
}); });
} }
void MediaServer::PushAddMessageToReplayCall(const std::vector<uint8_t>& data) { void AssetsServer::PushAddMessageToReplayCall(
const std::vector<uint8_t>& data) {
thread()->PushCall([this, data] { thread()->PushCall([this, data] {
if (replays_broken_) { if (replays_broken_) {
return; return;
@ -87,7 +110,8 @@ void MediaServer::PushAddMessageToReplayCall(const std::vector<uint8_t>& data) {
// sanity check.. // sanity check..
if (!writing_replay_) { if (!writing_replay_) {
Log("MediaServer got AddMessageToReplayCall while not writing replay"); Log(LogLevel::kError,
"AssetsServer got AddMessageToReplayCall while not writing replay");
replays_broken_ = true; replays_broken_ = true;
return; return;
} }
@ -97,7 +121,8 @@ void MediaServer::PushAddMessageToReplayCall(const std::vector<uint8_t>& data) {
// if we've got too much data built up (lets go with 10 megs for now), // if we've got too much data built up (lets go with 10 megs for now),
// abort // abort
if (replay_message_bytes_ > 10000000) { if (replay_message_bytes_ > 10000000) {
Log("replay output buffer exceeded 10 megs; aborting replay"); Log(LogLevel::kError,
"replay output buffer exceeded 10 megs; aborting replay");
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
replay_message_bytes_ = 0; replay_message_bytes_ = 0;
@ -110,7 +135,7 @@ void MediaServer::PushAddMessageToReplayCall(const std::vector<uint8_t>& data) {
}); });
} }
void MediaServer::PushEndWriteReplayCall() { void AssetsServer::PushEndWriteReplayCall() {
thread()->PushCall([this] { thread()->PushCall([this] {
if (replays_broken_) { if (replays_broken_) {
return; return;
@ -118,7 +143,7 @@ void MediaServer::PushEndWriteReplayCall() {
// sanity check.. // sanity check..
if (!writing_replay_) { if (!writing_replay_) {
Log("_finishWritingReplay called while not writing"); Log(LogLevel::kError, "_finishWritingReplay called while not writing");
replays_broken_ = true; replays_broken_ = true;
return; return;
} }
@ -134,7 +159,7 @@ void MediaServer::PushEndWriteReplayCall() {
}); });
} }
void MediaServer::WriteReplayMessages() { void AssetsServer::WriteReplayMessages() {
if (replay_out_file_) { if (replay_out_file_) {
for (auto&& i : replay_messages_) { for (auto&& i : replay_messages_) {
std::vector<uint8_t> data_compressed = g_utils->huffman()->compress(i); std::vector<uint8_t> data_compressed = g_utils->huffman()->compress(i);
@ -155,7 +180,8 @@ void MediaServer::WriteReplayMessages() {
if (fwrite(&len8, 1, 1, replay_out_file_) != 1) { if (fwrite(&len8, 1, 1, replay_out_file_) != 1) {
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
Log("error writing replay file: " + g_platform->GetErrnoString()); Log(LogLevel::kError,
"error writing replay file: " + g_platform->GetErrnoString());
return; return;
} }
} }
@ -166,14 +192,16 @@ void MediaServer::WriteReplayMessages() {
if (fwrite(&len16, 2, 1, replay_out_file_) != 1) { if (fwrite(&len16, 2, 1, replay_out_file_) != 1) {
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
Log("error writing replay file: " + g_platform->GetErrnoString()); Log(LogLevel::kError,
"error writing replay file: " + g_platform->GetErrnoString());
return; return;
} }
} else { } else {
if (fwrite(&len32, 4, 1, replay_out_file_) != 1) { if (fwrite(&len32, 4, 1, replay_out_file_) != 1) {
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
Log("error writing replay file: " + g_platform->GetErrnoString()); Log(LogLevel::kError,
"error writing replay file: " + g_platform->GetErrnoString());
return; return;
} }
} }
@ -184,7 +212,8 @@ void MediaServer::WriteReplayMessages() {
if (result != 1) { if (result != 1) {
fclose(replay_out_file_); fclose(replay_out_file_);
replay_out_file_ = nullptr; replay_out_file_ = nullptr;
Log("error writing replay file: " + g_platform->GetErrnoString()); Log(LogLevel::kError,
"error writing replay file: " + g_platform->GetErrnoString());
return; return;
} }
replay_bytes_written_ += data_compressed.size() + 2; replay_bytes_written_ += data_compressed.size() + 2;
@ -194,10 +223,10 @@ void MediaServer::WriteReplayMessages() {
} }
} }
void MediaServer::Process() { void AssetsServer::Process() {
// make sure we don't do any loading until we know what kind/quality of // make sure we don't do any loading until we know what kind/quality of
// textures we'll be loading // textures we'll be loading
if (!g_media || !g_graphics_server if (!g_assets || !g_graphics_server
|| !g_graphics_server->texture_compression_types_are_set() // NOLINT || !g_graphics_server->texture_compression_types_are_set() // NOLINT
|| !g_graphics_server->texture_quality_set()) { || !g_graphics_server->texture_quality_set()) {
return; return;
@ -209,12 +238,12 @@ void MediaServer::Process() {
if (!pending_preloads_.empty()) { if (!pending_preloads_.empty()) {
(**pending_preloads_.back()).Preload(); (**pending_preloads_.back()).Preload();
// pass the ref-pointer along to the load queue // pass the ref-pointer along to the load queue
g_media->AddPendingLoad(pending_preloads_.back()); g_assets->AddPendingLoad(pending_preloads_.back());
pending_preloads_.pop_back(); pending_preloads_.pop_back();
} else if (!pending_preloads_audio_.empty()) { } else if (!pending_preloads_audio_.empty()) {
(**pending_preloads_audio_.back()).Preload(); (**pending_preloads_audio_.back()).Preload();
// pass the ref-pointer along to the load queue // pass the ref-pointer along to the load queue
g_media->AddPendingLoad(pending_preloads_audio_.back()); g_assets->AddPendingLoad(pending_preloads_audio_.back());
pending_preloads_audio_.pop_back(); pending_preloads_audio_.pop_back();
} }

View File

@ -0,0 +1,42 @@
// Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_ASSETS_ASSETS_SERVER_H_
#define BALLISTICA_ASSETS_ASSETS_SERVER_H_
#include <list>
#include <vector>
#include "ballistica/core/object.h"
namespace ballistica {
class AssetsServer {
public:
AssetsServer();
auto OnAppStart() -> void;
auto PushBeginWriteReplayCall() -> void;
auto PushEndWriteReplayCall() -> void;
auto PushAddMessageToReplayCall(const std::vector<uint8_t>& data) -> void;
auto PushPendingPreload(Object::Ref<AssetComponentData>* asset_ref_ptr)
-> void;
auto thread() const -> Thread* { return thread_; }
private:
auto OnAppStartInThread() -> void;
void Process();
void WriteReplayMessages();
Thread* thread_{};
FILE* replay_out_file_{};
size_t replay_bytes_written_{};
bool writing_replay_{};
bool replays_broken_{};
std::list<std::vector<uint8_t> > replay_messages_;
size_t replay_message_bytes_{};
Timer* process_timer_{};
std::vector<Object::Ref<AssetComponentData>*> pending_preloads_;
std::vector<Object::Ref<AssetComponentData>*> pending_preloads_audio_;
};
} // namespace ballistica
#endif // BALLISTICA_ASSETS_ASSETS_SERVER_H_

View File

@ -1,16 +1,16 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/media_component.h" #include "ballistica/assets/component/asset_component.h"
#include "ballistica/python/python_sys.h" #include "ballistica/python/python_sys.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
namespace ballistica { namespace ballistica {
MediaComponent::MediaComponent(std::string name, Scene* scene) AssetComponent::AssetComponent(std::string name, Scene* scene)
: name_(std::move(name)), scene_(scene) {} : name_(std::move(name)), scene_(scene) {}
auto MediaComponent::GetPyRef(bool new_ref) -> PyObject* { auto AssetComponent::GetPyRef(bool new_ref) -> PyObject* {
if (!py_object_) { if (!py_object_) {
// if we have no python object, create it // if we have no python object, create it
py_object_ = CreatePyObject(); py_object_ = CreatePyObject();
@ -22,11 +22,11 @@ auto MediaComponent::GetPyRef(bool new_ref) -> PyObject* {
return py_object_; return py_object_;
} }
auto MediaComponent::GetObjectDescription() const -> std::string { auto AssetComponent::GetObjectDescription() const -> std::string {
return "<ballistica::" + GetMediaComponentTypeName() + " \"" + name() + "\">"; return "<ballistica::" + GetAssetComponentTypeName() + " \"" + name() + "\">";
} }
void MediaComponent::ClearPyObject() { void AssetComponent::ClearPyObject() {
assert(py_object_ != nullptr); assert(py_object_ != nullptr);
py_object_ = nullptr; py_object_ = nullptr;
} }

View File

@ -1,7 +1,7 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_MEDIA_COMPONENT_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_ASSET_COMPONENT_H_
#define BALLISTICA_MEDIA_COMPONENT_MEDIA_COMPONENT_H_ #define BALLISTICA_ASSETS_COMPONENT_ASSET_COMPONENT_H_
#include <string> #include <string>
@ -10,9 +10,9 @@
namespace ballistica { namespace ballistica {
class MediaComponent : public Object { class AssetComponent : public Object {
public: public:
MediaComponent(std::string name, Scene* scene); AssetComponent(std::string name, Scene* scene);
auto name() const -> std::string { return name_; } auto name() const -> std::string { return name_; }
// Returns true if this texture was created in the UI context. // Returns true if this texture was created in the UI context.
@ -41,7 +41,7 @@ class MediaComponent : public Object {
} }
protected: protected:
virtual auto GetMediaComponentTypeName() const -> std::string = 0; virtual auto GetAssetComponentTypeName() const -> std::string = 0;
// Create a python representation of this object. // Create a python representation of this object.
virtual auto CreatePyObject() -> PyObject* = 0; virtual auto CreatePyObject() -> PyObject* = 0;
@ -60,4 +60,4 @@ class MediaComponent : public Object {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_MEDIA_COMPONENT_H_ #endif // BALLISTICA_ASSETS_COMPONENT_ASSET_COMPONENT_H_

View File

@ -1,24 +1,24 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/collide_model.h" #include "ballistica/assets/component/collide_model.h"
#include "ballistica/game/game_stream.h"
#include "ballistica/python/class/python_class_collide_model.h" #include "ballistica/python/class/python_class_collide_model.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/scene_stream.h"
namespace ballistica { namespace ballistica {
CollideModel::CollideModel(const std::string& name, Scene* scene) CollideModel::CollideModel(const std::string& name, Scene* scene)
: MediaComponent(name, scene), dead_(false) { : AssetComponent(name, scene), dead_(false) {
assert(InLogicThread()); assert(InLogicThread());
if (scene) { if (scene) {
if (GameStream* os = scene->GetGameStream()) { if (SceneStream* os = scene->GetSceneStream()) {
os->AddCollideModel(this); os->AddCollideModel(this);
} }
} }
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
collide_model_data_ = g_media->GetCollideModelData(name); collide_model_data_ = g_assets->GetCollideModelData(name);
} }
assert(collide_model_data_.exists()); assert(collide_model_data_.exists());
} }
@ -30,7 +30,7 @@ void CollideModel::MarkDead() {
return; return;
} }
if (Scene* s = scene()) { if (Scene* s = scene()) {
if (GameStream* os = s->GetGameStream()) { if (SceneStream* os = s->GetSceneStream()) {
os->RemoveCollideModel(this); os->RemoveCollideModel(this);
} }
} }

View File

@ -1,18 +1,18 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_COLLIDE_MODEL_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_COLLIDE_MODEL_H_
#define BALLISTICA_MEDIA_COMPONENT_COLLIDE_MODEL_H_ #define BALLISTICA_ASSETS_COMPONENT_COLLIDE_MODEL_H_
#include <string> #include <string>
#include "ballistica/media/component/media_component.h" #include "ballistica/assets/assets.h"
#include "ballistica/media/data/collide_model_data.h" #include "ballistica/assets/component/asset_component.h"
#include "ballistica/media/media.h" #include "ballistica/assets/data/collide_model_data.h"
namespace ballistica { namespace ballistica {
// user-facing collide_model class // user-facing collide_model class
class CollideModel : public MediaComponent { class CollideModel : public AssetComponent {
public: public:
CollideModel(const std::string& name, Scene* scene); CollideModel(const std::string& name, Scene* scene);
~CollideModel() override; ~CollideModel() override;
@ -23,7 +23,7 @@ class CollideModel : public MediaComponent {
auto collide_model_data() const -> CollideModelData* { auto collide_model_data() const -> CollideModelData* {
return collide_model_data_.get(); return collide_model_data_.get();
} }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "CollideModel"; return "CollideModel";
} }
void MarkDead(); void MarkDead();
@ -38,4 +38,4 @@ class CollideModel : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_COLLIDE_MODEL_H_ #endif // BALLISTICA_ASSETS_COMPONENT_COLLIDE_MODEL_H_

View File

@ -1,19 +1,19 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/cube_map_texture.h" #include "ballistica/assets/component/cube_map_texture.h"
#include "ballistica/media/media.h" #include "ballistica/assets/assets.h"
namespace ballistica { namespace ballistica {
CubeMapTexture::CubeMapTexture(const std::string& name, Scene* scene) CubeMapTexture::CubeMapTexture(const std::string& name, Scene* scene)
: MediaComponent(name, scene) { : AssetComponent(name, scene) {
assert(InLogicThread()); assert(InLogicThread());
// cant currently add these to scenes so nothing to do here.. // cant currently add these to scenes so nothing to do here..
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
texture_data_ = g_media->GetCubeMapTextureData(name); texture_data_ = g_assets->GetCubeMapTextureData(name);
} }
assert(texture_data_.exists()); assert(texture_data_.exists());
} }

View File

@ -1,17 +1,17 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_CUBE_MAP_TEXTURE_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_CUBE_MAP_TEXTURE_H_
#define BALLISTICA_MEDIA_COMPONENT_CUBE_MAP_TEXTURE_H_ #define BALLISTICA_ASSETS_COMPONENT_CUBE_MAP_TEXTURE_H_
#include <string> #include <string>
#include "ballistica/media/component/media_component.h" #include "ballistica/assets/component/asset_component.h"
#include "ballistica/media/data/texture_data.h" #include "ballistica/assets/data/texture_data.h"
namespace ballistica { namespace ballistica {
// user-facing texture class // user-facing texture class
class CubeMapTexture : public MediaComponent { class CubeMapTexture : public AssetComponent {
public: public:
CubeMapTexture(const std::string& name, Scene* s); CubeMapTexture(const std::string& name, Scene* s);
@ -19,7 +19,7 @@ class CubeMapTexture : public MediaComponent {
// note that a texture's data can change over time as different // note that a texture's data can change over time as different
// versions are spooled in/out/etc // versions are spooled in/out/etc
auto GetTextureData() const -> TextureData* { return texture_data_.get(); } auto GetTextureData() const -> TextureData* { return texture_data_.get(); }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "CubeMapTexture"; return "CubeMapTexture";
} }
@ -29,4 +29,4 @@ class CubeMapTexture : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_CUBE_MAP_TEXTURE_H_ #endif // BALLISTICA_ASSETS_COMPONENT_CUBE_MAP_TEXTURE_H_

View File

@ -1,25 +1,25 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/data.h" #include "ballistica/assets/component/data.h"
#include "ballistica/game/game_stream.h"
#include "ballistica/python/class/python_class_data.h" #include "ballistica/python/class/python_class_data.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/scene_stream.h"
namespace ballistica { namespace ballistica {
Data::Data(const std::string& name, Scene* scene) Data::Data(const std::string& name, Scene* scene)
: MediaComponent(name, scene), dead_(false) { : AssetComponent(name, scene), dead_(false) {
assert(InLogicThread()); assert(InLogicThread());
if (scene) { if (scene) {
if (GameStream* os = scene->GetGameStream()) { if (SceneStream* os = scene->GetSceneStream()) {
os->AddData(this); os->AddData(this);
} }
} }
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
data_data_ = g_media->GetDataData(name); data_data_ = g_assets->GetDataData(name);
} }
assert(data_data_.exists()); assert(data_data_.exists());
} }
@ -31,7 +31,7 @@ void Data::MarkDead() {
return; return;
} }
if (Scene* s = scene()) { if (Scene* s = scene()) {
if (GameStream* os = s->GetGameStream()) { if (SceneStream* os = s->GetSceneStream()) {
os->RemoveData(this); os->RemoveData(this);
} }
} }

View File

@ -1,22 +1,22 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_DATA_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_DATA_H_
#define BALLISTICA_MEDIA_COMPONENT_DATA_H_ #define BALLISTICA_ASSETS_COMPONENT_DATA_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/assets/assets.h"
#include "ballistica/assets/component/asset_component.h"
#include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/assets/data/data_data.h"
#include "ballistica/ballistica.h" #include "ballistica/ballistica.h"
#include "ballistica/core/object.h" #include "ballistica/core/object.h"
#include "ballistica/media/component/media_component.h"
#include "ballistica/media/data/data_data.h"
#include "ballistica/media/data/media_component_data.h"
#include "ballistica/media/media.h"
namespace ballistica { namespace ballistica {
// user-facing data class // user-facing data class
class Data : public MediaComponent { class Data : public AssetComponent {
public: public:
Data(const std::string& name, Scene* scene); Data(const std::string& name, Scene* scene);
~Data() override; ~Data() override;
@ -25,7 +25,7 @@ class Data : public MediaComponent {
// note that a data's data can change over time as different // note that a data's data can change over time as different
// versions are spooled in/out/etc. // versions are spooled in/out/etc.
auto data_data() const -> DataData* { return data_data_.get(); } auto data_data() const -> DataData* { return data_data_.get(); }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "Data"; return "Data";
} }
void MarkDead(); void MarkDead();
@ -40,4 +40,4 @@ class Data : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_DATA_H_ #endif // BALLISTICA_ASSETS_COMPONENT_DATA_H_

View File

@ -1,25 +1,25 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/model.h" #include "ballistica/assets/component/model.h"
#include "ballistica/game/game_stream.h"
#include "ballistica/python/class/python_class_model.h" #include "ballistica/python/class/python_class_model.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/scene_stream.h"
namespace ballistica { namespace ballistica {
Model::Model(const std::string& name, Scene* scene) Model::Model(const std::string& name, Scene* scene)
: MediaComponent(name, scene), dead_(false) { : AssetComponent(name, scene), dead_(false) {
assert(InLogicThread()); assert(InLogicThread());
if (scene) { if (scene) {
if (GameStream* os = scene->GetGameStream()) { if (SceneStream* os = scene->GetSceneStream()) {
os->AddModel(this); os->AddModel(this);
} }
} }
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
model_data_ = g_media->GetModelData(name); model_data_ = g_assets->GetModelData(name);
} }
assert(model_data_.exists()); assert(model_data_.exists());
} }
@ -31,7 +31,7 @@ void Model::MarkDead() {
return; return;
} }
if (Scene* s = scene()) { if (Scene* s = scene()) {
if (GameStream* os = s->GetGameStream()) { if (SceneStream* os = s->GetSceneStream()) {
os->RemoveModel(this); os->RemoveModel(this);
} }
} }

View File

@ -1,23 +1,23 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_MODEL_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_MODEL_H_
#define BALLISTICA_MEDIA_COMPONENT_MODEL_H_ #define BALLISTICA_ASSETS_COMPONENT_MODEL_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/assets/assets.h"
#include "ballistica/assets/component/asset_component.h"
#include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/assets/data/model_data.h"
#include "ballistica/assets/data/model_renderer_data.h"
#include "ballistica/ballistica.h" #include "ballistica/ballistica.h"
#include "ballistica/core/object.h" #include "ballistica/core/object.h"
#include "ballistica/media/component/media_component.h"
#include "ballistica/media/data/media_component_data.h"
#include "ballistica/media/data/model_data.h"
#include "ballistica/media/data/model_renderer_data.h"
#include "ballistica/media/media.h"
namespace ballistica { namespace ballistica {
// user-facing model class // user-facing model class
class Model : public MediaComponent { class Model : public AssetComponent {
public: public:
Model(const std::string& name, Scene* scene); Model(const std::string& name, Scene* scene);
~Model() override; ~Model() override;
@ -26,7 +26,7 @@ class Model : public MediaComponent {
// note that a model's data can change over time as different // note that a model's data can change over time as different
// versions are spooled in/out/etc // versions are spooled in/out/etc
auto model_data() const -> ModelData* { return model_data_.get(); } auto model_data() const -> ModelData* { return model_data_.get(); }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "Model"; return "Model";
} }
void MarkDead(); void MarkDead();
@ -41,4 +41,4 @@ class Model : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_MODEL_H_ #endif // BALLISTICA_ASSETS_COMPONENT_MODEL_H_

View File

@ -1,26 +1,26 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/sound.h" #include "ballistica/assets/component/sound.h"
#include "ballistica/game/game_stream.h" #include "ballistica/assets/assets.h"
#include "ballistica/media/data/sound_data.h" #include "ballistica/assets/data/sound_data.h"
#include "ballistica/media/media.h"
#include "ballistica/python/class/python_class_sound.h" #include "ballistica/python/class/python_class_sound.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/scene_stream.h"
namespace ballistica { namespace ballistica {
Sound::Sound(const std::string& name, Scene* scene) Sound::Sound(const std::string& name, Scene* scene)
: MediaComponent(name, scene) { : AssetComponent(name, scene) {
assert(InLogicThread()); assert(InLogicThread());
if (scene) { if (scene) {
if (GameStream* os = scene->GetGameStream()) { if (SceneStream* os = scene->GetSceneStream()) {
os->AddSound(this); os->AddSound(this);
} }
} }
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
sound_data_ = g_media->GetSoundData(name); sound_data_ = g_assets->GetSoundData(name);
} }
assert(sound_data_.exists()); assert(sound_data_.exists());
} }
@ -30,7 +30,7 @@ Sound::~Sound() { MarkDead(); }
void Sound::MarkDead() { void Sound::MarkDead() {
if (dead_) return; if (dead_) return;
if (Scene* s = scene()) { if (Scene* s = scene()) {
if (GameStream* os = s->GetGameStream()) { if (SceneStream* os = s->GetSceneStream()) {
os->RemoveSound(this); os->RemoveSound(this);
} }
} }

View File

@ -1,16 +1,16 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_SOUND_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_SOUND_H_
#define BALLISTICA_MEDIA_COMPONENT_SOUND_H_ #define BALLISTICA_ASSETS_COMPONENT_SOUND_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/media/component/media_component.h" #include "ballistica/assets/component/asset_component.h"
namespace ballistica { namespace ballistica {
class Sound : public MediaComponent { class Sound : public AssetComponent {
public: public:
Sound(const std::string& name, Scene* scene); Sound(const std::string& name, Scene* scene);
~Sound() override; ~Sound() override;
@ -19,7 +19,7 @@ class Sound : public MediaComponent {
// Note that a sound's data can change over time as different // Note that a sound's data can change over time as different
// versions are spooled in/out/etc. // versions are spooled in/out/etc.
auto GetSoundData() const -> SoundData* { return sound_data_.get(); } auto GetSoundData() const -> SoundData* { return sound_data_.get(); }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "Sound"; return "Sound";
} }
void MarkDead(); void MarkDead();
@ -34,4 +34,4 @@ class Sound : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_SOUND_H_ #endif // BALLISTICA_ASSETS_COMPONENT_SOUND_H_

View File

@ -1,37 +1,37 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/component/texture.h" #include "ballistica/assets/component/texture.h"
#include "ballistica/game/game_stream.h"
#include "ballistica/graphics/renderer.h" #include "ballistica/graphics/renderer.h"
#include "ballistica/python/class/python_class_texture.h" #include "ballistica/python/class/python_class_texture.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/scene_stream.h"
namespace ballistica { namespace ballistica {
Texture::Texture(const std::string& name, Scene* scene) Texture::Texture(const std::string& name, Scene* scene)
: MediaComponent(name, scene), dead_(false) { : AssetComponent(name, scene), dead_(false) {
assert(InLogicThread()); assert(InLogicThread());
// Add to the provided scene to get a numeric ID. // Add to the provided scene to get a numeric ID.
if (scene) { if (scene) {
if (GameStream* os = scene->GetGameStream()) { if (SceneStream* os = scene->GetSceneStream()) {
os->AddTexture(this); os->AddTexture(this);
} }
} }
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
texture_data_ = g_media->GetTextureData(name); texture_data_ = g_assets->GetTextureData(name);
} }
assert(texture_data_.exists()); assert(texture_data_.exists());
} }
// qrcode version // qrcode version
Texture::Texture(const std::string& qr_url) : MediaComponent(qr_url, nullptr) { Texture::Texture(const std::string& qr_url) : AssetComponent(qr_url, nullptr) {
assert(InLogicThread()); assert(InLogicThread());
{ {
Media::MediaListsLock lock; Assets::AssetListLock lock;
texture_data_ = g_media->GetTextureDataQRCode(qr_url); texture_data_ = g_assets->GetTextureDataQRCode(qr_url);
} }
assert(texture_data_.exists()); assert(texture_data_.exists());
} }
@ -43,7 +43,7 @@ void Texture::MarkDead() {
return; return;
} }
if (Scene* s = scene()) { if (Scene* s = scene()) {
if (GameStream* os = s->GetGameStream()) { if (SceneStream* os = s->GetSceneStream()) {
os->RemoveTexture(this); os->RemoveTexture(this);
} }
} }

View File

@ -1,17 +1,17 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_COMPONENT_TEXTURE_H_ #ifndef BALLISTICA_ASSETS_COMPONENT_TEXTURE_H_
#define BALLISTICA_MEDIA_COMPONENT_TEXTURE_H_ #define BALLISTICA_ASSETS_COMPONENT_TEXTURE_H_
#include <string> #include <string>
#include "ballistica/media/component/media_component.h" #include "ballistica/assets/component/asset_component.h"
#include "ballistica/media/data/texture_data.h" #include "ballistica/assets/data/texture_data.h"
namespace ballistica { namespace ballistica {
// User-facing texture class. // User-facing texture class.
class Texture : public MediaComponent { class Texture : public AssetComponent {
public: public:
Texture(const std::string& name, Scene* scene); Texture(const std::string& name, Scene* scene);
explicit Texture(const std::string& qr_url); explicit Texture(const std::string& qr_url);
@ -21,7 +21,7 @@ class Texture : public MediaComponent {
// Note that a texture's data can change over time as different // Note that a texture's data can change over time as different
// versions are spooled in/out/etc. // versions are spooled in/out/etc.
auto texture_data() const -> TextureData* { return texture_data_.get(); } auto texture_data() const -> TextureData* { return texture_data_.get(); }
auto GetMediaComponentTypeName() const -> std::string override { auto GetAssetComponentTypeName() const -> std::string override {
return "Texture"; return "Texture";
} }
void MarkDead(); void MarkDead();
@ -36,4 +36,4 @@ class Texture : public MediaComponent {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_COMPONENT_TEXTURE_H_ #endif // BALLISTICA_ASSETS_COMPONENT_TEXTURE_H_

View File

@ -1,25 +1,25 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/media_component_data.h" #include "ballistica/assets/data/asset_component_data.h"
namespace ballistica { namespace ballistica {
MediaComponentData::MediaComponentData() { AssetComponentData::AssetComponentData() {
assert(InLogicThread()); assert(InLogicThread());
assert(g_media); assert(g_assets);
last_used_time_ = GetRealTime(); last_used_time_ = GetRealTime();
} }
MediaComponentData::~MediaComponentData() { AssetComponentData::~AssetComponentData() {
// at the moment whoever owns the last reference to us // at the moment whoever owns the last reference to us
// needs to make sure to unload us before we die.. // needs to make sure to unload us before we die..
// I feel like there should be a more elegant solution to that. // I feel like there should be a more elegant solution to that.
assert(g_media); assert(g_assets);
assert(!locked()); assert(!locked());
assert(!loaded()); assert(!loaded());
} }
void MediaComponentData::Preload(bool already_locked) { void AssetComponentData::Preload(bool already_locked) {
LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock
: LockGuard::Type::kLock); : LockGuard::Type::kLock);
if (!preloaded_) { if (!preloaded_) {
@ -35,7 +35,7 @@ void MediaComponentData::Preload(bool already_locked) {
} }
} }
void MediaComponentData::Load(bool already_locked) { void AssetComponentData::Load(bool already_locked) {
LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock
: LockGuard::Type::kLock); : LockGuard::Type::kLock);
if (!preloaded_) { if (!preloaded_) {
@ -57,7 +57,7 @@ void MediaComponentData::Load(bool already_locked) {
} }
} }
void MediaComponentData::Unload(bool already_locked) { void AssetComponentData::Unload(bool already_locked) {
LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock LockGuard lock(this, already_locked ? LockGuard::Type::kDontLock
: LockGuard::Type::kLock); : LockGuard::Type::kLock);
@ -80,7 +80,7 @@ void MediaComponentData::Unload(bool already_locked) {
} }
} }
MediaComponentData::LockGuard::LockGuard(MediaComponentData* data, Type type) AssetComponentData::LockGuard::LockGuard(AssetComponentData* data, Type type)
: data_(data) { : data_(data) {
switch (type) { switch (type) {
case kLock: { case kLock: {
@ -100,7 +100,7 @@ MediaComponentData::LockGuard::LockGuard(MediaComponentData* data, Type type)
} }
} }
MediaComponentData::LockGuard::~LockGuard() { AssetComponentData::LockGuard::~LockGuard() {
if (holds_lock_) { if (holds_lock_) {
data_->Unlock(); data_->Unlock();
} }

View File

@ -1,7 +1,7 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_MEDIA_COMPONENT_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_ASSET_COMPONENT_DATA_H_
#define BALLISTICA_MEDIA_DATA_MEDIA_COMPONENT_DATA_H_ #define BALLISTICA_ASSETS_DATA_ASSET_COMPONENT_DATA_H_
#include <mutex> #include <mutex>
#include <string> #include <string>
@ -11,17 +11,17 @@
namespace ballistica { namespace ballistica {
/// Base class for loadable media components. /// Base class for loadable asset components.
class MediaComponentData : public Object { class AssetComponentData : public Object {
public: public:
MediaComponentData(); AssetComponentData();
~MediaComponentData() override; ~AssetComponentData() override;
void Preload(bool already_locked = false); void Preload(bool already_locked = false);
void Load(bool already_locked = false); void Load(bool already_locked = false);
void Unload(bool already_locked = false); void Unload(bool already_locked = false);
auto preloaded() const -> bool { return preloaded_; } auto preloaded() const -> bool { return preloaded_; }
auto loaded() const -> bool { return preloaded_ && loaded_; } auto loaded() const -> bool { return preloaded_ && loaded_; }
virtual auto GetMediaType() const -> MediaType = 0; virtual auto GetAssetType() const -> AssetType = 0;
// Return name or another identifier. For debugging purposes. // Return name or another identifier. For debugging purposes.
virtual auto GetName() const -> std::string { return "invalid"; } virtual auto GetName() const -> std::string { return "invalid"; }
@ -35,14 +35,14 @@ class MediaComponentData : public Object {
class LockGuard { class LockGuard {
public: public:
enum Type { kLock, kInheritLock, kDontLock }; enum Type { kLock, kInheritLock, kDontLock };
explicit LockGuard(MediaComponentData* data, Type type = kLock); explicit LockGuard(AssetComponentData* data, Type type = kLock);
~LockGuard(); ~LockGuard();
// Does this guard hold a lock? // Does this guard hold a lock?
auto holds_lock() const -> bool { return holds_lock_; } auto holds_lock() const -> bool { return holds_lock_; }
private: private:
MediaComponentData* data_ = nullptr; AssetComponentData* data_ = nullptr;
bool holds_lock_ = false; bool holds_lock_ = false;
}; };
@ -128,9 +128,9 @@ class MediaComponentData : public Object {
bool preloaded_ = false; bool preloaded_ = false;
bool loaded_ = false; bool loaded_ = false;
std::mutex mutex_; std::mutex mutex_;
BA_DISALLOW_CLASS_COPIES(MediaComponentData); BA_DISALLOW_CLASS_COPIES(AssetComponentData);
}; };
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_MEDIA_COMPONENT_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_ASSET_COMPONENT_DATA_H_

View File

@ -1,15 +1,15 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/collide_model_data.h" #include "ballistica/assets/data/collide_model_data.h"
#include "ballistica/media/media.h" #include "ballistica/assets/assets.h"
namespace ballistica { namespace ballistica {
CollideModelData::CollideModelData(const std::string& file_name_in) CollideModelData::CollideModelData(const std::string& file_name_in)
: file_name_(file_name_in) { : file_name_(file_name_in) {
file_name_full_ = file_name_full_ =
g_media->FindMediaFile(Media::FileType::kCollisionModel, file_name_in); g_assets->FindAssetFile(Assets::FileType::kCollisionModel, file_name_in);
valid_ = true; valid_ = true;
} }

View File

@ -1,26 +1,26 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_COLLIDE_MODEL_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_COLLIDE_MODEL_DATA_H_
#define BALLISTICA_MEDIA_DATA_COLLIDE_MODEL_DATA_H_ #define BALLISTICA_ASSETS_DATA_COLLIDE_MODEL_DATA_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/media/data/media_component_data.h" #include "ballistica/assets/data/asset_component_data.h"
#include "ode/ode.h" #include "ode/ode.h"
namespace ballistica { namespace ballistica {
// Loadable model for collision detection. // Loadable model for collision detection.
class CollideModelData : public MediaComponentData { class CollideModelData : public AssetComponentData {
public: public:
CollideModelData() = default; CollideModelData() = default;
explicit CollideModelData(const std::string& file_name_in); explicit CollideModelData(const std::string& file_name_in);
void DoPreload() override; void DoPreload() override;
void DoLoad() override; void DoLoad() override;
void DoUnload() override; void DoUnload() override;
auto GetMediaType() const -> MediaType override { auto GetAssetType() const -> AssetType override {
return MediaType::kCollideModel; return AssetType::kCollideModel;
} }
auto GetName() const -> std::string override { auto GetName() const -> std::string override {
if (!file_name_full_.empty()) { if (!file_name_full_.empty()) {
@ -44,4 +44,4 @@ class CollideModelData : public MediaComponentData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_COLLIDE_MODEL_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_COLLIDE_MODEL_DATA_H_

View File

@ -1,8 +1,8 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/data_data.h" #include "ballistica/assets/data/data_data.h"
#include "ballistica/media/media.h" #include "ballistica/assets/assets.h"
#include "ballistica/python/python.h" #include "ballistica/python/python.h"
#include "ballistica/python/python_sys.h" #include "ballistica/python/python_sys.h"
@ -10,7 +10,7 @@ namespace ballistica {
DataData::DataData(const std::string& file_name_in) : file_name_(file_name_in) { DataData::DataData(const std::string& file_name_in) : file_name_(file_name_in) {
file_name_full_ = file_name_full_ =
g_media->FindMediaFile(Media::FileType::kData, file_name_in); g_assets->FindAssetFile(Assets::FileType::kData, file_name_in);
valid_ = true; valid_ = true;
} }
@ -20,8 +20,8 @@ void DataData::DoPreload() {
// in the following case: // in the following case:
// - asset thread grabs payload lock for Preload() // - asset thread grabs payload lock for Preload()
// - asset thread tries to grab GIL in Preload(); spins. // - asset thread tries to grab GIL in Preload(); spins.
// - meanwhile, something in game thread has called Load() // - meanwhile, something in logic thread has called Load()
// - game thread holds GIL by default and now spins waiting on payload lock. // - logic thread holds GIL by default and now spins waiting on payload lock.
// - deadlock :-( // - deadlock :-(
// ...so the new plan is to simply load the file into a string in Preload() // ...so the new plan is to simply load the file into a string in Preload()

View File

@ -1,16 +1,16 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_DATA_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_DATA_DATA_H_
#define BALLISTICA_MEDIA_DATA_DATA_DATA_H_ #define BALLISTICA_ASSETS_DATA_DATA_DATA_H_
#include <string> #include <string>
#include "ballistica/media/data/media_component_data.h" #include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/python/python_ref.h" #include "ballistica/python/python_ref.h"
namespace ballistica { namespace ballistica {
class DataData : public MediaComponentData { class DataData : public AssetComponentData {
public: public:
DataData() = default; DataData() = default;
explicit DataData(const std::string& file_name_in); explicit DataData(const std::string& file_name_in);
@ -19,7 +19,7 @@ class DataData : public MediaComponentData {
void DoLoad() override; void DoLoad() override;
void DoUnload() override; void DoUnload() override;
auto GetMediaType() const -> MediaType override { return MediaType::kData; } auto GetAssetType() const -> AssetType override { return AssetType::kData; }
auto GetName() const -> std::string override { auto GetName() const -> std::string override {
if (!file_name_full_.empty()) { if (!file_name_full_.empty()) {
return file_name_full_; return file_name_full_;
@ -44,4 +44,4 @@ class DataData : public MediaComponentData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_DATA_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_DATA_DATA_H_

View File

@ -1,6 +1,6 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/model_data.h" #include "ballistica/assets/data/model_data.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/renderer.h" #include "ballistica/graphics/renderer.h"
@ -10,7 +10,7 @@ namespace ballistica {
ModelData::ModelData(const std::string& file_name_in) ModelData::ModelData(const std::string& file_name_in)
: file_name_(file_name_in) { : file_name_(file_name_in) {
file_name_full_ = file_name_full_ =
g_media->FindMediaFile(Media::FileType::kModel, file_name_in); g_assets->FindAssetFile(Assets::FileType::kModel, file_name_in);
valid_ = true; valid_ = true;
} }

View File

@ -1,24 +1,24 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_MODEL_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_MODEL_DATA_H_
#define BALLISTICA_MEDIA_DATA_MODEL_DATA_H_ #define BALLISTICA_ASSETS_DATA_MODEL_DATA_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/media/data/media_component_data.h" #include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/media/data/model_renderer_data.h" #include "ballistica/assets/data/model_renderer_data.h"
namespace ballistica { namespace ballistica {
class ModelData : public MediaComponentData { class ModelData : public AssetComponentData {
public: public:
ModelData() = default; ModelData() = default;
explicit ModelData(const std::string& file_name_in); explicit ModelData(const std::string& file_name_in);
void DoPreload() override; void DoPreload() override;
void DoLoad() override; void DoLoad() override;
void DoUnload() override; void DoUnload() override;
auto GetMediaType() const -> MediaType override { return MediaType::kModel; } auto GetAssetType() const -> AssetType override { return AssetType::kModel; }
auto GetName() const -> std::string override { auto GetName() const -> std::string override {
if (!file_name_full_.empty()) { if (!file_name_full_.empty()) {
return file_name_full_; return file_name_full_;
@ -64,4 +64,4 @@ class ModelData : public MediaComponentData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_MODEL_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_MODEL_DATA_H_

View File

@ -1,7 +1,7 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_MODEL_RENDERER_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_MODEL_RENDERER_DATA_H_
#define BALLISTICA_MEDIA_DATA_MODEL_RENDERER_DATA_H_ #define BALLISTICA_ASSETS_DATA_MODEL_RENDERER_DATA_H_
#include "ballistica/core/object.h" #include "ballistica/core/object.h"
@ -11,11 +11,11 @@ namespace ballistica {
// this is provided by the renderer // this is provided by the renderer
class ModelRendererData : public Object { class ModelRendererData : public Object {
public: public:
auto GetDefaultOwnerThread() const -> ThreadIdentifier override { auto GetDefaultOwnerThread() const -> ThreadTag override {
return ThreadIdentifier::kMain; return ThreadTag::kMain;
} }
}; };
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_MODEL_RENDERER_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_MODEL_RENDERER_DATA_H_

View File

@ -1,6 +1,6 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/sound_data.h" #include "ballistica/assets/data/sound_data.h"
#if BA_ENABLE_AUDIO #if BA_ENABLE_AUDIO
#if BA_USE_TREMOR_VORBIS #if BA_USE_TREMOR_VORBIS
@ -10,8 +10,8 @@
#endif #endif
#endif // BA_ENABLE_AUDIO #endif // BA_ENABLE_AUDIO
#include "ballistica/assets/assets.h"
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/media/media.h"
#include "ballistica/python/python.h" #include "ballistica/python/python.h"
// Need to move away from OpenAL on Apple stuff. // Need to move away from OpenAL on Apple stuff.
@ -56,8 +56,8 @@ static auto LoadOgg(const char* file_name, std::vector<char>* buffer,
f = g_platform->FOpen(file_name, "rb"); f = g_platform->FOpen(file_name, "rb");
if (f == nullptr) { if (f == nullptr) {
fallback = true; fallback = true;
Log(std::string("Error: Can't open sound file '") + file_name Log(LogLevel::kError, std::string("Can't open sound file '") + file_name
+ "' for reading..."); + "' for reading...");
// Attempt a fallback standin; if that doesn't work, throw in the towel. // Attempt a fallback standin; if that doesn't work, throw in the towel.
file_name = "data/global/audio/blank.ogg"; file_name = "data/global/audio/blank.ogg";
@ -77,7 +77,8 @@ static auto LoadOgg(const char* file_name, std::vector<char>* buffer,
// Try opening the given file // Try opening the given file
if (ov_open_callbacks(f, &ogg_file, nullptr, 0, callbacks) != 0) { if (ov_open_callbacks(f, &ogg_file, nullptr, 0, callbacks) != 0) {
Log(std::string("Error decoding sound file '") + file_name + "'"); Log(LogLevel::kError,
std::string("Error decoding sound file '") + file_name + "'");
fclose(f); fclose(f);
@ -199,8 +200,9 @@ static void LoadCachedOgg(const char* file_name, std::vector<char>* buffer,
// with invalid formats of 0 once. Report and ignore if we see // with invalid formats of 0 once. Report and ignore if we see
// something like that. // something like that.
if (*format != AL_FORMAT_MONO16 && *format != AL_FORMAT_STEREO16) { if (*format != AL_FORMAT_MONO16 && *format != AL_FORMAT_STEREO16) {
Log(std::string("Ignoring invalid audio cache of ") + file_name Log(LogLevel::kError, std::string("Ignoring invalid audio cache of ")
+ " with format " + std::to_string(*format)); + file_name + " with format "
+ std::to_string(*format));
} else { } else {
return; // SUCCESS!!!! return; // SUCCESS!!!!
} }
@ -248,7 +250,7 @@ SoundData::SoundData(const std::string& file_name_in)
#endif // BA_ENABLE_AUDIO #endif // BA_ENABLE_AUDIO
last_play_time_(0) { last_play_time_(0) {
file_name_full_ = file_name_full_ =
g_media->FindMediaFile(Media::FileType::kSound, file_name_in); g_assets->FindAssetFile(Assets::FileType::kSound, file_name_in);
valid_ = true; valid_ = true;
} }

View File

@ -1,17 +1,17 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_SOUND_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_SOUND_DATA_H_
#define BALLISTICA_MEDIA_DATA_SOUND_DATA_H_ #define BALLISTICA_ASSETS_DATA_SOUND_DATA_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/assets/data/asset_component_data.h"
#include "ballistica/audio/al_sys.h" #include "ballistica/audio/al_sys.h"
#include "ballistica/media/data/media_component_data.h"
namespace ballistica { namespace ballistica {
class SoundData : public MediaComponentData { class SoundData : public AssetComponentData {
public: public:
SoundData() = default; SoundData() = default;
explicit SoundData(const std::string& file_name_in); explicit SoundData(const std::string& file_name_in);
@ -20,7 +20,7 @@ class SoundData : public MediaComponentData {
// FIXME: Should make sure the sound_data isn't in use before unloading it. // FIXME: Should make sure the sound_data isn't in use before unloading it.
void DoUnload() override; void DoUnload() override;
auto GetMediaType() const -> MediaType override { return MediaType::kSound; } auto GetAssetType() const -> AssetType override { return AssetType::kSound; }
auto GetName() const -> std::string override { auto GetName() const -> std::string override {
if (!file_name_full_.empty()) if (!file_name_full_.empty())
return file_name_full_; return file_name_full_;
@ -55,4 +55,4 @@ class SoundData : public MediaComponentData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_SOUND_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_SOUND_DATA_H_

View File

@ -1,7 +1,9 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/texture_data.h" #include "ballistica/assets/data/texture_data.h"
#include "ballistica/assets/data/texture_preload_data.h"
#include "ballistica/assets/data/texture_renderer_data.h"
#include "ballistica/graphics/graphics.h" #include "ballistica/graphics/graphics.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/renderer.h" #include "ballistica/graphics/renderer.h"
@ -9,8 +11,6 @@
#include "ballistica/graphics/texture/dds.h" #include "ballistica/graphics/texture/dds.h"
#include "ballistica/graphics/texture/ktx.h" #include "ballistica/graphics/texture/ktx.h"
#include "ballistica/graphics/texture/pvr.h" #include "ballistica/graphics/texture/pvr.h"
#include "ballistica/media/data/texture_preload_data.h"
#include "ballistica/media/data/texture_renderer_data.h"
#include "external/qr_code_generator/QrCode.hpp" #include "external/qr_code_generator/QrCode.hpp"
namespace ballistica { namespace ballistica {
@ -43,7 +43,8 @@ TextureData::TextureData() = default;
TextureData::TextureData(const std::string& file_in, TextureType type_in, TextureData::TextureData(const std::string& file_in, TextureType type_in,
TextureMinQuality min_quality_in) TextureMinQuality min_quality_in)
: file_name_(file_in), type_(type_in), min_quality_(min_quality_in) { : file_name_(file_in), type_(type_in), min_quality_(min_quality_in) {
file_name_full_ = g_media->FindMediaFile(Media::FileType::kTexture, file_in); file_name_full_ =
g_assets->FindAssetFile(Assets::FileType::kTexture, file_in);
valid_ = true; valid_ = true;
} }

View File

@ -1,17 +1,17 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_TEXTURE_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_TEXTURE_DATA_H_
#define BALLISTICA_MEDIA_DATA_TEXTURE_DATA_H_ #define BALLISTICA_ASSETS_DATA_TEXTURE_DATA_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include "ballistica/media/data/media_component_data.h" #include "ballistica/assets/data/asset_component_data.h"
namespace ballistica { namespace ballistica {
// Loadable texture media component. // Loadable texture media component.
class TextureData : public MediaComponentData { class TextureData : public AssetComponentData {
public: public:
TextureData(); TextureData();
~TextureData() override; ~TextureData() override;
@ -28,8 +28,8 @@ class TextureData : public MediaComponentData {
auto GetNameFull() const -> std::string override { return file_name_full(); } auto GetNameFull() const -> std::string override { return file_name_full(); }
auto file_name() const -> const std::string& { return file_name_; } auto file_name() const -> const std::string& { return file_name_; }
auto file_name_full() const -> const std::string& { return file_name_full_; } auto file_name_full() const -> const std::string& { return file_name_full_; }
auto GetMediaType() const -> MediaType override { auto GetAssetType() const -> AssetType override {
return MediaType::kTexture; return AssetType::kTexture;
} }
void DoPreload() override; void DoPreload() override;
void DoLoad() override; void DoLoad() override;
@ -59,4 +59,4 @@ class TextureData : public MediaComponentData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_TEXTURE_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_TEXTURE_DATA_H_

View File

@ -1,13 +1,13 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#include "ballistica/media/data/texture_preload_data.h" #include "ballistica/assets/data/texture_preload_data.h"
#if BA_OSTYPE_LINUX #if BA_OSTYPE_LINUX
#include <cstring> #include <cstring>
#endif #endif
#include "ballistica/assets/component/texture.h"
#include "ballistica/graphics/texture/ktx.h" #include "ballistica/graphics/texture/ktx.h"
#include "ballistica/media/component/texture.h"
namespace ballistica { namespace ballistica {

View File

@ -1,7 +1,7 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_TEXTURE_PRELOAD_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_TEXTURE_PRELOAD_DATA_H_
#define BALLISTICA_MEDIA_DATA_TEXTURE_PRELOAD_DATA_H_ #define BALLISTICA_ASSETS_DATA_TEXTURE_PRELOAD_DATA_H_
#include "ballistica/ballistica.h" #include "ballistica/ballistica.h"
@ -37,4 +37,4 @@ class TexturePreloadData {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_TEXTURE_PRELOAD_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_TEXTURE_PRELOAD_DATA_H_

View File

@ -1,7 +1,7 @@
// Released under the MIT License. See LICENSE for details. // Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_MEDIA_DATA_TEXTURE_RENDERER_DATA_H_ #ifndef BALLISTICA_ASSETS_DATA_TEXTURE_RENDERER_DATA_H_
#define BALLISTICA_MEDIA_DATA_TEXTURE_RENDERER_DATA_H_ #define BALLISTICA_ASSETS_DATA_TEXTURE_RENDERER_DATA_H_
namespace ballistica { namespace ballistica {
@ -9,8 +9,8 @@ namespace ballistica {
// this is extended by the renderer // this is extended by the renderer
class TextureRendererData : public Object { class TextureRendererData : public Object {
public: public:
auto GetDefaultOwnerThread() const -> ThreadIdentifier override { auto GetDefaultOwnerThread() const -> ThreadTag override {
return ThreadIdentifier::kMain; return ThreadTag::kMain;
} }
// Create the renderer data but don't load it in yet. // Create the renderer data but don't load it in yet.
@ -24,4 +24,4 @@ class TextureRendererData : public Object {
} // namespace ballistica } // namespace ballistica
#endif // BALLISTICA_MEDIA_DATA_TEXTURE_RENDERER_DATA_H_ #endif // BALLISTICA_ASSETS_DATA_TEXTURE_RENDERER_DATA_H_

View File

@ -16,13 +16,14 @@ namespace ballistica {
void _check_al_error(const char* file, int line) { void _check_al_error(const char* file, int line) {
if (g_audio_server->paused()) { if (g_audio_server->paused()) {
Log(Utils::BaseName(file) + ":" + std::to_string(line) Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
+ ": Checking OpenAL error while paused."); + ": Checking OpenAL error while paused.");
} }
ALenum al_err = alGetError(); ALenum al_err = alGetError();
if (al_err != AL_NO_ERROR) { if (al_err != AL_NO_ERROR) {
Log(Utils::BaseName(file) + ":" + std::to_string(line) Log(LogLevel::kError, Utils::BaseName(file) + ":" + std::to_string(line)
+ ": OpenAL Error: " + GetALErrorString(al_err) + ";"); + ": OpenAL Error: " + GetALErrorString(al_err)
+ ";");
} }
} }

View File

@ -2,20 +2,14 @@
#include "ballistica/audio/audio.h" #include "ballistica/audio/audio.h"
#include "ballistica/assets/data/sound_data.h"
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/audio/audio_source.h" #include "ballistica/audio/audio_source.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/media/data/sound_data.h"
namespace ballistica { namespace ballistica {
Audio::Audio() { assert(InLogicThread()); } Audio::Audio() {}
void Audio::Init() {
// Init our singleton.
assert(g_audio == nullptr);
g_audio = new Audio();
}
void Audio::Reset() { void Audio::Reset() {
assert(InLogicThread()); assert(InLogicThread());

View File

@ -15,14 +15,15 @@ namespace ballistica {
/// used by the game and/or other threads. /// used by the game and/or other threads.
class Audio { class Audio {
public: public:
static void Init(); Audio();
void Reset(); auto Reset() -> void;
void SetVolumes(float music_volume, float sound_volume); auto SetVolumes(float music_volume, float sound_volume) -> void;
void SetListenerPosition(const Vector3f& p); auto SetListenerPosition(const Vector3f& p) -> void;
void SetListenerOrientation(const Vector3f& forward, const Vector3f& up); auto SetListenerOrientation(const Vector3f& forward, const Vector3f& up)
void SetSoundPitch(float pitch); -> void;
auto SetSoundPitch(float pitch) -> void;
// Return a pointer to a locked sound source, or nullptr if they're all busy. // Return a pointer to a locked sound source, or nullptr if they're all busy.
// The sound source will be reset to standard settings (no loop, fade 1, pos // The sound source will be reset to standard settings (no loop, fade 1, pos
@ -41,9 +42,9 @@ class Audio {
auto IsSoundPlaying(uint32_t play_id) -> bool; auto IsSoundPlaying(uint32_t play_id) -> bool;
// Simple one-shot play functions. // Simple one-shot play functions.
void PlaySound(SoundData* s, float volume = 1.0f); auto PlaySound(SoundData* s, float volume = 1.0f) -> void;
void PlaySoundAtPosition(SoundData* sound, float volume, float x, float y, auto PlaySoundAtPosition(SoundData* sound, float volume, float x, float y,
float z); float z) -> void;
// Call this if you want to prevent repeated plays of the same sound. It'll // Call this if you want to prevent repeated plays of the same sound. It'll
// tell you if the sound has been played recently. The one-shot sound-play // tell you if the sound has been played recently. The one-shot sound-play
@ -51,19 +52,17 @@ class Audio {
auto ShouldPlay(SoundData* s) -> bool; auto ShouldPlay(SoundData* s) -> bool;
// Hmm; shouldn't these be accessed through the Source class? // Hmm; shouldn't these be accessed through the Source class?
void PushSourceFadeOutCall(uint32_t play_id, uint32_t time); auto PushSourceFadeOutCall(uint32_t play_id, uint32_t time) -> void;
void PushSourceStopSoundCall(uint32_t play_id); auto PushSourceStopSoundCall(uint32_t play_id) -> void;
void AddClientSource(AudioSource* source); auto AddClientSource(AudioSource* source) -> void;
void MakeSourceAvailable(AudioSource* source); auto MakeSourceAvailable(AudioSource* source) -> void;
auto available_sources_mutex() -> std::mutex& { auto available_sources_mutex() -> std::mutex& {
return available_sources_mutex_; return available_sources_mutex_;
} }
private: private:
Audio();
// Flat list of client sources indexed by id. // Flat list of client sources indexed by id.
std::vector<AudioSource*> client_sources_; std::vector<AudioSource*> client_sources_;

View File

@ -3,17 +3,17 @@
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/app/app.h" #include "ballistica/app/app.h"
#include "ballistica/assets/assets.h"
#include "ballistica/assets/data/sound_data.h"
#include "ballistica/audio/al_sys.h" #include "ballistica/audio/al_sys.h"
#include "ballistica/audio/audio.h" #include "ballistica/audio/audio.h"
#include "ballistica/audio/audio_source.h" #include "ballistica/audio/audio_source.h"
#include "ballistica/audio/audio_streamer.h" #include "ballistica/audio/audio_streamer.h"
#include "ballistica/audio/ogg_stream.h" #include "ballistica/audio/ogg_stream.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/generic/timer.h" #include "ballistica/generic/timer.h"
#include "ballistica/logic/logic.h"
#include "ballistica/math/vector3f.h" #include "ballistica/math/vector3f.h"
#include "ballistica/media/data/sound_data.h"
#include "ballistica/media/media.h"
// Need to move away from OpenAL on Apple stuff. // Need to move away from OpenAL on Apple stuff.
#if __clang__ #if __clang__
@ -30,10 +30,10 @@ extern "C" void opensl_resume_playback();
extern std::string g_rift_audio_device_name; extern std::string g_rift_audio_device_name;
#endif #endif
const int kAudioProcessIntervalNormal = 500; const int kAudioProcessIntervalNormal{500};
const int kAudioProcessIntervalFade = 50; const int kAudioProcessIntervalFade{50};
const int kAudioProcessIntervalPendingLoad = 1; const int kAudioProcessIntervalPendingLoad{1};
const bool kShowInUseSounds = false; const bool kShowInUseSounds{};
int AudioServer::al_source_count_ = 0; int AudioServer::al_source_count_ = 0;
@ -55,7 +55,7 @@ class AudioServer::ThreadSource : public Object {
// not be used. // not be used.
ThreadSource(AudioServer* audio_thread, int id, bool* valid); ThreadSource(AudioServer* audio_thread, int id, bool* valid);
~ThreadSource() override; ~ThreadSource() override;
void Reset() { auto Reset() -> void {
SetIsMusic(false); SetIsMusic(false);
SetPositional(true); SetPositional(true);
SetPosition(0, 0, 0); SetPosition(0, 0, 0);
@ -66,18 +66,18 @@ class AudioServer::ThreadSource : public Object {
/// Set whether a sound is "music". /// Set whether a sound is "music".
/// This influences which volume controls affect it. /// This influences which volume controls affect it.
void SetIsMusic(bool m); auto SetIsMusic(bool m) -> void;
/// Set whether a source is positional. /// Set whether a source is positional.
/// A non-positional source's position coords are always relative to the /// A non-positional source's position coords are always relative to the
/// listener - ie: 0, 0, 0 will always be centered. /// listener - ie: 0, 0, 0 will always be centered.
void SetPositional(bool p); auto SetPositional(bool p) -> void;
void SetPosition(float x, float y, float z); auto SetPosition(float x, float y, float z) -> void;
void SetGain(float g); auto SetGain(float g) -> void;
void SetFade(float f); auto SetFade(float f) -> void;
void SetLooping(bool loop); auto SetLooping(bool loop) -> void;
auto Play(const Object::Ref<SoundData>* s) -> uint32_t; auto Play(const Object::Ref<SoundData>* s) -> uint32_t;
void Stop(); auto Stop() -> void;
auto play_count() -> uint32_t { return play_count_; } auto play_count() -> uint32_t { return play_count_; }
auto is_streamed() const -> bool { return is_streamed_; } auto is_streamed() const -> bool { return is_streamed_; }
auto current_is_music() const -> bool { return current_is_music_; } auto current_is_music() const -> bool { return current_is_music_; }
@ -86,41 +86,41 @@ class AudioServer::ThreadSource : public Object {
auto play_id() const -> uint32_t { auto play_id() const -> uint32_t {
return (play_count_ << 16u) | (static_cast<uint32_t>(id_) & 0xFFFFu); return (play_count_ << 16u) | (static_cast<uint32_t>(id_) & 0xFFFFu);
} }
void UpdateAvailability(); auto UpdateAvailability() -> void;
auto GetDefaultOwnerThread() const -> ThreadIdentifier override; auto GetDefaultOwnerThread() const -> ThreadTag override;
auto client_source() const -> AudioSource* { return client_source_.get(); } auto client_source() const -> AudioSource* { return client_source_.get(); }
auto source_sound() const -> SoundData* { auto source_sound() const -> SoundData* {
return source_sound_ ? source_sound_->get() : nullptr; return source_sound_ ? source_sound_->get() : nullptr;
} }
void UpdatePitch(); auto UpdatePitch() -> void;
void UpdateVolume(); auto UpdateVolume() -> void;
void ExecStop(); auto ExecStop() -> void;
void ExecPlay(); auto ExecPlay() -> void;
void Update(); auto Update() -> void;
private: private:
bool looping_ = false; bool looping_{};
std::unique_ptr<AudioSource> client_source_; std::unique_ptr<AudioSource> client_source_;
float fade_ = 1.0f; float fade_{1.0f};
float gain_ = 1.0f; float gain_{1.0f};
AudioServer* audio_thread_; AudioServer* audio_thread_{};
bool valid_ = false; bool valid_{};
const Object::Ref<SoundData>* source_sound_ = nullptr; const Object::Ref<SoundData>* source_sound_{};
int id_; int id_{};
uint32_t play_count_ = 0; uint32_t play_count_{};
bool is_actually_playing_ = false; bool is_actually_playing_{};
bool want_to_play_ = false; bool want_to_play_{};
#if BA_ENABLE_AUDIO #if BA_ENABLE_AUDIO
ALuint source_ = 0; ALuint source_{};
#endif #endif
bool is_streamed_ = false; bool is_streamed_{};
/// Whether we should be designated as "music" next time we play. /// Whether we should be designated as "music" next time we play.
bool is_music_ = false; bool is_music_{};
/// Whether currently playing as music. /// Whether currently playing as music.
bool current_is_music_ = false; bool current_is_music_{};
#if BA_ENABLE_AUDIO #if BA_ENABLE_AUDIO
Object::Ref<AudioStreamer> streamer_; Object::Ref<AudioStreamer> streamer_;
@ -144,7 +144,7 @@ struct AudioServer::SoundFadeNode {
void AudioServer::SetPaused(bool pause) { void AudioServer::SetPaused(bool pause) {
if (!paused_) { if (!paused_) {
if (!pause) { if (!pause) {
Log("Error: got audio unpause request when already unpaused."); Log(LogLevel::kError, "Got audio unpause request when already unpaused.");
} else { } else {
#if BA_OSTYPE_IOS_TVOS #if BA_OSTYPE_IOS_TVOS
// apple recommends this during audio-interruptions.. // apple recommends this during audio-interruptions..
@ -163,7 +163,7 @@ void AudioServer::SetPaused(bool pause) {
} else { } else {
// unpause if requested.. // unpause if requested..
if (pause) { if (pause) {
Log("Error: Got audio pause request when already paused."); Log(LogLevel::kError, "Got audio pause request when already paused.");
} else { } else {
#if BA_OSTYPE_IOS_TVOS #if BA_OSTYPE_IOS_TVOS
// apple recommends this during audio-interruptions.. // apple recommends this during audio-interruptions..
@ -321,24 +321,34 @@ void AudioServer::PushSetListenerOrientationCall(const Vector3f& forward,
}); });
} }
AudioServer::AudioServer(Thread* thread) AudioServer::AudioServer() : impl_{new AudioServer::Impl()} {
: thread_(thread), impl_{new AudioServer::Impl()} { // We're a singleton; make sure we don't already exist.
// we're a singleton...
assert(g_audio_server == nullptr); assert(g_audio_server == nullptr);
g_audio_server = this;
thread->AddPauseCallback(NewLambdaRunnableRaw([this] { OnThreadPause(); })); // Spin up our thread.
thread->AddResumeCallback(NewLambdaRunnableRaw([this] { OnThreadResume(); })); thread_ = new Thread(ThreadTag::kAudio);
g_app->pausable_threads.push_back(thread_);
}
auto AudioServer::OnAppStart() -> void {
thread_->PushCallSynchronous([this] { OnAppStartInThread(); });
}
auto AudioServer::OnAppStartInThread() -> void {
assert(InAudioThread());
thread()->AddPauseCallback(NewLambdaRunnableRaw([this] { OnThreadPause(); }));
thread()->AddResumeCallback(
NewLambdaRunnableRaw([this] { OnThreadResume(); }));
// Get our thread to give us periodic processing time. // Get our thread to give us periodic processing time.
process_timer_ = thread->NewTimer(kAudioProcessIntervalNormal, true, process_timer_ = thread()->NewTimer(kAudioProcessIntervalNormal, true,
NewLambdaRunnable([this] { Process(); })); NewLambdaRunnable([this] { Process(); }));
#if BA_ENABLE_AUDIO #if BA_ENABLE_AUDIO
// Bring up OpenAL stuff. // Bring up OpenAL stuff.
{ {
const char* alDeviceName = nullptr; const char* al_device_name = nullptr;
// On the rift build in vr mode we need to make sure we open the rift audio // On the rift build in vr mode we need to make sure we open the rift audio
// device. // device.
@ -347,7 +357,7 @@ AudioServer::AudioServer(Thread* thread)
ALboolean enumeration = ALboolean enumeration =
alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"); alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT");
if (enumeration == AL_FALSE) { if (enumeration == AL_FALSE) {
Log("OpenAL enumeration extensions missing."); Log(LogLevel::kError, "OpenAL enumeration extensions missing.");
} else { } else {
const ALCchar* devices = const ALCchar* devices =
alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER); alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
@ -357,26 +367,26 @@ AudioServer::AudioServer(Thread* thread)
// If the string is blank, we weren't able to find the oculus // If the string is blank, we weren't able to find the oculus
// audio device. In that case we'll just go with default. // audio device. In that case we'll just go with default.
if (g_rift_audio_device_name != "") { if (g_rift_audio_device_name != "") {
// Log("AL Devices list:"); // Log(LogLevel::kInfo, "AL Devices list:");
// Log("----------"); // Log(LogLevel::kInfo, "----------");
while (device && *device != '\0' && next && *next != '\0') { while (device && *device != '\0' && next && *next != '\0') {
// These names seem to be things like "OpenAL Soft on FOO" // These names seem to be things like "OpenAL Soft on FOO"
// ..we should be able to search for FOO. // ..we should be able to search for FOO.
if (strstr(device, g_rift_audio_device_name.c_str())) { if (strstr(device, g_rift_audio_device_name.c_str())) {
alDeviceName = device; al_device_name = device;
} }
len = strlen(device); len = strlen(device);
device += (len + 1); device += (len + 1);
next += (len + 2); next += (len + 2);
} }
// Log("----------"); // Log(LogLevel::kInfo, "----------");
} }
} }
} }
#endif // BA_RIFT_BUILD #endif // BA_RIFT_BUILD
ALCdevice* device; ALCdevice* device;
device = alcOpenDevice(alDeviceName); device = alcOpenDevice(al_device_name);
BA_PRECONDITION(device); BA_PRECONDITION(device);
impl_->alc_context_ = alcCreateContext(device, nullptr); impl_->alc_context_ = alcCreateContext(device, nullptr);
BA_PRECONDITION(impl_->alc_context_); BA_PRECONDITION(impl_->alc_context_);
@ -404,8 +414,8 @@ AudioServer::AudioServer(Thread* thread)
sound_source_refs_.push_back(s); sound_source_refs_.push_back(s);
sources_.push_back(&(*s)); sources_.push_back(&(*s));
} else { } else {
Log("Error: Made " + std::to_string(i) + " sources; (wanted " Log(LogLevel::kError, "Made " + std::to_string(i) + " sources; (wanted "
+ std::to_string(target_source_count) + ")."); + std::to_string(target_source_count) + ").");
break; break;
} }
} }
@ -463,9 +473,10 @@ void AudioServer::UpdateAvailableSources() {
// that probably means somebody's grabbing a source but never // that probably means somebody's grabbing a source but never
// resubmitting it. // resubmitting it.
if (t - i->client_source()->last_lock_time() > 10000) { if (t - i->client_source()->last_lock_time() > 10000) {
Log("Error: Client audio source has been locked for too long; " Log(LogLevel::kError,
"Client audio source has been locked for too long; "
"probably leaked. (debug id " "probably leaked. (debug id "
+ std::to_string(i->client_source()->lock_debug_id()) + ")"); + std::to_string(i->client_source()->lock_debug_id()) + ")");
} }
continue; continue;
} }
@ -601,7 +612,7 @@ void AudioServer::Process() {
// If we're paused we don't do nothin'. // If we're paused we don't do nothin'.
if (!paused_) { if (!paused_) {
// Do some loading... // Do some loading...
have_pending_loads_ = g_media->RunPendingAudioLoads(); have_pending_loads_ = g_assets->RunPendingAudioLoads();
// Keep that available-sources list filled. // Keep that available-sources list filled.
UpdateAvailableSources(); UpdateAvailableSources();
@ -666,7 +677,7 @@ void AudioServer::FadeSoundOut(uint32_t play_id, uint32_t time) {
std::make_pair(play_id, SoundFadeNode(play_id, time, true))); std::make_pair(play_id, SoundFadeNode(play_id, time, true)));
} }
void AudioServer::DeleteMediaComponent(MediaComponentData* c) { void AudioServer::DeleteAssetComponent(AssetComponentData* c) {
assert(InAudioThread()); assert(InAudioThread());
c->Unload(); c->Unload();
delete c; delete c;
@ -684,8 +695,8 @@ AudioServer::ThreadSource::ThreadSource(AudioServer* audio_thread_in, int id_in,
ALenum err = alGetError(); ALenum err = alGetError();
valid_ = (err == AL_NO_ERROR); valid_ = (err == AL_NO_ERROR);
if (!valid_) { if (!valid_) {
Log(std::string("Error: AL Error ") + GetALErrorString(err) Log(LogLevel::kError, std::string("AL Error ") + GetALErrorString(err)
+ " on source creation."); + " on source creation.");
} else { } else {
// In vr mode we keep the microphone a bit closer to the camera // In vr mode we keep the microphone a bit closer to the camera
// for realism purposes, so we need stuff louder in general. // for realism purposes, so we need stuff louder in general.
@ -702,7 +713,9 @@ AudioServer::ThreadSource::ThreadSource(AudioServer* audio_thread_in, int id_in,
CHECK_AL_ERROR; CHECK_AL_ERROR;
} }
*valid_out = valid_; *valid_out = valid_;
if (valid_) al_source_count_++; if (valid_) {
al_source_count_++;
}
#endif // BA_ENABLE_AUDIO #endif // BA_ENABLE_AUDIO
} }
@ -734,9 +747,8 @@ AudioServer::ThreadSource::~ThreadSource() {
#endif // BA_ENABLE_AUDIO #endif // BA_ENABLE_AUDIO
} }
auto AudioServer::ThreadSource::GetDefaultOwnerThread() const auto AudioServer::ThreadSource::GetDefaultOwnerThread() const -> ThreadTag {
-> ThreadIdentifier { return ThreadTag::kAudio;
return ThreadIdentifier::kAudio;
} }
void AudioServer::ThreadSource::UpdateAvailability() { void AudioServer::ThreadSource::UpdateAvailability() {
@ -867,9 +879,9 @@ void AudioServer::ThreadSource::SetPosition(float x, float y, float z) {
z = 500; z = 500;
} }
if (oob) { if (oob) {
BA_LOG_ONCE( BA_LOG_ONCE(LogLevel::kError,
"Error: AudioServer::ThreadSource::SetPosition" "AudioServer::ThreadSource::SetPosition"
" got out-of-bounds value."); " got out-of-bounds value.");
} }
ALfloat source_pos[] = {x, y, z}; ALfloat source_pos[] = {x, y, z};
alSourcefv(source_, AL_POSITION, source_pos); alSourcefv(source_, AL_POSITION, source_pos);
@ -1033,7 +1045,7 @@ void AudioServer::ThreadSource::Stop() {
// to free up... // to free up...
// (we can't kill media-refs outside the main thread) // (we can't kill media-refs outside the main thread)
if (source_sound_) { if (source_sound_) {
assert(g_media); assert(g_assets);
g_audio_server->AddSoundRefDelete(source_sound_); g_audio_server->AddSoundRefDelete(source_sound_);
source_sound_ = nullptr; source_sound_ = nullptr;
} }
@ -1087,22 +1099,22 @@ void AudioServer::PushSetSoundPitchCall(float val) {
void AudioServer::PushSetPausedCall(bool pause) { void AudioServer::PushSetPausedCall(bool pause) {
thread()->PushCall([this, pause] { thread()->PushCall([this, pause] {
if (g_buildconfig.ostype_android()) { if (g_buildconfig.ostype_android()) {
Log("Error: Shouldn't be getting SetPausedCall on android."); Log(LogLevel::kError, "Shouldn't be getting SetPausedCall on android.");
} }
SetPaused(pause); SetPaused(pause);
}); });
} }
void AudioServer::PushComponentUnloadCall( void AudioServer::PushComponentUnloadCall(
const std::vector<Object::Ref<MediaComponentData>*>& components) { const std::vector<Object::Ref<AssetComponentData>*>& components) {
thread()->PushCall([this, components] { thread()->PushCall([this, components] {
// Unload all components we were passed... // Unload all components we were passed...
for (auto&& i : components) { for (auto&& i : components) {
(**i).Unload(); (**i).Unload();
} }
// ...and then ship these pointers back to the game thread, so it can free // ...and then ship these pointers back to the logic thread, so it can free
// the references. // the references.
g_game->PushFreeMediaComponentRefsCall(components); g_logic->PushFreeAssetComponentRefsCall(components);
}); });
} }
@ -1118,8 +1130,9 @@ void AudioServer::AddSoundRefDelete(const Object::Ref<SoundData>* c) {
std::scoped_lock lock(sound_ref_delete_list_mutex_); std::scoped_lock lock(sound_ref_delete_list_mutex_);
sound_ref_delete_list_.push_back(c); sound_ref_delete_list_.push_back(c);
} }
// Now push a call to the game thread to do the deletes. // Now push a call to the logic thread to do the deletes.
g_game->thread()->PushCall([] { g_audio_server->ClearSoundRefDeleteList(); }); g_logic->thread()->PushCall(
[] { g_audio_server->ClearSoundRefDeleteList(); });
} }
void AudioServer::ClearSoundRefDeleteList() { void AudioServer::ClearSoundRefDeleteList() {
@ -1142,7 +1155,7 @@ void AudioServer::BeginInterruption() {
break; break;
} }
if (GetRealTime() - t > 1000) { if (GetRealTime() - t > 1000) {
Log("Error: Timed out waiting for audio pause."); Log(LogLevel::kError, "Timed out waiting for audio pause.");
break; break;
} }
Platform::SleepMS(2); Platform::SleepMS(2);
@ -1164,7 +1177,7 @@ void AudioServer::EndInterruption() {
break; break;
} }
if (GetRealTime() - t > 1000) { if (GetRealTime() - t > 1000) {
Log("Error: Timed out waiting for audio unpause."); Log(LogLevel::kError, "Timed out waiting for audio unpause.");
break; break;
} }
Platform::SleepMS(2); Platform::SleepMS(2);

View File

@ -22,45 +22,47 @@ class AudioServer {
return play_id >> 16u; return play_id >> 16u;
} }
explicit AudioServer(Thread* o); AudioServer();
auto OnAppStart() -> void;
void PushSetVolumesCall(float music_volume, float sound_volume); auto PushSetVolumesCall(float music_volume, float sound_volume) -> void;
void PushSetSoundPitchCall(float val); auto PushSetSoundPitchCall(float val) -> void;
void PushSetPausedCall(bool pause); auto PushSetPausedCall(bool pause) -> void;
static void BeginInterruption(); static auto BeginInterruption() -> void;
static void EndInterruption(); static auto EndInterruption() -> void;
void PushSetListenerPositionCall(const Vector3f& p); auto PushSetListenerPositionCall(const Vector3f& p) -> void;
void PushSetListenerOrientationCall(const Vector3f& forward, auto PushSetListenerOrientationCall(const Vector3f& forward,
const Vector3f& up); const Vector3f& up) -> void;
void PushResetCall(); auto PushResetCall() -> void;
void PushHavePendingLoadsCall(); auto PushHavePendingLoadsCall() -> void;
void PushComponentUnloadCall( auto PushComponentUnloadCall(
const std::vector<Object::Ref<MediaComponentData>*>& components); const std::vector<Object::Ref<AssetComponentData>*>& components) -> void;
/// For use by g_game_module(). /// For use by g_logic_module().
void ClearSoundRefDeleteList(); auto ClearSoundRefDeleteList() -> void;
auto paused() const -> bool { return paused_; } auto paused() const -> bool { return paused_; }
// Client sources use these to pass settings to the server. // Client sources use these to pass settings to the server.
void PushSourceSetIsMusicCall(uint32_t play_id, bool val); auto PushSourceSetIsMusicCall(uint32_t play_id, bool val) -> void;
void PushSourceSetPositionalCall(uint32_t play_id, bool val); auto PushSourceSetPositionalCall(uint32_t play_id, bool val) -> void;
void PushSourceSetPositionCall(uint32_t play_id, const Vector3f& p); auto PushSourceSetPositionCall(uint32_t play_id, const Vector3f& p) -> void;
void PushSourceSetGainCall(uint32_t play_id, float val); auto PushSourceSetGainCall(uint32_t play_id, float val) -> void;
void PushSourceSetFadeCall(uint32_t play_id, float val); auto PushSourceSetFadeCall(uint32_t play_id, float val) -> void;
void PushSourceSetLoopingCall(uint32_t play_id, bool val); auto PushSourceSetLoopingCall(uint32_t play_id, bool val) -> void;
void PushSourcePlayCall(uint32_t play_id, Object::Ref<SoundData>* sound); auto PushSourcePlayCall(uint32_t play_id, Object::Ref<SoundData>* sound)
void PushSourceStopCall(uint32_t play_id); -> void;
void PushSourceEndCall(uint32_t play_id); auto PushSourceStopCall(uint32_t play_id) -> void;
auto PushSourceEndCall(uint32_t play_id) -> void;
// Fade a playing sound out over the given time. If it is already // Fade a playing sound out over the given time. If it is already
// fading or does not exist, does nothing. // fading or does not exist, does nothing.
void FadeSoundOut(uint32_t play_id, uint32_t time); auto FadeSoundOut(uint32_t play_id, uint32_t time) -> void;
// Stop a sound from playing if it exists. // Stop a sound from playing if it exists.
void StopSound(uint32_t play_id); auto StopSound(uint32_t play_id) -> void;
auto thread() const -> Thread* { return thread_; } auto thread() const -> Thread* { return thread_; }
@ -68,16 +70,17 @@ class AudioServer {
class ThreadSource; class ThreadSource;
struct Impl; struct Impl;
auto OnAppStartInThread() -> void;
~AudioServer(); ~AudioServer();
auto OnThreadPause() -> void; auto OnThreadPause() -> void;
auto OnThreadResume() -> void; auto OnThreadResume() -> void;
void SetPaused(bool paused); auto SetPaused(bool paused) -> void;
void SetMusicVolume(float volume); auto SetMusicVolume(float volume) -> void;
void SetSoundVolume(float volume); auto SetSoundVolume(float volume) -> void;
void SetSoundPitch(float pitch); auto SetSoundPitch(float pitch) -> void;
auto music_volume() -> float { return music_volume_; } auto music_volume() -> float { return music_volume_; }
auto sound_volume() -> float { return sound_volume_; } auto sound_volume() -> float { return sound_volume_; }
auto sound_pitch() -> float { return sound_pitch_; } auto sound_pitch() -> float { return sound_pitch_; }
@ -85,22 +88,22 @@ class AudioServer {
/// If a sound play id is currently playing, return the sound. /// If a sound play id is currently playing, return the sound.
auto GetPlayingSound(uint32_t play_id) -> ThreadSource*; auto GetPlayingSound(uint32_t play_id) -> ThreadSource*;
void Reset(); auto Reset() -> void;
void Process(); auto Process() -> void;
/// Send a component to the audio thread to delete. /// Send a component to the audio thread to delete.
void DeleteMediaComponent(MediaComponentData* c); auto DeleteAssetComponent(AssetComponentData* c) -> void;
void UpdateTimerInterval(); auto UpdateTimerInterval() -> void;
void UpdateAvailableSources(); auto UpdateAvailableSources() -> void;
void UpdateMusicPlayState(); auto UpdateMusicPlayState() -> void;
void ProcessSoundFades(); auto ProcessSoundFades() -> void;
// Some threads such as audio hold onto allocated Media-Component-Refs to keep // Some threads such as audio hold onto allocated Media-Component-Refs to keep
// media components alive that they need. Media-Component-Refs, however, must // media components alive that they need. Media-Component-Refs, however, must
// be disposed of in the game thread, so they are passed back to it through // be disposed of in the logic thread, so they are passed back to it through
// this function. // this function.
void AddSoundRefDelete(const Object::Ref<SoundData>* c); auto AddSoundRefDelete(const Object::Ref<SoundData>* c) -> void;
// Note: should use unique_ptr for this, but build fails on raspberry pi // Note: should use unique_ptr for this, but build fails on raspberry pi
// (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later. // (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later.

View File

@ -2,10 +2,10 @@
#include "ballistica/audio/audio_source.h" #include "ballistica/audio/audio_source.h"
#include "ballistica/assets/data/sound_data.h"
#include "ballistica/audio/audio.h" #include "ballistica/audio/audio.h"
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/math/vector3f.h" #include "ballistica/math/vector3f.h"
#include "ballistica/media/data/sound_data.h"
namespace ballistica { namespace ballistica {
@ -41,7 +41,7 @@ void AudioSource::SetPosition(float x, float y, float z) {
assert(client_queue_size_ > 0); assert(client_queue_size_ > 0);
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
if (std::isnan(x) || std::isnan(y) || std::isnan(z)) { if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
Log("Error: Got nan value in AudioSource::SetPosition."); Log(LogLevel::kError, "Got nan value in AudioSource::SetPosition.");
} }
#endif #endif
g_audio_server->PushSourceSetPositionCall(play_id_, Vector3f(x, y, z)); g_audio_server->PushSourceSetPositionCall(play_id_, Vector3f(x, y, z));

View File

@ -86,8 +86,9 @@ void AudioStreamer::Update() {
// A fun anomaly in the linux version; we sometimes get more // A fun anomaly in the linux version; we sometimes get more
// "processed" buffers than we have queued. // "processed" buffers than we have queued.
if (queued < processed) { if (queued < processed) {
Log("Error: streamer oddness: queued(" + std::to_string(queued) Log(LogLevel::kError, "Streamer oddness: queued(" + std::to_string(queued)
+ "); processed(" + std::to_string(processed) + ")"); + "); processed(" + std::to_string(processed)
+ ")");
processed = queued; processed = queued;
} }

View File

@ -15,8 +15,8 @@ namespace ballistica {
// Provider for streamed audio data. // Provider for streamed audio data.
class AudioStreamer : public Object { class AudioStreamer : public Object {
public: public:
auto GetDefaultOwnerThread() const -> ThreadIdentifier override { auto GetDefaultOwnerThread() const -> ThreadTag override {
return ThreadIdentifier::kAudio; return ThreadTag::kAudio;
} }
AudioStreamer(const char* file_name, ALuint source, bool loop); AudioStreamer(const char* file_name, ALuint source, bool loop);
~AudioStreamer() override; ~AudioStreamer() override;

View File

@ -88,7 +88,8 @@ void OggStream::DoStream(char* pcm, int* size, unsigned int* rate) {
static bool reported_error = false; static bool reported_error = false;
if (!reported_error) { if (!reported_error) {
reported_error = true; reported_error = true;
Log("Error streaming ogg file: '" + file_name() + "'."); Log(LogLevel::kError,
"Error streaming ogg file: '" + file_name() + "'.");
} }
if (loops()) { if (loops()) {
ov_pcm_seek(&ogg_file_, 0); ov_pcm_seek(&ogg_file_, 0);

View File

@ -4,73 +4,69 @@
#include <map> #include <map>
#include "ballistica/app/app_config.h"
#include "ballistica/app/app_flavor.h" #include "ballistica/app/app_flavor.h"
#include "ballistica/assets/assets.h"
#include "ballistica/assets/assets_server.h"
#include "ballistica/audio/audio.h"
#include "ballistica/audio/audio_server.h" #include "ballistica/audio/audio_server.h"
#include "ballistica/core/fatal_error.h" #include "ballistica/core/fatal_error.h"
#include "ballistica/core/logging.h" #include "ballistica/core/logging.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/dynamics/bg/bg_dynamics_server.h" #include "ballistica/dynamics/bg/bg_dynamics_server.h"
#include "ballistica/game/account.h"
#include "ballistica/graphics/graphics_server.h" #include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/text/text_graphics.h"
#include "ballistica/input/input.h"
#include "ballistica/internal/app_internal.h" #include "ballistica/internal/app_internal.h"
#include "ballistica/media/media_server.h" #include "ballistica/logic/v1_account.h"
#include "ballistica/networking/network_write_module.h" #include "ballistica/networking/network_reader.h"
#include "ballistica/networking/network_writer.h"
#include "ballistica/networking/networking.h"
#include "ballistica/platform/platform.h" #include "ballistica/platform/platform.h"
#include "ballistica/platform/stdio_console.h"
#include "ballistica/python/python.h" #include "ballistica/python/python.h"
#include "ballistica/scene/scene.h" #include "ballistica/scene/scene.h"
#include "ballistica/scene/v1/scene_v1.h"
#include "ballistica/ui/ui.h"
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kAppBuildNumber = 20798; const int kAppBuildNumber = 20877;
const char* kAppVersion = "1.7.7"; const char* kAppVersion = "1.7.9";
// Our standalone globals. // Our standalone globals.
// These are separated out for easy access. // These are separated out for easy access.
// Everything else should go into App (or more ideally into a class). // Everything else should go into App (or more ideally into a class).
int g_early_log_writes{10}; int g_early_v1_cloud_log_writes{10};
Account* g_account{};
AppConfig* g_app_config{};
App* g_app{}; App* g_app{};
AppConfig* g_app_config{};
AppInternal* g_app_internal{}; AppInternal* g_app_internal{};
AppFlavor* g_app_flavor{}; AppFlavor* g_app_flavor{};
Assets* g_assets{};
AssetsServer* g_assets_server{};
Audio* g_audio{}; Audio* g_audio{};
AudioServer* g_audio_server{}; AudioServer* g_audio_server{};
BGDynamics* g_bg_dynamics{}; BGDynamics* g_bg_dynamics{};
BGDynamicsServer* g_bg_dynamics_server{}; BGDynamicsServer* g_bg_dynamics_server{};
Game* g_game{}; Context* g_context{};
Graphics* g_graphics{}; Graphics* g_graphics{};
GraphicsServer* g_graphics_server{}; GraphicsServer* g_graphics_server{};
Input* g_input{}; Input* g_input{};
Logic* g_logic{};
Thread* g_main_thread{}; Thread* g_main_thread{};
Media* g_media{};
MediaServer* g_media_server{};
NetworkReader* g_network_reader{};
Networking* g_networking{}; Networking* g_networking{};
NetworkWriteModule* g_network_write_module{}; NetworkReader* g_network_reader{};
NetworkWriter* g_network_writer{};
Platform* g_platform{}; Platform* g_platform{};
Python* g_python{}; Python* g_python{};
StdInputModule* g_std_input_module{}; SceneV1* g_scene_v1{};
StdioConsole* g_stdio_console{};
TextGraphics* g_text_graphics{}; TextGraphics* g_text_graphics{};
UI* g_ui{}; UI* g_ui{};
Utils* g_utils{}; Utils* g_utils{};
V1Account* g_v1_account{};
// Basic overview of our bootstrapping process:
// 1: All threads and globals are created and provisioned. Everything above
// should exist at the end of this step (if it is going to exist).
// Threads should not be talking to each other yet at this point.
// 2: The system is set in motion. Game thread is told to load/apply the config.
// This event kicks off an initial-screen-creation message sent to the
// graphics-server thread. Other systems are informed that bootstrapping
// is complete and that they are free to talk to each other. Initial
// input-devices are added, media loads can begin (at least ones not
// dependent on the screen/renderer), etc.
// 3: The initial screen is created on the graphics-server thread in response
// to the message sent from the game thread. A completion notice is sent
// back to the game thread when done.
// 4: Back on the game thread, any renderer-dependent media-loads/etc. can begin
// and lastly the initial game session is kicked off.
auto BallisticaMain(int argc, char** argv) -> int { auto BallisticaMain(int argc, char** argv) -> int {
try { try {
@ -83,77 +79,107 @@ auto BallisticaMain(int argc, char** argv) -> int {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Phase 1: Create and provision all globals. // Phase 1: "The board is set."
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Absolute bare-bones basics. // Here we instantiate all of our globals. Code here should
g_app = new App(argc, argv); // avoid any logic that accesses other globals since they may
// not yet exist.
// Minimal globals we must assign immediately as they ARE needed
// for construction of the others (would be great to eliminate this need).
g_platform = Platform::Create(); g_platform = Platform::Create();
g_app = new App(argc, argv);
g_app_internal = CreateAppInternal();
g_main_thread = new Thread(ThreadTag::kMain, ThreadSource::kWrapMain);
// If we're not running under a Python executable, we need to set up // For everything else, we hold off until the end to actually assign
// our own Python environment. // them to their globals. This keeps us honest and catches any stray
assert(g_python == nullptr); // inter-global access that we might accidentally include in a
g_python = new Python(); // constructor.
auto* app_flavor = g_platform->CreateAppFlavor();
auto* python = Python::Create();
auto* graphics = g_platform->CreateGraphics();
auto* graphics_server = new GraphicsServer();
auto* audio = new Audio();
auto* audio_server = new AudioServer();
auto* context = new Context(nullptr);
auto* text_graphics = new TextGraphics();
auto* app_config = new AppConfig();
auto* v1_account = new V1Account();
auto* utils = new Utils();
auto* assets = new Assets();
auto* assets_server = new AssetsServer();
auto* ui = Object::NewUnmanaged<UI>();
auto* networking = new Networking();
auto* network_reader = new NetworkReader();
auto* network_writer = new NetworkWriter();
auto* input = new Input();
auto* logic = new Logic();
auto* scene_v1 = new SceneV1();
auto* bg_dynamics = HeadlessMode() ? nullptr : new BGDynamics;
auto* bg_dynamics_server = HeadlessMode() ? nullptr : new BGDynamicsServer;
auto* stdio_console =
g_buildconfig.enable_stdio_console() ? new StdioConsole() : nullptr;
// Create a Thread wrapper around the current (main) thread. g_app_flavor = app_flavor;
g_main_thread = new Thread(ThreadIdentifier::kMain, ThreadType::kMain); g_python = python;
Thread::UpdateMainThreadID(); g_graphics = graphics;
g_graphics_server = graphics_server;
g_audio = audio;
g_audio_server = audio_server;
g_context = context;
g_text_graphics = text_graphics;
g_app_config = app_config;
g_v1_account = v1_account;
g_utils = utils;
g_assets = assets;
g_assets_server = assets_server;
g_ui = ui;
g_networking = networking;
g_network_reader = network_reader;
g_network_writer = network_writer;
g_input = input;
g_logic = logic;
g_scene_v1 = scene_v1;
g_bg_dynamics = bg_dynamics;
g_bg_dynamics_server = bg_dynamics_server;
g_stdio_console = stdio_console;
// Spin up our specific app variation (VR, headless, regular, etc.)
g_app_flavor = g_platform->CreateAppFlavor();
g_app_flavor->PostInit();
g_account = new Account();
g_utils = new Utils();
Scene::Init();
// Spin up our other standard threads.
auto* media_thread{new Thread(ThreadIdentifier::kMedia)};
g_app->pausable_threads.push_back(media_thread);
auto* audio_thread{new Thread(ThreadIdentifier::kAudio)};
g_app->pausable_threads.push_back(audio_thread);
auto* logic_thread{new Thread(ThreadIdentifier::kLogic)};
g_app->pausable_threads.push_back(logic_thread);
auto* network_write_thread{new Thread(ThreadIdentifier::kNetworkWrite)};
g_app->pausable_threads.push_back(network_write_thread);
// Spin up our subsystems in those threads.
logic_thread->PushCallSynchronous(
[logic_thread] { new Game(logic_thread); });
network_write_thread->PushCallSynchronous([network_write_thread] {
new NetworkWriteModule(network_write_thread);
});
media_thread->PushCallSynchronous(
[media_thread] { new MediaServer(media_thread); });
new GraphicsServer(g_main_thread);
audio_thread->PushCallSynchronous(
[audio_thread] { new AudioServer(audio_thread); });
// Now let the platform spin up any other threads/modules it uses.
// (bg-dynamics in non-headless builds, stdin/stdout where applicable,
// etc.)
g_platform->CreateAuxiliaryModules();
// Ok at this point we can be considered up-and-running.
g_app->is_bootstrapped = true; g_app->is_bootstrapped = true;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Phase 2: Set things in motion. // Phase 2: "The pieces are moving."
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Let the app and platform do whatever else it wants here such as adding // Allow our subsystems to start doing work in their own threads
// initial input devices/etc. // and communicating with other subsystems. Note that we may still
g_app_flavor->OnBootstrapComplete(); // want to run some things serially here and ordering may be important
g_platform->OnBootstrapComplete(); // (for instance we want to give our main thread a chance to register
// all initial input devices with the logic thread before the logic
// thread applies the current config to them).
// Ok; now that we're bootstrapped, tell the game thread to read and apply g_logic->OnAppStart();
// the config which should kick off the real action. g_audio_server->OnAppStart();
g_game->PushApplyConfigCall(); g_assets_server->OnAppStart();
g_platform->OnAppStart();
g_app_flavor->OnAppStart();
if (g_stdio_console) {
g_stdio_console->OnAppStart();
}
// As the last step of this phase, tell the logic thread to apply
// the app config which will kick off screen creation and otherwise
// get the ball rolling.
g_logic->PushApplyConfigCall();
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Phase 3/4: Create a screen and/or kick off game (in other threads). // Phase 3: "We come to it at last; the great battle of our time."
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// At this point all threads are off and running and we simply
// feed events until things end (or return and let the OS do that).
if (g_app_flavor->ManagesEventLoop()) { if (g_app_flavor->ManagesEventLoop()) {
// On our event-loop-managing platforms we now simply sit in our event // On our event-loop-managing platforms we now simply sit in our event
// loop until the app is quit. // loop until the app is quit.
@ -223,77 +249,87 @@ auto FatalError(const std::string& message) -> void {
FatalError::ReportFatalError(message, false); FatalError::ReportFatalError(message, false);
bool exit_cleanly = !IsUnmodifiedBlessedBuild(); bool exit_cleanly = !IsUnmodifiedBlessedBuild();
bool handled = FatalError::HandleFatalError(exit_cleanly, false); bool handled = FatalError::HandleFatalError(exit_cleanly, false);
assert(handled); BA_PRECONDITION(handled);
} }
// FIXME: move this to g_app or whatnot.
auto GetAppInstanceUUID() -> const std::string& { auto GetAppInstanceUUID() -> const std::string& {
static std::string session_id; static std::string app_instance_uuid;
static bool have_session_id = false; static bool have_app_instance_uuid = false;
if (!have_session_id) { if (!have_app_instance_uuid) {
if (g_python) { if (g_python) {
Python::ScopedInterpreterLock gil; Python::ScopedInterpreterLock gil;
auto uuid = g_python->obj(Python::ObjID::kUUIDStrCall).Call(); auto uuid = g_python->obj(Python::ObjID::kUUIDStrCall).Call();
if (uuid.exists()) { if (uuid.exists()) {
session_id = uuid.ValueAsString().c_str(); app_instance_uuid = uuid.ValueAsString().c_str();
have_session_id = true; have_app_instance_uuid = true;
} }
} }
if (!have_session_id) { if (!have_app_instance_uuid) {
// As an emergency fallback simply use a single random number. // As an emergency fallback simply use a single random number.
Log("WARNING: GetSessionUUID() using rand fallback."); // We should probably simply disallow this before Python is up.
Log(LogLevel::kWarning, "GetSessionUUID() using rand fallback.");
srand(static_cast<unsigned int>( srand(static_cast<unsigned int>(
Platform::GetCurrentMilliseconds())); // NOLINT Platform::GetCurrentMilliseconds())); // NOLINT
session_id = std::to_string(static_cast<uint32_t>(rand())); // NOLINT app_instance_uuid =
have_session_id = true; std::to_string(static_cast<uint32_t>(rand())); // NOLINT
have_app_instance_uuid = true;
} }
if (session_id.size() >= 100) { if (app_instance_uuid.size() >= 100) {
Log("WARNING: session id longer than it should be."); Log(LogLevel::kWarning, "session id longer than it should be.");
} }
} }
return session_id; return app_instance_uuid;
}
auto InLogicThread() -> bool {
return (g_game && g_game->thread()->IsCurrent());
} }
auto InMainThread() -> bool { auto InMainThread() -> bool {
return (g_app && std::this_thread::get_id() == g_app->main_thread_id); assert(g_main_thread); // Root out early use of this.
return (g_main_thread->IsCurrent());
}
auto InLogicThread() -> bool {
assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
return (g_logic && g_logic->thread()->IsCurrent());
} }
auto InGraphicsThread() -> bool { auto InGraphicsThread() -> bool {
assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
return (g_graphics_server && g_graphics_server->thread()->IsCurrent()); return (g_graphics_server && g_graphics_server->thread()->IsCurrent());
} }
auto InAudioThread() -> bool { auto InAudioThread() -> bool {
assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
return (g_audio_server && g_audio_server->thread()->IsCurrent()); return (g_audio_server && g_audio_server->thread()->IsCurrent());
} }
auto InBGDynamicsThread() -> bool { auto InBGDynamicsThread() -> bool {
assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
return (g_bg_dynamics_server && g_bg_dynamics_server->thread()->IsCurrent()); return (g_bg_dynamics_server && g_bg_dynamics_server->thread()->IsCurrent());
} }
auto InMediaThread() -> bool { auto InAssetsThread() -> bool {
return (g_media_server && g_media_server->thread()->IsCurrent()); assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
return (g_assets_server && g_assets_server->thread()->IsCurrent());
} }
auto InNetworkWriteThread() -> bool { auto InNetworkWriteThread() -> bool {
return (g_network_write_module assert(g_app && g_app->is_bootstrapped); // Root out early use of this.
&& g_network_write_module->thread()->IsCurrent()); return (g_network_writer && g_network_writer->thread()->IsCurrent());
} }
auto Log(const std::string& msg, bool to_stdout, bool to_server) -> void { auto Log(LogLevel level, const std::string& msg) -> void {
Logging::Log(msg, to_stdout, to_server); Logging::Log(level, msg);
} }
auto IsVRMode() -> bool { return g_app->vr_mode; } auto IsVRMode() -> bool { return g_app->vr_mode; }
void ScreenMessage(const std::string& s, const Vector3f& color) { void ScreenMessage(const std::string& s, const Vector3f& color) {
if (g_game) { if (g_logic) {
g_game->PushScreenMessage(s, color); g_logic->PushScreenMessage(s, color);
} else { } else {
Log("ScreenMessage before g_game init (will be lost): '" + s + "'"); Log(LogLevel::kError,
"ScreenMessage before g_logic init (will be lost): '" + s + "'");
} }
} }

View File

@ -5,28 +5,14 @@
// Try to ensure they're providing proper config stuff. // Try to ensure they're providing proper config stuff.
#ifndef BA_HAVE_CONFIG #ifndef BA_HAVE_CONFIG
#error platform config has not been defined! #error ballistica platform config has not been defined!
#endif #endif
// FIXME: We need to update to C++17 to get unified std::abs().
// Until we do that, int types are defined in <cstdlib>
// and float/double in <cmath>, meaning its possible to call the wrong
// version if we aren't careful and only include one header.
// For now just including both here at the top level to hopefully
// minimize problems.
// UPDATE: We should now be building with C++17 everywhere; should add a
// check to ensure that is the case and can simplify this.
#ifdef __cplusplus #ifdef __cplusplus
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <set>
#include <stdexcept>
#include <string> #include <string>
#include <thread>
#include <vector>
#endif #endif
// Minimum functionality we want available everywhere we are included.
#include "ballistica/core/exception.h" #include "ballistica/core/exception.h"
#include "ballistica/core/inline.h" #include "ballistica/core/inline.h"
#include "ballistica/core/macros.h" #include "ballistica/core/macros.h"
@ -116,8 +102,8 @@ const float kGameStepSeconds =
(static_cast<float>(kGameStepMilliseconds) / 1000.0f); (static_cast<float>(kGameStepMilliseconds) / 1000.0f);
// Globals. // Globals.
extern int g_early_log_writes; extern int g_early_v1_cloud_log_writes;
extern Account* g_account; extern V1Account* g_v1_account;
extern AppFlavor* g_app_flavor; extern AppFlavor* g_app_flavor;
extern AppConfig* g_app_config; extern AppConfig* g_app_config;
extern App* g_app; extern App* g_app;
@ -127,19 +113,20 @@ extern AudioServer* g_audio_server;
extern BGDynamics* g_bg_dynamics; extern BGDynamics* g_bg_dynamics;
extern BGDynamicsServer* g_bg_dynamics_server; extern BGDynamicsServer* g_bg_dynamics_server;
extern Context* g_context; extern Context* g_context;
extern Game* g_game;
extern Graphics* g_graphics; extern Graphics* g_graphics;
extern GraphicsServer* g_graphics_server; extern GraphicsServer* g_graphics_server;
extern Input* g_input; extern Input* g_input;
extern Logic* g_logic;
extern Thread* g_main_thread; extern Thread* g_main_thread;
extern Media* g_media; extern Assets* g_assets;
extern MediaServer* g_media_server; extern AssetsServer* g_assets_server;
extern Networking* g_networking; extern Networking* g_networking;
extern NetworkReader* g_network_reader; extern NetworkReader* g_network_reader;
extern NetworkWriteModule* g_network_write_module; extern NetworkWriter* g_network_writer;
extern Platform* g_platform; extern Platform* g_platform;
extern Python* g_python; extern Python* g_python;
extern StdInputModule* g_std_input_module; extern SceneV1* g_scene_v1;
extern StdioConsole* g_stdio_console;
extern TextGraphics* g_text_graphics; extern TextGraphics* g_text_graphics;
extern UI* g_ui; extern UI* g_ui;
extern Utils* g_utils; extern Utils* g_utils;
@ -172,17 +159,20 @@ auto InGraphicsThread() -> bool; // (main and graphics are same currently)
auto InLogicThread() -> bool; auto InLogicThread() -> bool;
auto InAudioThread() -> bool; auto InAudioThread() -> bool;
auto InBGDynamicsThread() -> bool; auto InBGDynamicsThread() -> bool;
auto InMediaThread() -> bool; auto InAssetsThread() -> bool;
auto InNetworkWriteThread() -> bool; auto InNetworkWriteThread() -> bool;
/// Return a human-readable name for the current thread. /// Return a human-readable name for the current thread.
auto GetCurrentThreadName() -> std::string; auto GetCurrentThreadName() -> std::string;
/// Write a string to the log. /// Submit a log entry.
/// This will go to stdout, windows debug log, android log, etc. /// Can be called from any thread at any time.
/// A trailing newline will be added. /// Use either this or Python printing functionality for anything
auto Log(const std::string& msg, bool to_stdout = true, bool to_server = true) /// that should be seen by the user, as both of those will end up
-> void; /// in the in-app console, cloud based consoles, android log, etc.
/// Regular C level prints to stdout/stderr will not and will only
/// be visible on some platforms.
auto Log(LogLevel level, const std::string& msg) -> void;
/// Log a fatal error and kill the app. /// Log a fatal error and kill the app.
/// Can be called from any thread at any time. /// Can be called from any thread at any time.

View File

@ -62,7 +62,7 @@
#define BA_ENABLE_EXECINFO_BACKTRACES 1 #define BA_ENABLE_EXECINFO_BACKTRACES 1
// Allow stdin commands too. // Allow stdin commands too.
#define BA_USE_STDIN_THREAD 1 #define BA_ENABLE_STDIO_CONSOLE 1
#define BA_DEFINE_MAIN 1 #define BA_DEFINE_MAIN 1

View File

@ -122,8 +122,8 @@ namespace ballistica {
#error platform string undefined #error platform string undefined
#endif #endif
#ifndef BA_USE_STDIN_THREAD #ifndef BA_ENABLE_STDIO_CONSOLE
#define BA_USE_STDIN_THREAD 0 #define BA_ENABLE_STDIO_CONSOLE 0
#endif #endif
#ifndef BA_HARDWARE_CURSOR #ifndef BA_HARDWARE_CURSOR
@ -240,7 +240,9 @@ class BuildConfig {
bool use_store_kit() const { return EXPBOOL_(BA_USE_STORE_KIT); } bool use_store_kit() const { return EXPBOOL_(BA_USE_STORE_KIT); }
bool use_game_center() const { return EXPBOOL_(BA_USE_GAME_CENTER); } bool use_game_center() const { return EXPBOOL_(BA_USE_GAME_CENTER); }
bool use_stdin_thread() const { return EXPBOOL_(BA_USE_STDIN_THREAD); } bool enable_stdio_console() const {
return EXPBOOL_(BA_ENABLE_STDIO_CONSOLE);
}
bool enable_os_font_rendering() const { bool enable_os_font_rendering() const {
return EXPBOOL_(BA_ENABLE_OS_FONT_RENDERING); return EXPBOOL_(BA_ENABLE_OS_FONT_RENDERING);
} }

View File

@ -5,7 +5,7 @@
// note: define overrides BEFORE common makefile // note: define overrides BEFORE common makefile
#define BA_USE_STDIN_THREAD 1 #define BA_ENABLE_STDIO_CONSOLE 1
#define BA_SDL_BUILD 1 #define BA_SDL_BUILD 1
#define BA_SDL2_BUILD 1 #define BA_SDL2_BUILD 1

View File

@ -6,7 +6,7 @@
// note: define overrides BEFORE common header // note: define overrides BEFORE common header
#define BA_HEADLESS_BUILD 1 #define BA_HEADLESS_BUILD 1
#define BA_USE_STDIN_THREAD 1 #define BA_ENABLE_STDIO_CONSOLE 1
#define BA_MINSDL_BUILD 1 #define BA_MINSDL_BUILD 1

View File

@ -2,20 +2,12 @@
#include "ballistica/core/context.h" #include "ballistica/core/context.h"
#include "ballistica/game/host_activity.h"
#include "ballistica/generic/runnable.h" #include "ballistica/generic/runnable.h"
#include "ballistica/logic/host_activity.h"
#include "ballistica/ui/ui.h" #include "ballistica/ui/ui.h"
namespace ballistica { namespace ballistica {
// Dynamically allocate this; don't want it torn down on quit.
Context* g_context = nullptr;
void Context::Init() {
assert(!g_context);
g_context = new Context(nullptr);
}
ContextTarget::ContextTarget() = default; ContextTarget::ContextTarget() = default;
ContextTarget::~ContextTarget() = default; ContextTarget::~ContextTarget() = default;
@ -108,7 +100,7 @@ auto ContextTarget::NewTimer(TimeType timetype, TimerMedium length, bool repeat,
void ContextTarget::DeleteTimer(TimeType timetype, int timer_id) { void ContextTarget::DeleteTimer(TimeType timetype, int timer_id) {
// We throw on NewTimer; lets just ignore anything that comes // We throw on NewTimer; lets just ignore anything that comes
// through here to avoid messing up destructors. // through here to avoid messing up destructors.
Log("ContextTarget::DeleteTimer() called; unexpected."); Log(LogLevel::kError, "ContextTarget::DeleteTimer() called; unexpected.");
} }
auto ContextTarget::GetTime(TimeType timetype) -> millisecs_t { auto ContextTarget::GetTime(TimeType timetype) -> millisecs_t {

View File

@ -14,18 +14,16 @@ namespace ballistica {
// effects properly apply to the place they came from. // effects properly apply to the place they came from.
class Context { class Context {
public: public:
static void Init();
static auto current() -> const Context& { static auto current() -> const Context& {
assert(g_context); assert(g_context);
// Context can only be accessed from the game thread. // Context can only be accessed from the logic thread.
BA_PRECONDITION(InLogicThread()); BA_PRECONDITION(InLogicThread());
return *g_context; return *g_context;
} }
static void set_current(const Context& context) { static void set_current(const Context& context) {
// Context can only be accessed from the game thread. // Context can only be accessed from the logic thread.
BA_PRECONDITION(InLogicThread()); BA_PRECONDITION(InLogicThread());
*g_context = context; *g_context = context;

View File

@ -27,7 +27,7 @@ auto FatalError::ReportFatalError(const std::string& message,
// error to the user and exiting the app cleanly (so we don't pollute our // error to the user and exiting the app cleanly (so we don't pollute our
// crash records with results of user tinkering). // crash records with results of user tinkering).
// Give the platform the opportunity to completely override our handling. // Give the platform the opportunity to augment or override our handling.
if (g_platform) { if (g_platform) {
auto handled = auto handled =
g_platform->ReportFatalError(message, in_top_level_exception_handler); g_platform->ReportFatalError(message, in_top_level_exception_handler);
@ -38,7 +38,8 @@ auto FatalError::ReportFatalError(const std::string& message,
std::string dialog_msg = message; std::string dialog_msg = message;
if (!dialog_msg.empty()) { if (!dialog_msg.empty()) {
dialog_msg += "\n"; // Why was this here?
// dialog_msg += "\n";
} }
auto starttime = time(nullptr); auto starttime = time(nullptr);
@ -69,11 +70,16 @@ auto FatalError::ReportFatalError(const std::string& message,
} }
} }
// Prevent the early-log insta-send mechanism from firing since we do // Prevent the early-v1-cloud-log insta-send mechanism from firing since
// basically the same thing ourself here (avoid sending the same logs twice). // we do basically the same thing ourself here (avoid sending the same
g_early_log_writes = 0; // logs twice).
g_early_v1_cloud_log_writes = 0;
Logging::Log(logmsg); // Add this to our V1CloudLog which we'll be attempting to send momentarily,
// and also go to platform-specific logging and good ol' stderr.
Logging::V1CloudLog(logmsg);
Logging::DisplayLog("root", LogLevel::kCritical, logmsg);
fprintf(stderr, "%s\n", logmsg.c_str());
std::string prefix = "FATAL-ERROR-LOG:"; std::string prefix = "FATAL-ERROR-LOG:";
std::string suffix; std::string suffix;
@ -83,7 +89,7 @@ auto FatalError::ReportFatalError(const std::string& message,
if (g_app == nullptr) { if (g_app == nullptr) {
suffix = logmsg; suffix = logmsg;
} }
g_app_internal->DirectSendLogs(prefix, suffix, true, &result); g_app_internal->DirectSendV1CloudLogs(prefix, suffix, true, &result);
// If we're able to show a fatal-error dialog synchronously, do so. // If we're able to show a fatal-error dialog synchronously, do so.
if (g_platform && g_platform->CanShowBlockingFatalErrorDialog()) { if (g_platform && g_platform->CanShowBlockingFatalErrorDialog()) {
@ -148,10 +154,10 @@ auto FatalError::HandleFatalError(bool exit_cleanly,
// bring the app down ourself. // bring the app down ourself.
if (!in_top_level_exception_handler) { if (!in_top_level_exception_handler) {
if (exit_cleanly) { if (exit_cleanly) {
Log("Calling exit(1)..."); Logging::DisplayLog("root", LogLevel::kCritical, "Calling exit(1)...");
exit(1); exit(1);
} else { } else {
Log("Calling abort()..."); Logging::DisplayLog("root", LogLevel::kCritical, "Calling abort()...");
abort(); abort();
} }
} }

View File

@ -5,106 +5,103 @@
#include <map> #include <map>
#include "ballistica/app/app.h" #include "ballistica/app/app.h"
#include "ballistica/game/game.h"
#include "ballistica/internal/app_internal.h" #include "ballistica/internal/app_internal.h"
#include "ballistica/logic/logic.h"
#include "ballistica/networking/telnet_server.h" #include "ballistica/networking/telnet_server.h"
#include "ballistica/platform/platform.h" #include "ballistica/platform/platform.h"
#include "ballistica/python/python.h" #include "ballistica/python/python.h"
namespace ballistica { namespace ballistica {
static void PrintCommon(const std::string& s) { auto Logging::Log(LogLevel level, const std::string& msg) -> void {
// This is basically up to Python to handle, but its up to us
// if Python's not up yet.
if (!g_python) {
// Make an attempt to get it at least seen (and note the fact
// that its super-early).
const char* errmsg{"Logging::Log() called before g_python exists."};
if (g_platform) {
g_platform->DisplayLog("root", LogLevel::kError, errmsg);
g_platform->DisplayLog("root", level, msg);
}
fprintf(stderr, "%s\n%s\n", errmsg, msg.c_str());
return;
}
// All we want to do is call Python logging.XXX. That's on Python.
g_python->LoggingCall(level, msg);
}
auto Logging::DisplayLog(const std::string& name, LogLevel level,
const std::string& msg) -> void {
auto msgnewline{msg + "\n"};
// Print to in-game console. // Print to in-game console.
{ {
if (g_game != nullptr) { if (g_logic != nullptr) {
g_game->PushConsolePrintCall(s); g_logic->PushConsolePrintCall(msgnewline);
} else { } else {
if (g_platform != nullptr) { if (g_platform != nullptr) {
g_platform->HandleLog( g_platform->DisplayLog("root", LogLevel::kWarning,
"Warning: Log() called before game-thread setup; " "DisplayLog() called before logic-thread setup; "
"will not appear on in-game console.\n"); "will not appear on in-game console.");
} }
} }
} }
// Print to any telnet clients. // Print to any telnet clients.
if (g_app && g_app->telnet_server) { if (g_app && g_app->telnet_server) {
g_app->telnet_server->PushPrint(s); g_app->telnet_server->PushPrint(msgnewline);
} }
// Ship to platform-specific display mechanisms (android log, etc).
g_platform->DisplayLog(name, level, msg);
} }
void Logging::PrintStdout(const std::string& s, bool flush) { auto Logging::V1CloudLog(const std::string& msg) -> void {
fprintf(stdout, "%s", s.c_str()); // Route through platform-specific loggers if present.
if (flush) { // (things like Crashlytics crash-logging)
fflush(stdout); if (g_platform) {
} Platform::DebugLog(msg);
PrintCommon(s);
}
void Logging::PrintStderr(const std::string& s, bool flush) {
fprintf(stderr, "%s", s.c_str());
if (flush) {
fflush(stderr);
}
PrintCommon(s);
}
void Logging::Log(const std::string& msg, bool to_stdout, bool to_server) {
if (to_stdout) {
PrintStdout(msg + "\n", true);
} }
// Ship to the platform logging mechanism (android-log, stderr, etc.) // Add to our complete v1-cloud-log.
// if that's available yet. if (g_app != nullptr) {
if (g_platform != nullptr) { std::scoped_lock lock(g_app->v1_cloud_log_mutex);
g_platform->HandleLog(msg); if (!g_app->v1_cloud_log_full) {
} (g_app->v1_cloud_log) += (msg + "\n");
if ((g_app->v1_cloud_log).size() > 10000) {
// Ship to master-server/etc. // Allow some reasonable overflow for last statement.
if (to_server) { if ((g_app->v1_cloud_log).size() > 100000) {
// Route through platform-specific loggers if present. // FIXME: This could potentially chop up utf-8 chars.
// (things like Crashlytics crash-logging) (g_app->v1_cloud_log).resize(100000);
if (g_platform) {
Platform::DebugLog(msg);
}
// Add to our complete log.
if (g_app != nullptr) {
std::scoped_lock lock(g_app->log_mutex);
if (!g_app->log_full) {
(g_app->log) += (msg + "\n");
if ((g_app->log).size() > 10000) {
// Allow some reasonable overflow for last statement.
if ((g_app->log).size() > 100000) {
// FIXME: This could potentially chop up utf-8 chars.
(g_app->log).resize(100000);
}
g_app->log += "\n<max log size reached>\n";
g_app->log_full = true;
} }
g_app->v1_cloud_log += "\n<max log size reached>\n";
g_app->v1_cloud_log_full = true;
} }
} }
}
// If the game is fully bootstrapped, let the Python layer handle logs. // If the game is fully bootstrapped, let the Python layer handle logs.
// It will group log messages intelligently and ship them to the // It will group log messages intelligently and ship them to the
// master server with various other context info included. // master server with various other context info included.
if (g_app && g_app->is_bootstrapped) { if (g_app && g_app->is_bootstrapped) {
assert(g_python != nullptr); assert(g_python != nullptr);
g_python->PushObjCall(Python::ObjID::kHandleLogCall); g_python->PushObjCall(Python::ObjID::kHandleV1CloudLogCall);
} else { } else {
// For log messages during bootstrapping we ship them immediately since // For log messages during bootstrapping we ship them immediately since
// we don't know if the Python layer is (or will be) able to. // we don't know if the Python layer is (or will be) able to.
if (g_early_log_writes > 0) { if (g_early_v1_cloud_log_writes > 0) {
g_early_log_writes -= 1; g_early_v1_cloud_log_writes -= 1;
std::string logprefix = "EARLY-LOG:"; std::string logprefix = "EARLY-LOG:";
std::string logsuffix; std::string logsuffix;
// If we're an early enough error, our global log isn't even available, // If we're an early enough error, our global log isn't even available,
// so include this specific message as a suffix instead. // so include this specific message as a suffix instead.
if (g_app == nullptr) { if (g_app == nullptr) {
logsuffix = msg; logsuffix = msg;
}
g_app_internal->DirectSendLogs(logprefix, logsuffix, false);
} }
g_app_internal->DirectSendV1CloudLogs(logprefix, logsuffix, false);
} }
} }
} }

View File

@ -5,23 +5,33 @@
#include <string> #include <string>
#include "ballistica/ballistica.h"
namespace ballistica { namespace ballistica {
class Logging { class Logging {
public: public:
/// Print a string directly to stdout as well as the in-game console /// Write a message to the log. Intended for logging use in C++ code.
/// and any connected telnet consoles. /// This is safe to call by any thread at any time. In general it simply
static auto PrintStdout(const std::string& s, bool flush = false) -> void; /// passes through to the equivalent Python log calls: logging.info,
/// logging.warning, etc.
/// Note that log messages often must go through some background
/// processing before being seen by the user, meaning they may not
/// always work well for tight debugging purposes. In cases such as these,
/// printf() type calls or calling DisplayLog() directly may work better.
/// (though both of these should be avoided in permanent code).
static auto Log(LogLevel level, const std::string& msg) -> void;
/// Print a string directly to stderr as well as the in-game console /// Immediately display a log message in the in-game console,
/// and any connected telnet consoles. /// platform-specific logs, etc. This generally should not be called
static auto PrintStderr(const std::string& s, bool flush = false) -> void; /// directly but instead wired up to display messages coming from the
/// Python logging system.
static auto DisplayLog(const std::string& name, LogLevel level,
const std::string& msg) -> void;
/// Write a string to the debug log. /// Write a message to the v1 cloud log. This is considered legacy
/// This will go to stdout, windows debug log, android log, etc. depending /// and will be phased out eventually.
/// on the platform. static auto V1CloudLog(const std::string& msg) -> void;
static auto Log(const std::string& msg, bool to_stdout = true,
bool to_server = true) -> void;
}; };
} // namespace ballistica } // namespace ballistica

View File

@ -18,8 +18,8 @@ void MacroFunctionTimerEnd(millisecs_t starttime, millisecs_t time,
} }
millisecs_t endtime = g_platform->GetTicks(); millisecs_t endtime = g_platform->GetTicks();
if (endtime - starttime > time) { if (endtime - starttime > time) {
Log("Warning: " + std::to_string(endtime - starttime) Log(LogLevel::kWarning, std::to_string(endtime - starttime)
+ " milliseconds spent in " + funcname); + " milliseconds spent in " + funcname);
} }
} }
@ -32,9 +32,9 @@ void MacroFunctionTimerEndThread(millisecs_t starttime, millisecs_t time,
} }
millisecs_t endtime = g_platform->GetTicks(); millisecs_t endtime = g_platform->GetTicks();
if (endtime - starttime > time) { if (endtime - starttime > time) {
Log("Warning: " + std::to_string(endtime - starttime) Log(LogLevel::kWarning,
+ " milliseconds spent by " + ballistica::GetCurrentThreadName() std::to_string(endtime - starttime) + " milliseconds spent by "
+ " thread in " + funcname); + ballistica::GetCurrentThreadName() + " thread in " + funcname);
} }
} }
@ -47,8 +47,9 @@ void MacroFunctionTimerEndEx(millisecs_t starttime, millisecs_t time,
} }
millisecs_t endtime = g_platform->GetTicks(); millisecs_t endtime = g_platform->GetTicks();
if (endtime - starttime > time) { if (endtime - starttime > time) {
Log("Warning: " + std::to_string(endtime - starttime) Log(LogLevel::kWarning, std::to_string(endtime - starttime)
+ " milliseconds spent in " + funcname + " for " + what); + " milliseconds spent in " + funcname + " for "
+ what);
} }
} }
@ -62,9 +63,10 @@ void MacroFunctionTimerEndThreadEx(millisecs_t starttime, millisecs_t time,
} }
millisecs_t endtime = g_platform->GetTicks(); millisecs_t endtime = g_platform->GetTicks();
if (endtime - starttime > time) { if (endtime - starttime > time) {
Log("Warning: " + std::to_string(endtime - starttime) Log(LogLevel::kWarning, std::to_string(endtime - starttime)
+ " milliseconds spent by " + ballistica::GetCurrentThreadName() + " milliseconds spent by "
+ " thread in " + funcname + " for " + what); + ballistica::GetCurrentThreadName()
+ " thread in " + funcname + " for " + what);
} }
} }
@ -77,9 +79,9 @@ void MacroTimeCheckEnd(millisecs_t starttime, millisecs_t time,
} }
millisecs_t e = g_platform->GetTicks(); millisecs_t e = g_platform->GetTicks();
if (e - starttime > time) { if (e - starttime > time) {
Log(std::string("Warning: ") + name + " took " Log(LogLevel::kWarning,
+ std::to_string(e - starttime) + " milliseconds; " + file + " line " std::string(name) + " took " + std::to_string(e - starttime)
+ std::to_string(line)); + " milliseconds; " + file + " line " + std::to_string(line));
} }
} }
@ -88,19 +90,19 @@ void MacroLogErrorTrace(const std::string& msg, const char* fname, int line) {
snprintf(buffer, sizeof(buffer), "%s:%d:", fname, line); snprintf(buffer, sizeof(buffer), "%s:%d:", fname, line);
buffer[sizeof(buffer) - 1] = 0; buffer[sizeof(buffer) - 1] = 0;
Python::PrintStackTrace(); Python::PrintStackTrace();
Log(std::string(buffer) + " error: " + msg); Log(LogLevel::kError, std::string(buffer) + " error: " + msg);
} }
void MacroLogError(const std::string& msg, const char* fname, int line) { void MacroLogError(const std::string& msg, const char* fname, int line) {
char e_buffer[2048]; char e_buffer[2048];
snprintf(e_buffer, sizeof(e_buffer), "%s:%d:", fname, line); snprintf(e_buffer, sizeof(e_buffer), "%s:%d:", fname, line);
e_buffer[sizeof(e_buffer) - 1] = 0; e_buffer[sizeof(e_buffer) - 1] = 0;
ballistica::Log(std::string(e_buffer) + " error: " + msg); Log(LogLevel::kError, std::string(e_buffer) + " error: " + msg);
} }
void MacroLogPythonTrace(const std::string& msg) { void MacroLogPythonTrace(const std::string& msg) {
Python::PrintStackTrace(); Python::PrintStackTrace();
Log(msg); Log(LogLevel::kError, msg);
} }
} // namespace ballistica } // namespace ballistica

View File

@ -86,11 +86,11 @@
} \ } \
((void)0) // (see 'Trailing-semicolon note' at top) ((void)0) // (see 'Trailing-semicolon note' at top)
#define BA_LOG_ONCE(msg) \ #define BA_LOG_ONCE(lvl, msg) \
{ \ { \
static bool did_log_here = false; \ static bool did_log_here = false; \
if (!did_log_here) { \ if (!did_log_here) { \
ballistica::Log(msg); \ ballistica::Log(lvl, msg); \
did_log_here = true; \ did_log_here = true; \
} \ } \
} \ } \
@ -120,12 +120,12 @@
/// Test a condition and simply print a log message if it fails (on both debug /// Test a condition and simply print a log message if it fails (on both debug
/// and release builds) /// and release builds)
#define BA_PRECONDITION_LOG(b) \ #define BA_PRECONDITION_LOG(b) \
{ \ { \
if (!(b)) { \ if (!(b)) { \
Log("Precondition failed: " #b); \ Log(LogLevel::kError, "Precondition failed: " #b); \
} \ } \
} \ } \
((void)0) // (see 'Trailing-semicolon note' at top) ((void)0) // (see 'Trailing-semicolon note' at top)
/// Test a condition and abort the program if it fails (on both debug /// Test a condition and abort the program if it fails (on both debug

View File

@ -54,9 +54,9 @@ void Object::PrintObjects() {
assert(count == g_app->object_count); assert(count == g_app->object_count);
} }
} }
Log(s); Log(LogLevel::kInfo, s);
#else #else
Log("PrintObjects() only functions in debug builds."); Log(LogLevel::kInfo, "PrintObjects() only functions in debug builds.");
#endif // BA_DEBUG_BUILD #endif // BA_DEBUG_BUILD
} }
@ -126,8 +126,8 @@ auto Object::GetObjectDescription() const -> std::string {
+ ">"; + ">";
} }
auto Object::GetDefaultOwnerThread() const -> ThreadIdentifier { auto Object::GetDefaultOwnerThread() const -> ThreadTag {
return ThreadIdentifier::kLogic; return ThreadTag::kLogic;
} }
auto Object::GetThreadOwnership() const -> Object::ThreadOwnership { auto Object::GetThreadOwnership() const -> Object::ThreadOwnership {
@ -141,19 +141,19 @@ auto Object::GetThreadOwnership() const -> Object::ThreadOwnership {
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
static auto GetCurrentThreadIdentifier() -> ThreadIdentifier { static auto GetCurrentThreadTag() -> ThreadTag {
if (InMainThread()) { if (InMainThread()) {
return ThreadIdentifier::kMain; return ThreadTag::kMain;
} else if (InLogicThread()) { } else if (InLogicThread()) {
return ThreadIdentifier::kLogic; return ThreadTag::kLogic;
} else if (InAudioThread()) { } else if (InAudioThread()) {
return ThreadIdentifier::kAudio; return ThreadTag::kAudio;
} else if (InNetworkWriteThread()) { } else if (InNetworkWriteThread()) {
return ThreadIdentifier::kNetworkWrite; return ThreadTag::kNetworkWrite;
} else if (InMediaThread()) { } else if (InAssetsThread()) {
return ThreadIdentifier::kMedia; return ThreadTag::kAssets;
} else if (InBGDynamicsThread()) { } else if (InBGDynamicsThread()) {
return ThreadIdentifier::kBGDynamics; return ThreadTag::kBGDynamics;
} else { } else {
throw Exception(std::string("unrecognized thread: ") throw Exception(std::string("unrecognized thread: ")
+ GetCurrentThreadName()); + GetCurrentThreadName());
@ -166,8 +166,8 @@ auto Object::ObjectUpdateForAcquire() -> void {
// If we're set to use the next-referencing thread and haven't set one // If we're set to use the next-referencing thread and haven't set one
// yet, do so. // yet, do so.
if (thread_ownership == ThreadOwnership::kNextReferencing if (thread_ownership == ThreadOwnership::kNextReferencing
&& owner_thread_ == ThreadIdentifier::kInvalid) { && owner_thread_ == ThreadTag::kInvalid) {
owner_thread_ = GetCurrentThreadIdentifier(); owner_thread_ = GetCurrentThreadTag();
} }
} }
@ -178,7 +178,7 @@ auto Object::ObjectThreadCheck() -> void {
ThreadOwnership thread_ownership = GetThreadOwnership(); ThreadOwnership thread_ownership = GetThreadOwnership();
ThreadIdentifier t; ThreadTag t;
if (thread_ownership == ThreadOwnership::kClassDefault) { if (thread_ownership == ThreadOwnership::kClassDefault) {
t = GetDefaultOwnerThread(); t = GetDefaultOwnerThread();
} else { } else {
@ -189,32 +189,32 @@ auto Object::ObjectThreadCheck() -> void {
+ "; expected " THREADNAME " thread; got " \ + "; expected " THREADNAME " thread; got " \
+ GetCurrentThreadName()) + GetCurrentThreadName())
switch (t) { switch (t) {
case ThreadIdentifier::kMain: case ThreadTag::kMain:
if (!InMainThread()) { if (!InMainThread()) {
DO_FAIL("Main"); DO_FAIL("Main");
} }
break; break;
case ThreadIdentifier::kLogic: case ThreadTag::kLogic:
if (!InLogicThread()) { if (!InLogicThread()) {
DO_FAIL("Logic"); DO_FAIL("Logic");
} }
break; break;
case ThreadIdentifier::kAudio: case ThreadTag::kAudio:
if (!InAudioThread()) { if (!InAudioThread()) {
DO_FAIL("Audio"); DO_FAIL("Audio");
} }
break; break;
case ThreadIdentifier::kNetworkWrite: case ThreadTag::kNetworkWrite:
if (!InNetworkWriteThread()) { if (!InNetworkWriteThread()) {
DO_FAIL("NetworkWrite"); DO_FAIL("NetworkWrite");
} }
break; break;
case ThreadIdentifier::kMedia: case ThreadTag::kAssets:
if (!InMediaThread()) { if (!InAssetsThread()) {
DO_FAIL("Media"); DO_FAIL("Assets");
} }
break; break;
case ThreadIdentifier::kBGDynamics: case ThreadTag::kBGDynamics:
if (!InBGDynamicsThread()) { if (!InBGDynamicsThread()) {
DO_FAIL("BGDynamics"); DO_FAIL("BGDynamics");
} }

View File

@ -45,7 +45,7 @@ class Object {
/// it can perform sanity-tests to make sure references are not being /// it can perform sanity-tests to make sure references are not being
/// added at incorrect times or from incorrect threads. /// added at incorrect times or from incorrect threads.
/// The default implementation uses the per-object /// The default implementation uses the per-object
/// ThreadOwnership/ThreadIdentifier values accessible below. NOTE: this /// ThreadOwnership/ThreadTag values accessible below. NOTE: this
/// check runs only in the debug build so don't add any logical side-effects! /// check runs only in the debug build so don't add any logical side-effects!
virtual void ObjectThreadCheck(); virtual void ObjectThreadCheck();
@ -59,15 +59,15 @@ class Object {
/// Return the exact thread to check for with ThreadOwnership::kClassDefault /// Return the exact thread to check for with ThreadOwnership::kClassDefault
/// (in the default ObjectThreadCheck implementation at least). /// (in the default ObjectThreadCheck implementation at least).
/// Default returns ThreadIdentifier::kLogic /// Default returns ThreadTag::kLogic
virtual auto GetDefaultOwnerThread() const -> ThreadIdentifier; virtual auto GetDefaultOwnerThread() const -> ThreadTag;
/// Set thread ownership for an individual object. /// Set thread ownership for an individual object.
void SetThreadOwnership(ThreadOwnership ownership) { void SetThreadOwnership(ThreadOwnership ownership) {
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
thread_ownership_ = ownership; thread_ownership_ = ownership;
if (thread_ownership_ == ThreadOwnership::kNextReferencing) { if (thread_ownership_ == ThreadOwnership::kNextReferencing) {
owner_thread_ = ThreadIdentifier::kInvalid; owner_thread_ = ThreadTag::kInvalid;
} }
#endif #endif
} }
@ -560,7 +560,7 @@ class Object {
Object* object_next_{}; Object* object_next_{};
Object* object_prev_{}; Object* object_prev_{};
ThreadOwnership thread_ownership_{ThreadOwnership::kClassDefault}; ThreadOwnership thread_ownership_{ThreadOwnership::kClassDefault};
ThreadIdentifier owner_thread_{ThreadIdentifier::kInvalid}; ThreadTag owner_thread_{ThreadTag::kInvalid};
bool thread_checks_enabled_{true}; bool thread_checks_enabled_{true};
millisecs_t object_birth_time_{}; millisecs_t object_birth_time_{};
bool object_printed_warning_{}; bool object_printed_warning_{};

View File

@ -11,7 +11,6 @@ namespace ballistica {
void Thread::SetInternalThreadName(const std::string& name) { void Thread::SetInternalThreadName(const std::string& name) {
std::scoped_lock lock(g_app->thread_name_map_mutex); std::scoped_lock lock(g_app->thread_name_map_mutex);
std::thread::id thread_id = std::this_thread::get_id();
g_app->thread_name_map[std::this_thread::get_id()] = name; g_app->thread_name_map[std::this_thread::get_id()] = name;
} }
@ -44,26 +43,54 @@ auto Thread::RunLogicThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunLogicThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
auto Thread::RunAudioThread(void* data) -> int { auto Thread::RunAudioThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunAudioThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
auto Thread::RunBGDynamicThread(void* data) -> int { auto Thread::RunBGDynamicThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunBGDynamicThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
auto Thread::RunNetworkWriteThread(void* data) -> int { auto Thread::RunNetworkWriteThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunNetworkWriteThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
auto Thread::RunStdInputThread(void* data) -> int { auto Thread::RunStdInputThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunStdInputThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
auto Thread::RunMediaThread(void* data) -> int { auto Thread::RunAssetsThread(void* data) -> int {
return static_cast<Thread*>(data)->ThreadMain(); return static_cast<Thread*>(data)->ThreadMain();
} }
auto Thread::RunAssetsThreadP(void* data) -> void* {
static_cast<Thread*>(data)->ThreadMain();
return nullptr;
}
void Thread::SetPaused(bool paused) { void Thread::SetPaused(bool paused) {
// Can be toggled from the main thread only. // Can be toggled from the main thread only.
assert(std::this_thread::get_id() == g_app->main_thread_id); assert(std::this_thread::get_id() == g_app->main_thread_id);
@ -85,7 +112,7 @@ void Thread::WaitForNextEvent(bool single_cycle) {
} }
// While we're waiting, allow other python threads to run. // While we're waiting, allow other python threads to run.
if (owns_python_) { if (acquires_python_gil_) {
g_python->ReleaseGIL(); g_python->ReleaseGIL();
} }
@ -96,29 +123,29 @@ void Thread::WaitForNextEvent(bool single_cycle) {
millisecs_t wait_time = timers_.GetTimeToNextExpire(real_time); millisecs_t wait_time = timers_.GetTimeToNextExpire(real_time);
if (wait_time > 0) { if (wait_time > 0) {
std::unique_lock<std::mutex> lock(thread_message_mutex_); std::unique_lock<std::mutex> lock(thread_message_mutex_);
if (thread_message_count_ == 0) { if (thread_messages_.empty()) {
thread_message_cv_.wait_for(lock, std::chrono::milliseconds(wait_time), thread_message_cv_.wait_for(lock, std::chrono::milliseconds(wait_time),
[this] { [this] {
// Go back to sleep on spurious wakeups // Go back to sleep on spurious wakeups
// if we didn't wind up with any new // if we didn't wind up with any new
// messages. // messages.
return (thread_message_count_ > 0); return !thread_messages_.empty();
}); });
} }
} }
} else { } else {
// Not running timers; just wait indefinitely for the next message. // Not running timers; just wait indefinitely for the next message.
std::unique_lock<std::mutex> lock(thread_message_mutex_); std::unique_lock<std::mutex> lock(thread_message_mutex_);
if (thread_message_count_ == 0) { if (thread_messages_.empty()) {
thread_message_cv_.wait(lock, [this] { thread_message_cv_.wait(lock, [this] {
// Go back to sleep on spurious wakeups // Go back to sleep on spurious wakeups
// (if we didn't wind up with any new messages). // (if we didn't wind up with any new messages).
return (thread_message_count_ > 0); return !(thread_messages_.empty());
}); });
} }
} }
if (owns_python_) { if (acquires_python_gil_) {
g_python->AcquireGIL(); g_python->AcquireGIL();
} }
} }
@ -203,49 +230,69 @@ void Thread::GetThreadMessages(std::list<ThreadMessage>* messages) {
// Make sure they passed an empty one in. // Make sure they passed an empty one in.
assert(messages->empty()); assert(messages->empty());
if (thread_message_count_ > 0) { std::scoped_lock lock(thread_message_mutex_);
std::unique_lock<std::mutex> lock(thread_message_mutex_); if (!thread_messages_.empty()) {
assert(thread_messages_.size() == thread_message_count_);
messages->swap(thread_messages_); messages->swap(thread_messages_);
thread_message_count_ = 0;
} }
} }
Thread::Thread(ThreadIdentifier identifier_in, ThreadType type_in) Thread::Thread(ThreadTag identifier_in, ThreadSource source)
: type_(type_in), identifier_(identifier_in) { : source_(source), identifier_(identifier_in) {
switch (type_) { switch (source_) {
case ThreadType::kStandard: { case ThreadSource::kCreate: {
// Lock down until the thread is up and running. It'll unlock us when
// it's ready to go.
int (*func)(void*); int (*func)(void*);
void* (*funcp)(void*);
switch (identifier_) { switch (identifier_) {
case ThreadIdentifier::kLogic: case ThreadTag::kLogic:
func = RunLogicThread; func = RunLogicThread;
funcp = RunLogicThreadP;
break; break;
case ThreadIdentifier::kMedia: case ThreadTag::kAssets:
func = RunMediaThread; func = RunAssetsThread;
funcp = RunAssetsThreadP;
break; break;
case ThreadIdentifier::kMain: case ThreadTag::kMain:
// Shouldn't happen; this thread gets wrapped; not launched. // Shouldn't happen; this thread gets wrapped; not launched.
throw Exception(); throw Exception();
case ThreadIdentifier::kAudio: case ThreadTag::kAudio:
func = RunAudioThread; func = RunAudioThread;
funcp = RunAudioThreadP;
break; break;
case ThreadIdentifier::kBGDynamics: case ThreadTag::kBGDynamics:
func = RunBGDynamicThread; func = RunBGDynamicThread;
funcp = RunBGDynamicThreadP;
break; break;
case ThreadIdentifier::kNetworkWrite: case ThreadTag::kNetworkWrite:
func = RunNetworkWriteThread; func = RunNetworkWriteThread;
funcp = RunNetworkWriteThreadP;
break; break;
case ThreadIdentifier::kStdin: case ThreadTag::kStdin:
func = RunStdInputThread; func = RunStdInputThread;
funcp = RunStdInputThreadP;
break; break;
default: default:
throw Exception(); throw Exception();
} }
// Let 'er rip. // Let 'er rip.
thread_ = new std::thread(func, this);
// NOTE: Apple platforms have a default secondary thread stack size
// of 512k which I've found to be insufficient in cases of heavy
// Python recursion or large simulations. It sounds like Windows
// and Android might have 1mb as default; let's try to standardize
// on that across the board. Unfortunately we have to use pthreads
// to get custom stack sizes; std::thread stupidly doesn't support it.
// FIXME - move this to platform.
#if BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS || BA_OSTYPE_LINUX
pthread_attr_t attr;
BA_PRECONDITION(pthread_attr_init(&attr) == 0);
BA_PRECONDITION(pthread_attr_setstacksize(&attr, 1024 * 1024) == 0);
pthread_t thread;
pthread_create(&thread, &attr, funcp, this);
#else
new std::thread(func, this);
#endif
// Block until the thread is bootstrapped. // Block until the thread is bootstrapped.
// (maybe not necessary, but let's be cautious in case we'd // (maybe not necessary, but let's be cautious in case we'd
@ -255,7 +302,7 @@ Thread::Thread(ThreadIdentifier identifier_in, ThreadType type_in)
break; break;
} }
case ThreadType::kMain: { case ThreadSource::kWrapMain: {
// We've got no thread of our own to launch // We've got no thread of our own to launch
// so we run our setup stuff right here instead of off in some. // so we run our setup stuff right here instead of off in some.
assert(std::this_thread::get_id() == g_app->main_thread_id); assert(std::this_thread::get_id() == g_app->main_thread_id);
@ -275,41 +322,41 @@ Thread::Thread(ThreadIdentifier identifier_in, ThreadType type_in)
auto Thread::ThreadMain() -> int { auto Thread::ThreadMain() -> int {
try { try {
assert(type_ == ThreadType::kStandard); assert(source_ == ThreadSource::kCreate);
thread_id_ = std::this_thread::get_id(); thread_id_ = std::this_thread::get_id();
const char* name; const char* name;
const char* id_string; const char* id_string;
switch (identifier_) { switch (identifier_) {
case ThreadIdentifier::kLogic: case ThreadTag::kLogic:
name = "logic"; name = "logic";
id_string = "ballistica logic"; id_string = "ballistica logic";
break; break;
case ThreadIdentifier::kStdin: case ThreadTag::kStdin:
name = "stdin"; name = "stdin";
id_string = "ballistica stdin"; id_string = "ballistica stdin";
break; break;
case ThreadIdentifier::kMedia: case ThreadTag::kAssets:
name = "media"; name = "assets";
id_string = "ballistica media"; id_string = "ballistica assets";
break; break;
case ThreadIdentifier::kFileOut: case ThreadTag::kFileOut:
name = "fileout"; name = "fileout";
id_string = "ballistica file-out"; id_string = "ballistica file-out";
break; break;
case ThreadIdentifier::kMain: case ThreadTag::kMain:
name = "main"; name = "main";
id_string = "ballistica main"; id_string = "ballistica main";
break; break;
case ThreadIdentifier::kAudio: case ThreadTag::kAudio:
name = "audio"; name = "audio";
id_string = "ballistica audio"; id_string = "ballistica audio";
break; break;
case ThreadIdentifier::kBGDynamics: case ThreadTag::kBGDynamics:
name = "bgdynamics"; name = "bgdynamics";
id_string = "ballistica bg-dynamics"; id_string = "ballistica bg-dynamics";
break; break;
case ThreadIdentifier::kNetworkWrite: case ThreadTag::kNetworkWrite:
name = "networkwrite"; name = "networkwrite";
id_string = "ballistica network writing"; id_string = "ballistica network writing";
break; break;
@ -322,10 +369,7 @@ auto Thread::ThreadMain() -> int {
// Mark ourself as bootstrapped and signal listeners so // Mark ourself as bootstrapped and signal listeners so
// anyone waiting for us to spin up can move along. // anyone waiting for us to spin up can move along.
{ bootstrapped_ = true;
std::scoped_lock lock(client_listener_mutex_);
bootstrapped_ = true;
}
client_listener_cv_.notify_all(); client_listener_cv_.notify_all();
// Now just run our loop until we die. // Now just run our loop until we die.
@ -358,15 +402,17 @@ auto Thread::ThreadMain() -> int {
} }
} }
void Thread::SetOwnsPython() { void Thread::SetAcquiresPythonGIL() {
owns_python_ = true; assert(!acquires_python_gil_); // This should be called exactly once.
assert(IsCurrent());
acquires_python_gil_ = true;
g_python->AcquireGIL(); g_python->AcquireGIL();
} }
// Explicitly kill the main thread. // Explicitly kill the main thread.
void Thread::Quit() { void Thread::Quit() {
assert(type_ == ThreadType::kMain); assert(source_ == ThreadSource::kWrapMain);
if (type_ == ThreadType::kMain) { if (source_ == ThreadSource::kWrapMain) {
done_ = true; done_ = true;
} }
} }
@ -382,8 +428,9 @@ void Thread::LogThreadMessageTally() {
writing_tally_ = true; writing_tally_ = true;
std::unordered_map<std::string, int> tally; std::unordered_map<std::string, int> tally;
Log("Thread message tally (" + std::to_string(thread_messages_.size()) Log(LogLevel::kError, "Thread message tally ("
+ " in list):"); + std::to_string(thread_messages_.size())
+ " in list):");
for (auto&& m : thread_messages_) { for (auto&& m : thread_messages_) {
std::string s; std::string s;
switch (m.type) { switch (m.type) {
@ -417,8 +464,8 @@ void Thread::LogThreadMessageTally() {
} }
int entry = 1; int entry = 1;
for (auto&& i : tally) { for (auto&& i : tally) {
Log(" #" + std::to_string(entry++) + " (" + std::to_string(i.second) Log(LogLevel::kError, " #" + std::to_string(entry++) + " ("
+ "x): " + i.first); + std::to_string(i.second) + "x): " + i.first);
} }
writing_tally_ = false; writing_tally_ = false;
} }
@ -432,13 +479,10 @@ void Thread::PushThreadMessage(const ThreadMessage& t) {
// Plop the data on to the list; we're assuming the mutex is locked. // Plop the data on to the list; we're assuming the mutex is locked.
thread_messages_.push_back(t); thread_messages_.push_back(t);
// Keep our own count; apparently size() on an stl list involves // Keep our own count; apparently size() on an stl list involves iterating.
// iterating.
// FIXME: Actually I don't think this is the case anymore; should check. // FIXME: Actually I don't think this is the case anymore; should check.
thread_message_count_++;
assert(thread_message_count_ == thread_messages_.size());
// Show message count states. // Debugging: show message count states.
if (explicit_bool(false)) { if (explicit_bool(false)) {
static int one_off = 0; static int one_off = 0;
static int foo = 0; static int foo = 0;
@ -446,7 +490,7 @@ void Thread::PushThreadMessage(const ThreadMessage& t) {
one_off++; one_off++;
// Show momemtary spikes. // Show momemtary spikes.
if (thread_message_count_ > 100 && one_off > 100) { if (thread_messages_.size() > 100 && one_off > 100) {
one_off = 0; one_off = 0;
foo = 999; foo = 999;
} }
@ -454,24 +498,25 @@ void Thread::PushThreadMessage(const ThreadMessage& t) {
// Show count periodically. // Show count periodically.
if ((std::this_thread::get_id() == g_app->main_thread_id) && foo > 100) { if ((std::this_thread::get_id() == g_app->main_thread_id) && foo > 100) {
foo = 0; foo = 0;
Log("MSG COUNT " + std::to_string(thread_message_count_)); Log(LogLevel::kInfo,
"MSG COUNT " + std::to_string(thread_messages_.size()));
} }
} }
if (thread_message_count_ > 1000) { if (thread_messages_.size() > 1000) {
static bool sent_error = false; static bool sent_error = false;
if (!sent_error) { if (!sent_error) {
sent_error = true; sent_error = true;
Log("Error: ThreadMessage list > 1000 in thread: " Log(LogLevel::kError,
+ GetCurrentThreadName()); "ThreadMessage list > 1000 in thread: " + GetCurrentThreadName());
LogThreadMessageTally(); LogThreadMessageTally();
} }
} }
// Prevent runaway mem usage if the list gets out of control. // Prevent runaway mem usage if the list gets out of control.
if (thread_message_count_ > 10000) { if (thread_messages_.size() > 10000) {
throw Exception("KILLING APP: ThreadMessage list > 10000 in thread: " FatalError("ThreadMessage list > 10000 in thread: "
+ GetCurrentThreadName()); + GetCurrentThreadName());
} }
// Unlock thread-message list and inform thread that there's something // Unlock thread-message list and inform thread that there's something
@ -618,5 +663,12 @@ auto Thread::CheckPushSafety() -> bool {
return CheckPushRunnableSafety(); return CheckPushRunnableSafety();
} }
} }
auto Thread::CheckPushRunnableSafety() -> bool {
std::scoped_lock lock(client_listener_mutex_);
// We first complain when we get to 1000 queued messages so
// let's consider things unsafe when we're halfway there.
return (thread_messages_.size() < kThreadMessageSafetyThreshold);
}
} // namespace ballistica } // namespace ballistica

View File

@ -23,8 +23,7 @@ const int kThreadMessageSafetyThreshold{500};
// A thread with a built-in event loop. // A thread with a built-in event loop.
class Thread { class Thread {
public: public:
explicit Thread(ThreadIdentifier id, explicit Thread(ThreadTag id, ThreadSource source = ThreadSource::kCreate);
ThreadType type_in = ThreadType::kStandard);
virtual ~Thread(); virtual ~Thread();
auto ClearCurrentThreadName() -> void; auto ClearCurrentThreadName() -> void;
@ -44,7 +43,7 @@ class Thread {
// Used to quit the main thread. // Used to quit the main thread.
void Quit(); void Quit();
void SetOwnsPython(); void SetAcquiresPythonGIL();
void SetPaused(bool paused); void SetPaused(bool paused);
auto thread_id() const -> std::thread::id { return thread_id_; } auto thread_id() const -> std::thread::id { return thread_id_; }
@ -55,13 +54,7 @@ class Thread {
void set_thread_id(std::thread::id id) { thread_id_ = id; } void set_thread_id(std::thread::id id) { thread_id_ = id; }
auto RunEventLoop(bool single_cycle = false) -> int; auto RunEventLoop(bool single_cycle = false) -> int;
auto identifier() const -> ThreadIdentifier { return identifier_; } auto identifier() const -> ThreadTag { return identifier_; }
auto CheckPushRunnableSafety() -> bool {
// We first complain when we get to 1000 queued messages so
// let's consider things unsafe when we're halfway there.
return (thread_message_count_ < kThreadMessageSafetyThreshold);
}
// Register a timer to run on the thread. // Register a timer to run on the thread.
auto NewTimer(millisecs_t length, bool repeat, auto NewTimer(millisecs_t length, bool repeat,
@ -116,7 +109,7 @@ class Thread {
explicit ThreadMessage(Type type, Runnable* runnable, bool* completion_flag) explicit ThreadMessage(Type type, Runnable* runnable, bool* completion_flag)
: type(type), runnable(runnable), completion_flag{completion_flag} {} : type(type), runnable(runnable), completion_flag{completion_flag} {}
}; };
auto CheckPushRunnableSafety() -> bool;
auto SetInternalThreadName(const std::string& name) -> void; auto SetInternalThreadName(const std::string& name) -> void;
auto WaitForNextEvent(bool single_cycle) -> void; auto WaitForNextEvent(bool single_cycle) -> void;
auto LoopUpkeep(bool once) -> void; auto LoopUpkeep(bool once) -> void;
@ -132,12 +125,12 @@ class Thread {
int messages_since_paused_{}; int messages_since_paused_{};
millisecs_t last_paused_message_report_time_{}; millisecs_t last_paused_message_report_time_{};
bool done_{}; bool done_{};
ThreadType type_; ThreadSource source_;
int listen_sd_{}; int listen_sd_{};
std::thread::id thread_id_{}; std::thread::id thread_id_{};
ThreadIdentifier identifier_{ThreadIdentifier::kInvalid}; ThreadTag identifier_{ThreadTag::kInvalid};
millisecs_t last_complaint_time_{}; millisecs_t last_complaint_time_{};
bool owns_python_{}; bool acquires_python_gil_{};
// FIXME: Should generalize this to some sort of PlatformThreadData class. // FIXME: Should generalize this to some sort of PlatformThreadData class.
#if BA_XCODE_BUILD #if BA_XCODE_BUILD
@ -148,11 +141,17 @@ class Thread {
// different thread groups makes its easy to see which thread is which // different thread groups makes its easy to see which thread is which
// in profilers, backtraces, etc. // in profilers, backtraces, etc.
static auto RunLogicThread(void* data) -> int; static auto RunLogicThread(void* data) -> int;
static auto RunLogicThreadP(void* data) -> void*;
static auto RunAudioThread(void* data) -> int; static auto RunAudioThread(void* data) -> int;
static auto RunAudioThreadP(void* data) -> void*;
static auto RunBGDynamicThread(void* data) -> int; static auto RunBGDynamicThread(void* data) -> int;
static auto RunBGDynamicThreadP(void* data) -> void*;
static auto RunNetworkWriteThread(void* data) -> int; static auto RunNetworkWriteThread(void* data) -> int;
static auto RunNetworkWriteThreadP(void* data) -> void*;
static auto RunStdInputThread(void* data) -> int; static auto RunStdInputThread(void* data) -> int;
static auto RunMediaThread(void* data) -> int; static auto RunStdInputThreadP(void* data) -> void*;
static auto RunAssetsThread(void* data) -> int;
static auto RunAssetsThreadP(void* data) -> void*;
auto ThreadMain() -> int; auto ThreadMain() -> int;
auto GetThreadMessages(std::list<ThreadMessage>* messages) -> void; auto GetThreadMessages(std::list<ThreadMessage>* messages) -> void;
@ -162,12 +161,11 @@ class Thread {
auto RunPauseCallbacks() -> void; auto RunPauseCallbacks() -> void;
auto RunResumeCallbacks() -> void; auto RunResumeCallbacks() -> void;
int thread_message_count_{};
bool bootstrapped_{}; bool bootstrapped_{};
std::list<std::pair<Runnable*, bool*>> runnables_; std::list<std::pair<Runnable*, bool*>> runnables_;
std::list<Runnable*> pause_callbacks_; std::list<Runnable*> pause_callbacks_;
std::list<Runnable*> resume_callbacks_; std::list<Runnable*> resume_callbacks_;
std::thread* thread_{}; // std::thread* thread_{};
std::condition_variable thread_message_cv_; std::condition_variable thread_message_cv_;
std::mutex thread_message_mutex_; std::mutex thread_message_mutex_;
std::list<ThreadMessage> thread_messages_; std::list<ThreadMessage> thread_messages_;

View File

@ -34,12 +34,12 @@ typedef int64_t millisecs_t;
// avoid pulling in their full headers as much as possible // avoid pulling in their full headers as much as possible
// to keep compile times down. // to keep compile times down.
class Account;
class AppFlavor; class AppFlavor;
class AppConfig; class AppConfig;
class App; class App;
class AppInternal; class AppInternal;
class AreaOfInterest; class AreaOfInterest;
class Assets;
class Audio; class Audio;
class AudioServer; class AudioServer;
class AudioStreamer; class AudioStreamer;
@ -81,7 +81,6 @@ class DataData;
class Dynamics; class Dynamics;
class FrameDef; class FrameDef;
struct FriendScoreSet; struct FriendScoreSet;
class Game;
class GLContext; class GLContext;
class GlobalsNode; class GlobalsNode;
class Graphics; class Graphics;
@ -97,15 +96,15 @@ struct JointFixedEF;
class Joystick; class Joystick;
class JsonDict; class JsonDict;
class KeyboardInput; class KeyboardInput;
class Logic;
class Material; class Material;
class MaterialAction; class MaterialAction;
class MaterialComponent; class MaterialComponent;
class MaterialConditionNode; class MaterialConditionNode;
class MaterialContext; class MaterialContext;
class Matrix44f; class Matrix44f;
class Media; class AssetComponentData;
class MediaComponentData; class AssetsServer;
class MediaServer;
class MeshBufferBase; class MeshBufferBase;
class MeshBufferVertexSprite; class MeshBufferVertexSprite;
class MeshBufferVertexSimpleFull; class MeshBufferVertexSimpleFull;
@ -124,7 +123,7 @@ class NetClientThread;
class NetGraph; class NetGraph;
class Networking; class Networking;
class NetworkReader; class NetworkReader;
class NetworkWriteModule; class NetworkWriter;
class Node; class Node;
class NodeType; class NodeType;
class NodeAttribute; class NodeAttribute;
@ -132,7 +131,6 @@ class NodeAttributeConnection;
class NodeAttributeUnbound; class NodeAttributeUnbound;
class Object; class Object;
class ObjectComponent; class ObjectComponent;
class GameStream;
class Part; class Part;
class Python; class Python;
class Platform; class Platform;
@ -164,6 +162,8 @@ class RootUI;
class RootWidget; class RootWidget;
class Runnable; class Runnable;
class Scene; class Scene;
class SceneV1;
class SceneStream;
class ScoreToBeat; class ScoreToBeat;
class SDLApp; class SDLApp;
class SDLContext; class SDLContext;
@ -174,7 +174,7 @@ class SoundData;
class SpriteMesh; class SpriteMesh;
class StackWidget; class StackWidget;
class StressTest; class StressTest;
class StdInputModule; class StdioConsole;
class Module; class Module;
class TelnetServer; class TelnetServer;
class TestInput; class TestInput;
@ -197,6 +197,7 @@ class Vector2f;
class Vector3f; class Vector3f;
class Vector4f; class Vector4f;
class AppFlavorVR; class AppFlavorVR;
class V1Account;
class VRGraphics; class VRGraphics;
class Widget; class Widget;
@ -403,7 +404,7 @@ enum class SpecialChar {
kLast // Sentinel kLast // Sentinel
}; };
enum class MediaType { kTexture, kCollideModel, kModel, kSound, kData, kLast }; enum class AssetType { kTexture, kCollideModel, kModel, kSound, kData, kLast };
/// Python exception types we can raise from our own exceptions. /// Python exception types we can raise from our own exceptions.
enum class PyExcType { enum class PyExcType {
@ -423,6 +424,8 @@ enum class PyExcType {
kWidgetNotFound kWidgetNotFound
}; };
enum class LogLevel { kDebug, kInfo, kWarning, kError, kCritical };
enum class SystemTextureID { enum class SystemTextureID {
kUIAtlas, kUIAtlas,
kButtonSquare, kButtonSquare,
@ -986,20 +989,20 @@ enum class NodeAttributeType {
kCollideModelArray kCollideModelArray
}; };
enum class ThreadType { enum class ThreadSource {
/// A normal thread spun up by us. /// A normal thread spun up by us.
kStandard, kCreate,
/// For wrapping a ballistica thread around the existing main thread. /// For wrapping a ballistica thread around the existing main thread.
kMain kWrapMain
}; };
/// Used for module-thread identification. /// Used for module-thread identification.
/// Mostly just for debugging, through a few things are affected by this /// Mostly just for debugging, through a few things are affected by this
/// (the Logic thread manages the python GIL, etc). /// (the Logic thread manages the python GIL, etc).
enum class ThreadIdentifier { enum class ThreadTag {
kInvalid, kInvalid,
kLogic, kLogic,
kMedia, kAssets,
kFileOut, kFileOut,
kMain, kMain,
kAudio, kAudio,

View File

@ -2,6 +2,7 @@
#include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/dynamics/bg/bg_dynamics.h"
#include "ballistica/assets/component/collide_model.h"
#include "ballistica/core/thread.h" #include "ballistica/core/thread.h"
#include "ballistica/dynamics/bg/bg_dynamics_draw_snapshot.h" #include "ballistica/dynamics/bg/bg_dynamics_draw_snapshot.h"
#include "ballistica/dynamics/bg/bg_dynamics_fuse_data.h" #include "ballistica/dynamics/bg/bg_dynamics_fuse_data.h"
@ -10,19 +11,12 @@
#include "ballistica/graphics/component/object_component.h" #include "ballistica/graphics/component/object_component.h"
#include "ballistica/graphics/component/smoke_component.h" #include "ballistica/graphics/component/smoke_component.h"
#include "ballistica/graphics/component/sprite_component.h" #include "ballistica/graphics/component/sprite_component.h"
#include "ballistica/media/component/collide_model.h"
namespace ballistica { namespace ballistica {
void BGDynamics::Init() {
// Just init our singleton.
new BGDynamics();
}
BGDynamics::BGDynamics() { BGDynamics::BGDynamics() {
assert(InLogicThread()); // We're a singleton; make sure we don't already exist.
assert(g_bg_dynamics == nullptr); assert(g_bg_dynamics == nullptr);
g_bg_dynamics = this;
} }
void BGDynamics::AddTerrain(CollideModelData* o) { void BGDynamics::AddTerrain(CollideModelData* o) {
@ -188,7 +182,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
c.SetCameraAligned(true); c.SetCameraAligned(true);
c.SetColor(2.0f, 2.0f, 2.0f, 1.0f); c.SetColor(2.0f, 2.0f, 2.0f, 1.0f);
c.SetOverlay(draw_in_overlay); c.SetOverlay(draw_in_overlay);
c.SetTexture(g_media->GetTexture(SystemTextureID::kSparks)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kSparks));
c.DrawMesh(sparks_mesh_.get(), kModelDrawFlagNoReflection); c.DrawMesh(sparks_mesh_.get(), kModelDrawFlagNoReflection);
c.Submit(); c.Submit();
} }
@ -203,7 +197,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
lights_mesh_->SetData( lights_mesh_->SetData(
Object::Ref<MeshBuffer<VertexSprite>>(ds->light_vertices)); Object::Ref<MeshBuffer<VertexSprite>>(ds->light_vertices));
SpriteComponent c(frame_def->light_shadow_pass()); SpriteComponent c(frame_def->light_shadow_pass());
c.SetTexture(g_media->GetTexture(SystemTextureID::kLightSoft)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kLightSoft));
c.DrawMesh(lights_mesh_.get()); c.DrawMesh(lights_mesh_.get());
c.Submit(); c.Submit();
} }
@ -216,7 +210,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
shadows_mesh_->SetData( shadows_mesh_->SetData(
Object::Ref<MeshBuffer<VertexSprite>>(ds->shadow_vertices)); Object::Ref<MeshBuffer<VertexSprite>>(ds->shadow_vertices));
SpriteComponent c(frame_def->light_shadow_pass()); SpriteComponent c(frame_def->light_shadow_pass());
c.SetTexture(g_media->GetTexture(SystemTextureID::kLight)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kLight));
c.DrawMesh(shadows_mesh_.get()); c.DrawMesh(shadows_mesh_.get());
c.Submit(); c.Submit();
} }
@ -268,7 +262,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
Object::Ref<MeshBuffer<VertexSimpleFull>>(ds->fuse_vertices)); Object::Ref<MeshBuffer<VertexSimpleFull>>(ds->fuse_vertices));
{ // Draw! { // Draw!
ObjectComponent c(frame_def->beauty_pass()); ObjectComponent c(frame_def->beauty_pass());
c.SetTexture(g_media->GetTexture(SystemTextureID::kFuse)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kFuse));
c.DrawMesh(fuses_mesh_.get(), kModelDrawFlagNoReflection); c.DrawMesh(fuses_mesh_.get(), kModelDrawFlagNoReflection);
c.Submit(); c.Submit();
} }
@ -286,16 +280,16 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
ModelData* model; ModelData* model;
switch (chunk_type) { switch (chunk_type) {
case BGDynamicsChunkType::kFlagStand: case BGDynamicsChunkType::kFlagStand:
model = g_media->GetModel(SystemModelID::kFlagStand); model = g_assets->GetModel(SystemModelID::kFlagStand);
break; break;
case BGDynamicsChunkType::kSplinter: case BGDynamicsChunkType::kSplinter:
model = g_media->GetModel(SystemModelID::kShrapnelBoard); model = g_assets->GetModel(SystemModelID::kShrapnelBoard);
break; break;
case BGDynamicsChunkType::kSlime: case BGDynamicsChunkType::kSlime:
model = g_media->GetModel(SystemModelID::kShrapnelSlime); model = g_assets->GetModel(SystemModelID::kShrapnelSlime);
break; break;
default: default:
model = g_media->GetModel(SystemModelID::kShrapnel1); model = g_assets->GetModel(SystemModelID::kShrapnel1);
break; break;
} }
ObjectComponent c(frame_def->beauty_pass()); ObjectComponent c(frame_def->beauty_pass());
@ -303,20 +297,20 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
// Set up shading. // Set up shading.
switch (chunk_type) { switch (chunk_type) {
case BGDynamicsChunkType::kRock: { case BGDynamicsChunkType::kRock: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSoft); c.SetReflection(ReflectionType::kSoft);
c.SetReflectionScale(0.2f, 0.2f, 0.2f); c.SetReflectionScale(0.2f, 0.2f, 0.2f);
c.SetColor(0.6f, 0.6f, 0.5f); c.SetColor(0.6f, 0.6f, 0.5f);
break; break;
} }
case BGDynamicsChunkType::kIce: { case BGDynamicsChunkType::kIce: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSharp); c.SetReflection(ReflectionType::kSharp);
c.SetAddColor(0.5f, 0.5f, 0.9f); c.SetAddColor(0.5f, 0.5f, 0.9f);
break; break;
} }
case BGDynamicsChunkType::kSlime: { case BGDynamicsChunkType::kSlime: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSharper); c.SetReflection(ReflectionType::kSharper);
c.SetReflectionScale(3.0f, 3.0f, 3.0f); c.SetReflectionScale(3.0f, 3.0f, 3.0f);
c.SetColor(0.0f, 0.0f, 0.0f); c.SetColor(0.0f, 0.0f, 0.0f);
@ -324,13 +318,13 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
break; break;
} }
case BGDynamicsChunkType::kMetal: { case BGDynamicsChunkType::kMetal: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kPowerup); c.SetReflection(ReflectionType::kPowerup);
c.SetColor(0.5f, 0.5f, 0.55f); c.SetColor(0.5f, 0.5f, 0.55f);
break; break;
} }
case BGDynamicsChunkType::kSpark: { case BGDynamicsChunkType::kSpark: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSharp); c.SetReflection(ReflectionType::kSharp);
c.SetColor(0.0f, 0.0f, 0.0f, 1.0f); c.SetColor(0.0f, 0.0f, 0.0f, 1.0f);
c.SetReflectionScale(4.0f, 3.0f, 2.0f); c.SetReflectionScale(4.0f, 3.0f, 2.0f);
@ -338,7 +332,7 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
break; break;
} }
case BGDynamicsChunkType::kSplinter: { case BGDynamicsChunkType::kSplinter: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSoft); c.SetReflection(ReflectionType::kSoft);
c.SetColor(1.0f, 0.8f, 0.5f); c.SetColor(1.0f, 0.8f, 0.5f);
break; break;
@ -347,7 +341,7 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
c.SetTransparent(true); c.SetTransparent(true);
c.SetPremultiplied(true); c.SetPremultiplied(true);
c.SetLightShadow(LightShadowType::kNone); c.SetLightShadow(LightShadowType::kNone);
c.SetTexture(g_media->GetTexture(SystemTextureID::kShrapnel1)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kShrapnel1));
c.SetReflection(ReflectionType::kSharp); c.SetReflection(ReflectionType::kSharp);
c.SetReflectionScale(0.5f, 0.4f, 0.3f); c.SetReflectionScale(0.5f, 0.4f, 0.3f);
c.SetColor(0.2f, 0.15f, 0.15f, 0.07f); c.SetColor(0.2f, 0.15f, 0.15f, 0.07f);
@ -355,7 +349,7 @@ void BGDynamics::DrawChunks(FrameDef* frame_def,
break; break;
} }
case BGDynamicsChunkType::kFlagStand: { case BGDynamicsChunkType::kFlagStand: {
c.SetTexture(g_media->GetTexture(SystemTextureID::kFlagPole)); c.SetTexture(g_assets->GetTexture(SystemTextureID::kFlagPole));
c.SetReflection(ReflectionType::kSharp); c.SetReflection(ReflectionType::kSharp);
c.SetColor(0.9f, 0.6f, 0.3f, 1.0f); c.SetColor(0.9f, 0.6f, 0.3f, 1.0f);
break; break;

Some files were not shown because too many files have changed in this diff Show More