mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-07 08:03:30 +08:00
cleaned up interaction between graphics server and client which will make alternate renderers more doable
This commit is contained in:
parent
a3b51abb03
commit
b5b34b4455
106
.efrocachemap
generated
106
.efrocachemap
generated
@ -421,7 +421,7 @@
|
|||||||
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
|
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
|
||||||
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
|
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
|
||||||
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
|
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
|
||||||
"build/assets/ba_data/data/langdata.json": "7a5f49ae1738b012a6d7c16740af80a0",
|
"build/assets/ba_data/data/langdata.json": "1a960da2db069ca3926b8ee6b8f82df7",
|
||||||
"build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226",
|
"build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226",
|
||||||
"build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c",
|
"build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c",
|
||||||
"build/assets/ba_data/data/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9",
|
"build/assets/ba_data/data/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9",
|
||||||
@ -433,30 +433,30 @@
|
|||||||
"build/assets/ba_data/data/languages/english.json": "e70277fc6325126d3d893524c8df03c9",
|
"build/assets/ba_data/data/languages/english.json": "e70277fc6325126d3d893524c8df03c9",
|
||||||
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
||||||
"build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894",
|
"build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894",
|
||||||
"build/assets/ba_data/data/languages/french.json": "d8527da977a563185de25ef02bacf826",
|
"build/assets/ba_data/data/languages/french.json": "4e218dcd488fa63e7db5b4da2261b9e1",
|
||||||
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
|
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
|
||||||
"build/assets/ba_data/data/languages/gibberish.json": "7863ceeedb1e87eef46f7769bae5f842",
|
"build/assets/ba_data/data/languages/gibberish.json": "b8dfd407fb7fd9b268129c364b70ca54",
|
||||||
"build/assets/ba_data/data/languages/greek.json": "a65d78f912e9a89f98de004405167a6a",
|
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
|
||||||
"build/assets/ba_data/data/languages/hindi.json": "88ee0cda537bab9ac827def5e236fe1a",
|
"build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6",
|
||||||
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
|
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
|
||||||
"build/assets/ba_data/data/languages/indonesian.json": "bff88ce57744a639810b93a1d1dd79f4",
|
"build/assets/ba_data/data/languages/indonesian.json": "53961b1484a1831f32bec2cc2941e672",
|
||||||
"build/assets/ba_data/data/languages/italian.json": "58ecf53a963dbeca1bbf3605e5ab6a2f",
|
"build/assets/ba_data/data/languages/italian.json": "58ecf53a963dbeca1bbf3605e5ab6a2f",
|
||||||
"build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2",
|
"build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2",
|
||||||
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
|
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
|
||||||
"build/assets/ba_data/data/languages/persian.json": "71cc5b33abda0f285b970b8cc4a014a8",
|
"build/assets/ba_data/data/languages/persian.json": "a391d80ff58ea22926499e4b19d2c0d0",
|
||||||
"build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a",
|
"build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a",
|
||||||
"build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2",
|
"build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2",
|
||||||
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
|
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
|
||||||
"build/assets/ba_data/data/languages/russian.json": "70f79c606ccc5ec7bd6ce0303fdece70",
|
"build/assets/ba_data/data/languages/russian.json": "70f79c606ccc5ec7bd6ce0303fdece70",
|
||||||
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
||||||
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
|
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
|
||||||
"build/assets/ba_data/data/languages/spanish.json": "6ccd728df4766be1969434d6f04c36d2",
|
"build/assets/ba_data/data/languages/spanish.json": "e72e394f94b99d3e838c1b81a9d17615",
|
||||||
"build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18",
|
"build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18",
|
||||||
"build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723",
|
"build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723",
|
||||||
"build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc",
|
"build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc",
|
||||||
"build/assets/ba_data/data/languages/turkish.json": "42318070b817663f671d78a9c8f3019c",
|
"build/assets/ba_data/data/languages/turkish.json": "42318070b817663f671d78a9c8f3019c",
|
||||||
"build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2",
|
"build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2",
|
||||||
"build/assets/ba_data/data/languages/venetian.json": "88595b7ee696b4094d7874c3c4188852",
|
"build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4",
|
||||||
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
|
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
|
||||||
"build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054",
|
"build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054",
|
||||||
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
|
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
|
||||||
@ -4056,50 +4056,50 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ece14cc6d7a449f581c810a2d6d3449d",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "48b5a58b401a2b22b88491f7bcd0e22a",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "b0b75bde134af8c73aa1f7e239bd84dc",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "6d83849db3e1398503e2bb682eb4323e",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f0742e77993c006a5f2df3e9bee6732e",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b054c284b778dc77edc9c9b046303f46",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b803f154b4bf2aeb908a603fa7888301",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b16789743a603fac02763c09bbca446b",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2be90b3e6fc6908448a7677dd3cfb594",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ab0a78d42cc511b4041478205e892897",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4d12d1887901f7c77b5df965bb0b4622",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4bbb41936ffe72a7fe9bdc803761b937",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "987f4e024c7ed08e58223369b40aa309",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "a1427251545496f84c4d4e2d90e6e25a",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7dd6ce5ab63d9d255029fb907cf6fb63",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "729bec30bafe25cac07f920c0cc30ab8",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ad505c3ad979b2cf52c664ee79798575",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f8b086fdf6bca929ebc75b117b80f522",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "3773aa5c6d396b4c38883321067f5523",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "7d8f3ffe791e5a665ecbb2c517483814",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "748f3877c0ac40f48ebc5d8aab442173",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5f4207138b152a110593c6c5ea8a9b32",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "2d059f03286603ac416718eb262241ab",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4211f250197995e7df6942d32cffd202",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3bd988564ed41c15b4d0f493eced88ef",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "40be1e38cbac3baf88dee161eeb912e1",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "f01539e046d72d86d63da0b4b6fc28df",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d4aacb95a1855e969d1cc8db33732c40",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d554e6d3ef9709ad7d7c848633901089",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "570f49dc1de66e3fe75d76ee5f9306e0",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "967375f76d43831afd7e10208502dcc1",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ad319e6fb3cd7043a597f0780de42a98",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7dba8e8a0b8ffbe7f8d73b33b0c41ed5",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "4c15b26f43b4cb81f433beeb927c8aa6",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "11ccabb65197c9f2e3059ac434888e11",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a06aaa7a95abb56d49ba7925cc503a28",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8d79aece6620eb017896a7e816a78f0d",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "82619b88184faf3ef7ae4bf41ea282ce",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a3331c3d60962e7f0c2b62728bf7f43e",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "61251e6fe58347224750fdf30d4bf8bc",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "3fc153ee973090358916b90938429931",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "3fc153ee973090358916b90938429931",
|
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea",
|
||||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce",
|
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8",
|
||||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1",
|
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4",
|
||||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54",
|
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b",
|
||||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd",
|
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987",
|
||||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "dc45874c7796f4fc740c224243efac28",
|
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "840e96e79a56393c353184475cf28fbc",
|
||||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "abeca8c975a6cd5766fc90df99e8dcd1",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d0940a2237c33b922cf3747cbf3910ef",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7aa3fa305f66461ec5e5bbc550aa742d",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "52ccfcbba95dcf3d06620748690446be",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "89c02f2300860fded6b44855f9b8407f",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "8369a217dc8cd95db308851de9f35d86",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "69f97da125d43fc396eeaea8013cb133",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6bc8e9e67a0cbe50ab2c6891d454570f",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9e56ac32e0cc2785811a162de68c69da",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2ce9d1659647bca4725f404d192c3554",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a62570a46fed2002590be0bafe5055e8",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8fd2fd1ec12170942823e809332e8cb9",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "b2a10b1eb917197da8f981d5a5daed44",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f40bd1a61620168791b88901975ea8ee",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c3af2f896ddb7a0b5f2ee2f35bac0318",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4e3f244ac43cd400ffdbd2ac2e887399",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "30628de8aa6a7d9cfccf09f102ff9953",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a5e5e62c259e23429eca4af7054cc7cb",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "bb96031e3f844704fcc9a0549a6d2c41",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "bb96031e3f844704fcc9a0549a6d2c41",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
### 1.7.28 (build 21479, api 8, 2023-10-17)
|
### 1.7.28 (build 21486, api 8, 2023-10-20)
|
||||||
|
|
||||||
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
||||||
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
||||||
|
|||||||
@ -353,6 +353,10 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/camera.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/camera.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.cc
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h
|
||||||
@ -688,6 +692,7 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/shared/generic/lambda_runnable.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/lambda_runnable.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.cc
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/shared/generic/snapshot.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.cc
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/utf8.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/utf8.cc
|
||||||
|
|||||||
@ -345,6 +345,10 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
||||||
@ -680,6 +684,7 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
||||||
|
|||||||
@ -469,6 +469,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1474,6 +1486,9 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@ -340,6 +340,10 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
||||||
@ -675,6 +679,7 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
||||||
|
|||||||
@ -469,6 +469,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1474,6 +1486,9 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@ -185,10 +185,8 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None:
|
|||||||
def _on_log(entry: LogEntry) -> None:
|
def _on_log(entry: LogEntry) -> None:
|
||||||
# Forward this along to the engine to display in the in-app
|
# Forward this along to the engine to display in the in-app
|
||||||
# console, in the Android log, etc.
|
# console, in the Android log, etc.
|
||||||
_babase.display_log(
|
_babase.emit_log(
|
||||||
name=entry.name,
|
name=entry.name, level=entry.level.name, message=entry.message
|
||||||
level=entry.level.name,
|
|
||||||
message=entry.message,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We also want to feed some logs to the old v1-cloud-log system.
|
# We also want to feed some logs to the old v1-cloud-log system.
|
||||||
|
|||||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
# Build number and version of the ballistica binary we expect to be
|
# Build number and version of the ballistica binary we expect to be
|
||||||
# using.
|
# using.
|
||||||
TARGET_BALLISTICA_BUILD = 21479
|
TARGET_BALLISTICA_BUILD = 21486
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.28'
|
TARGET_BALLISTICA_VERSION = '1.7.28'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||||
|
|
||||||
#if BA_OSTYPE_ANDROID
|
#if BA_OSTYPE_ANDROID // Remove conditional once android sources are public.
|
||||||
#include "ballistica/base/app_adapter/app_adapter_android.h"
|
#include "ballistica/base/app_adapter/app_adapter_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "ballistica/base/app_adapter/app_adapter_apple.h"
|
#include "ballistica/base/app_adapter/app_adapter_apple.h"
|
||||||
@ -305,4 +305,14 @@ void AppAdapter::DoSoftQuit() { FatalError("Fixme unimplemented."); }
|
|||||||
void AppAdapter::TerminateApp() { FatalError("Fixme unimplemented."); }
|
void AppAdapter::TerminateApp() { FatalError("Fixme unimplemented."); }
|
||||||
auto AppAdapter::HasDirectKeyboardInput() -> bool { return false; }
|
auto AppAdapter::HasDirectKeyboardInput() -> bool { return false; }
|
||||||
|
|
||||||
|
void AppAdapter::ApplyGraphicsSettings(const GraphicsSettings* settings) {}
|
||||||
|
|
||||||
|
auto AppAdapter::GetGraphicsSettings() -> GraphicsSettings* {
|
||||||
|
return new GraphicsSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AppAdapter::GetGraphicsClientContext() -> GraphicsClientContext* {
|
||||||
|
return new GraphicsClientContext();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|||||||
@ -30,6 +30,16 @@ class AppAdapter {
|
|||||||
virtual void OnScreenSizeChange();
|
virtual void OnScreenSizeChange();
|
||||||
virtual void DoApplyAppConfig();
|
virtual void DoApplyAppConfig();
|
||||||
|
|
||||||
|
/// When called, should allocate an instance of a GraphicsSettings
|
||||||
|
/// subclass using 'new', fill it out, and return it. Runs in the logic
|
||||||
|
/// thread.
|
||||||
|
virtual auto GetGraphicsSettings() -> GraphicsSettings*;
|
||||||
|
|
||||||
|
/// When called, should allocate an instance of a GraphicsClientContext
|
||||||
|
/// subclass using 'new', fill it out, and return it. Runs in the graphics
|
||||||
|
/// context.
|
||||||
|
virtual auto GetGraphicsClientContext() -> GraphicsClientContext*;
|
||||||
|
|
||||||
/// Return whether this class manages the main thread event loop itself.
|
/// Return whether this class manages the main thread event loop itself.
|
||||||
/// Default is true. If this is true, RunMainThreadEventLoopToCompletion()
|
/// Default is true. If this is true, RunMainThreadEventLoopToCompletion()
|
||||||
/// will be called to run the app. This should return false on builds
|
/// will be called to run the app. This should return false on builds
|
||||||
@ -181,6 +191,17 @@ class AppAdapter {
|
|||||||
/// should be callable from any thread.
|
/// should be callable from any thread.
|
||||||
virtual auto HasDirectKeyboardInput() -> bool;
|
virtual auto HasDirectKeyboardInput() -> bool;
|
||||||
|
|
||||||
|
/// Called in the graphics context to apply new settings coming in from
|
||||||
|
/// the logic subsystem. This will be called initially to jump-start the
|
||||||
|
/// graphics system as well as before frame draws to update any new
|
||||||
|
/// settings coming in.
|
||||||
|
///
|
||||||
|
/// Whenever graphics settings will result in a change to the graphics
|
||||||
|
/// context (ie: something visible to rendering code in the logic thread)
|
||||||
|
/// the adapter should call g_base->graphics_server->set_context() with
|
||||||
|
/// the updated context.
|
||||||
|
virtual void ApplyGraphicsSettings(const GraphicsSettings* settings);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AppAdapter();
|
AppAdapter();
|
||||||
virtual ~AppAdapter();
|
virtual ~AppAdapter();
|
||||||
|
|||||||
@ -44,58 +44,27 @@ void AppAdapterApple::DoPushMainThreadRunnable(Runnable* runnable) {
|
|||||||
BallisticaKit::FromCppPushRawRunnableToMain(runnable);
|
BallisticaKit::FromCppPushRawRunnableToMain(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterApple::DoApplyAppConfig() {
|
void AppAdapterApple::DoApplyAppConfig() { assert(g_base->InLogicThread()); }
|
||||||
assert(g_base->InLogicThread());
|
|
||||||
|
|
||||||
g_base->graphics_server->PushSetScreenPixelScaleCall(
|
void AppAdapterApple::ApplyGraphicsSettings(const GraphicsSettings* settings) {
|
||||||
g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale));
|
auto* graphics_server = g_base->graphics_server;
|
||||||
|
|
||||||
auto graphics_quality_requested =
|
// We need a full renderer reload if quality values have changed
|
||||||
g_base->graphics->GraphicsQualityFromAppConfig();
|
// or if we don't have a renderer yet.
|
||||||
|
bool need_full_reload = ((graphics_server->texture_quality_requested()
|
||||||
auto texture_quality_requested =
|
!= settings->texture_quality)
|
||||||
g_base->graphics->TextureQualityFromAppConfig();
|
|| (graphics_server->graphics_quality_requested()
|
||||||
|
!= settings->graphics_quality));
|
||||||
g_base->app_adapter->PushGraphicsContextCall([=] {
|
|
||||||
SetScreen_(texture_quality_requested, graphics_quality_requested);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppAdapterApple::SetScreen_(
|
|
||||||
TextureQualityRequest texture_quality_requested,
|
|
||||||
GraphicsQualityRequest graphics_quality_requested) {
|
|
||||||
// If we know what we support, filter our request types to what is
|
|
||||||
// supported. This will keep us from rebuilding contexts if request type
|
|
||||||
// is flipping between different types that we don't support.
|
|
||||||
if (g_base->graphics->has_supports_high_quality_graphics_value()) {
|
|
||||||
if (!g_base->graphics->supports_high_quality_graphics()
|
|
||||||
&& graphics_quality_requested > GraphicsQualityRequest::kMedium) {
|
|
||||||
graphics_quality_requested = GraphicsQualityRequest::kMedium;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* gs = g_base->graphics_server;
|
|
||||||
|
|
||||||
// We need a full renderer reload if quality values have changed or if we
|
// We need a full renderer reload if quality values have changed or if we
|
||||||
// don't have one yet.
|
// don't yet have a renderer.
|
||||||
bool need_full_reload =
|
|
||||||
((gs->texture_quality_requested() != texture_quality_requested)
|
|
||||||
|| (gs->graphics_quality_requested() != graphics_quality_requested)
|
|
||||||
|| !gs->texture_quality_set() || !gs->graphics_quality_set());
|
|
||||||
|
|
||||||
if (need_full_reload) {
|
if (need_full_reload) {
|
||||||
ReloadRenderer_(graphics_quality_requested, texture_quality_requested);
|
ReloadRenderer_(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the logic thread know we've got a graphics system up and running.
|
|
||||||
// It may use this cue to kick off asset loads and other bootstrapping.
|
|
||||||
g_base->logic->event_loop()->PushCall(
|
|
||||||
[] { g_base->logic->OnGraphicsReady(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterApple::ReloadRenderer_(
|
void AppAdapterApple::ReloadRenderer_(const GraphicsSettings* settings) {
|
||||||
GraphicsQualityRequest graphics_quality_requested,
|
|
||||||
TextureQualityRequest texture_quality_requested) {
|
|
||||||
auto* gs = g_base->graphics_server;
|
auto* gs = g_base->graphics_server;
|
||||||
|
|
||||||
if (gs->renderer() && gs->renderer_loaded()) {
|
if (gs->renderer() && gs->renderer_loaded()) {
|
||||||
@ -109,11 +78,11 @@ void AppAdapterApple::ReloadRenderer_(
|
|||||||
// along the latest real resolution just before each frame draw, but we
|
// along the latest real resolution just before each frame draw, but we
|
||||||
// need *something* here or else we'll get errors due to framebuffers
|
// need *something* here or else we'll get errors due to framebuffers
|
||||||
// getting made at size 0/etc.
|
// getting made at size 0/etc.
|
||||||
g_base->graphics_server->SetScreenResolution(320.0, 240.0);
|
// g_base->graphics_server->SetScreenResolution(320.0, 240.0);
|
||||||
|
|
||||||
// Update graphics quality based on request.
|
// Update graphics quality based on request.
|
||||||
gs->set_graphics_quality_requested(graphics_quality_requested);
|
gs->set_graphics_quality_requested(settings->graphics_quality);
|
||||||
gs->set_texture_quality_requested(texture_quality_requested);
|
gs->set_texture_quality_requested(settings->texture_quality);
|
||||||
|
|
||||||
// (Re)load stuff with these latest quality settings.
|
// (Re)load stuff with these latest quality settings.
|
||||||
gs->LoadRenderer();
|
gs->LoadRenderer();
|
||||||
@ -123,12 +92,6 @@ void AppAdapterApple::UpdateScreenSizes_() {
|
|||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterApple::SetScreenResolution(float pixel_width,
|
|
||||||
float pixel_height) {
|
|
||||||
auto allow = ScopedAllowGraphics_(this);
|
|
||||||
g_base->graphics_server->SetScreenResolution(pixel_width, pixel_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto AppAdapterApple::TryRender() -> bool {
|
auto AppAdapterApple::TryRender() -> bool {
|
||||||
auto allow = ScopedAllowGraphics_(this);
|
auto allow = ScopedAllowGraphics_(this);
|
||||||
|
|
||||||
@ -146,10 +109,45 @@ auto AppAdapterApple::TryRender() -> bool {
|
|||||||
call->RunAndLogErrors();
|
call->RunAndLogErrors();
|
||||||
delete call;
|
delete call;
|
||||||
}
|
}
|
||||||
// Lastly render.
|
|
||||||
return g_base->graphics_server->TryRender();
|
|
||||||
|
|
||||||
return true;
|
// Lastly, render.
|
||||||
|
auto result = g_base->graphics_server->TryRender();
|
||||||
|
|
||||||
|
// A little trick to make mac resizing look a lot smoother. Because we
|
||||||
|
// render in a background thread, we often don't render at the most up to
|
||||||
|
// date window size during a window resize. Normally this makes our image
|
||||||
|
// jerk around in an ugly way, but if we just re-render once or twice in
|
||||||
|
// those cases we mostly always get the most up to date window size.
|
||||||
|
if (result && resize_friendly_frames_ > 0) {
|
||||||
|
// Leave this enabled for just a few frames every time it is set.
|
||||||
|
// (so just in case it breaks we won't draw each frame serveral times for
|
||||||
|
// eternity).
|
||||||
|
resize_friendly_frames_ -= 1;
|
||||||
|
|
||||||
|
// Keep on drawing until the drawn window size
|
||||||
|
// matches what we have (or until we try for too long or fail at drawing).
|
||||||
|
seconds_t start_time = g_core->GetAppTimeSeconds();
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
if (((std::abs(resize_target_resolution_.x
|
||||||
|
- g_base->graphics_server->screen_pixel_width())
|
||||||
|
> 0.01f)
|
||||||
|
|| (std::abs(resize_target_resolution_.y
|
||||||
|
- g_base->graphics_server->screen_pixel_height())
|
||||||
|
> 0.01f))
|
||||||
|
&& g_core->GetAppTimeSeconds() - start_time < 0.1 && result) {
|
||||||
|
result = g_base->graphics_server->TryRender();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppAdapterApple::EnableResizeFriendlyMode(int width, int height) {
|
||||||
|
resize_friendly_frames_ = 5;
|
||||||
|
resize_target_resolution_ = Vector2f(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AppAdapterApple::InGraphicsContext() -> bool {
|
auto AppAdapterApple::InGraphicsContext() -> bool {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||||
#include "ballistica/shared/generic/runnable.h"
|
#include "ballistica/shared/generic/runnable.h"
|
||||||
|
#include "ballistica/shared/math/vector2f.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ class AppAdapterApple : public AppAdapter {
|
|||||||
auto TryRender() -> bool;
|
auto TryRender() -> bool;
|
||||||
|
|
||||||
/// Called by FromSwift.
|
/// Called by FromSwift.
|
||||||
void SetScreenResolution(float pixel_width, float pixel_height);
|
// void SetScreenResolution(float pixel_width, float pixel_height);
|
||||||
|
|
||||||
auto FullscreenControlAvailable() const -> bool override;
|
auto FullscreenControlAvailable() const -> bool override;
|
||||||
auto FullscreenControlGet() const -> bool override;
|
auto FullscreenControlGet() const -> bool override;
|
||||||
@ -42,6 +43,8 @@ class AppAdapterApple : public AppAdapter {
|
|||||||
|
|
||||||
auto HasDirectKeyboardInput() -> bool override;
|
auto HasDirectKeyboardInput() -> bool override;
|
||||||
|
|
||||||
|
void EnableResizeFriendlyMode(int width, int height);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
||||||
void DoPushGraphicsContextRunnable(Runnable* runnable) override;
|
void DoPushGraphicsContextRunnable(Runnable* runnable) override;
|
||||||
@ -50,16 +53,18 @@ class AppAdapterApple : public AppAdapter {
|
|||||||
auto HasHardwareCursor() -> bool override;
|
auto HasHardwareCursor() -> bool override;
|
||||||
void SetHardwareCursorVisible(bool visible) override;
|
void SetHardwareCursorVisible(bool visible) override;
|
||||||
void TerminateApp() override;
|
void TerminateApp() override;
|
||||||
|
void ApplyGraphicsSettings(const GraphicsSettings* settings) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateScreenSizes_();
|
|
||||||
class ScopedAllowGraphics_;
|
class ScopedAllowGraphics_;
|
||||||
void SetScreen_(TextureQualityRequest texture_quality_requested,
|
|
||||||
GraphicsQualityRequest graphics_quality_requested);
|
void UpdateScreenSizes_();
|
||||||
void ReloadRenderer_(GraphicsQualityRequest graphics_quality_requested,
|
void ReloadRenderer_(const GraphicsSettings* settings);
|
||||||
TextureQualityRequest texture_quality_requested);
|
|
||||||
std::thread::id graphics_thread_{};
|
std::thread::id graphics_thread_{};
|
||||||
bool graphics_allowed_;
|
bool graphics_allowed_ : 1 {};
|
||||||
|
uint8_t resize_friendly_frames_{};
|
||||||
|
Vector2f resize_target_resolution_{-1.0f, -1.0f};
|
||||||
std::mutex graphics_calls_mutex_;
|
std::mutex graphics_calls_mutex_;
|
||||||
std::vector<Runnable*> graphics_calls_;
|
std::vector<Runnable*> graphics_calls_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "ballistica/base/app_adapter/app_adapter_headless.h"
|
#include "ballistica/base/app_adapter/app_adapter_headless.h"
|
||||||
|
|
||||||
#include "ballistica/base/graphics/graphics_server.h"
|
#include "ballistica/base/graphics/graphics_server.h"
|
||||||
|
#include "ballistica/base/graphics/support/graphics_client_context.h"
|
||||||
#include "ballistica/shared/ballistica.h"
|
#include "ballistica/shared/ballistica.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
@ -19,12 +20,7 @@ void AppAdapterHeadless::OnMainThreadStartApp() {
|
|||||||
new EventLoop(EventLoopID::kMain, ThreadSource::kWrapCurrent);
|
new EventLoop(EventLoopID::kMain, ThreadSource::kWrapCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterHeadless::DoApplyAppConfig() {
|
void AppAdapterHeadless::DoApplyAppConfig() {}
|
||||||
// Normal graphical app-adapters kick off screen creation here
|
|
||||||
// which then leads to remaining app bootstrapping. We create
|
|
||||||
// a 'null' screen purely for the same effect.
|
|
||||||
PushMainThreadCall([] { g_base->graphics_server->SetNullGraphics(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppAdapterHeadless::RunMainThreadEventLoopToCompletion() {
|
void AppAdapterHeadless::RunMainThreadEventLoopToCompletion() {
|
||||||
assert(g_core->InMainThread());
|
assert(g_core->InMainThread());
|
||||||
@ -40,6 +36,11 @@ void AppAdapterHeadless::DoExitMainThreadEventLoop() {
|
|||||||
main_event_loop_->Exit();
|
main_event_loop_->Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto AppAdapterHeadless::GetGraphicsClientContext() -> GraphicsClientContext* {
|
||||||
|
// Special dummy form.
|
||||||
|
return new GraphicsClientContext(0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|
||||||
#endif // BA_HEADLESS_BUILD
|
#endif // BA_HEADLESS_BUILD
|
||||||
|
|||||||
@ -17,6 +17,8 @@ class AppAdapterHeadless : public AppAdapter {
|
|||||||
|
|
||||||
void DoApplyAppConfig() override;
|
void DoApplyAppConfig() override;
|
||||||
|
|
||||||
|
auto GetGraphicsClientContext() -> GraphicsClientContext* override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
||||||
void RunMainThreadEventLoopToCompletion() override;
|
void RunMainThreadEventLoopToCompletion() override;
|
||||||
|
|||||||
@ -104,32 +104,115 @@ void AppAdapterSDL::OnMainThreadStartApp() {
|
|||||||
SDL_ShowCursor(SDL_DISABLE);
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Our particular flavor of graphics settings.
|
||||||
|
struct AppAdapterSDL::GraphicsSettings_ : public GraphicsSettings {
|
||||||
|
bool fullscreen = g_base->app_config->Resolve(AppConfig::BoolID::kFullscreen);
|
||||||
|
VSyncRequest vsync = g_base->graphics->VSyncFromAppConfig();
|
||||||
|
int max_fps = g_base->app_config->Resolve(AppConfig::IntID::kMaxFPS);
|
||||||
|
};
|
||||||
|
|
||||||
void AppAdapterSDL::DoApplyAppConfig() {
|
void AppAdapterSDL::DoApplyAppConfig() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
g_base->graphics_server->PushSetScreenPixelScaleCall(
|
|
||||||
g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale));
|
|
||||||
|
|
||||||
auto graphics_quality_requested =
|
|
||||||
g_base->graphics->GraphicsQualityFromAppConfig();
|
|
||||||
|
|
||||||
auto texture_quality_requested =
|
|
||||||
g_base->graphics->TextureQualityFromAppConfig();
|
|
||||||
|
|
||||||
// Android res string.
|
// Android res string.
|
||||||
// std::string android_res =
|
// std::string android_res =
|
||||||
// g_base->app_config->Resolve(AppConfig::StringID::kResolutionAndroid);
|
// g_base->app_config->Resolve(AppConfig::StringID::kResolutionAndroid);
|
||||||
|
}
|
||||||
|
|
||||||
bool fullscreen = g_base->app_config->Resolve(AppConfig::BoolID::kFullscreen);
|
auto AppAdapterSDL::GetGraphicsSettings() -> GraphicsSettings* {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
return new GraphicsSettings_();
|
||||||
|
}
|
||||||
|
|
||||||
auto vsync = g_base->graphics->VSyncFromAppConfig();
|
void AppAdapterSDL::ApplyGraphicsSettings(
|
||||||
int max_fps = g_base->app_config->Resolve(AppConfig::IntID::kMaxFPS);
|
const GraphicsSettings* settings_base) {
|
||||||
|
assert(g_core->InMainThread());
|
||||||
|
assert(!g_core->HeadlessMode());
|
||||||
|
|
||||||
// Tell the main thread to set up the screen with these settings.
|
// In strict mode, allow graphics stuff while in here.
|
||||||
g_base->app_adapter->PushMainThreadCall([=] {
|
auto allow = ScopedAllowGraphics_(this);
|
||||||
SetScreen_(fullscreen, max_fps, vsync, texture_quality_requested,
|
|
||||||
graphics_quality_requested);
|
// Settings will always be our subclass (since we created it).
|
||||||
});
|
auto* settings = static_cast<const GraphicsSettings_*>(settings_base);
|
||||||
|
|
||||||
|
// Apply any changes.
|
||||||
|
bool do_toggle_fs{};
|
||||||
|
bool do_set_existing_fullscreen{};
|
||||||
|
|
||||||
|
auto* graphics_server = g_base->graphics_server;
|
||||||
|
|
||||||
|
// We need a full renderer reload if quality values have changed
|
||||||
|
// or if we don't have a renderer yet.
|
||||||
|
bool need_full_reload = ((sdl_window_ == nullptr
|
||||||
|
|| graphics_server->texture_quality_requested()
|
||||||
|
!= settings->texture_quality)
|
||||||
|
|| (graphics_server->graphics_quality_requested()
|
||||||
|
!= settings->graphics_quality));
|
||||||
|
|
||||||
|
if (need_full_reload) {
|
||||||
|
ReloadRenderer_(settings);
|
||||||
|
} else if (settings->fullscreen != fullscreen_) {
|
||||||
|
SDL_SetWindowFullscreen(
|
||||||
|
sdl_window_, settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||||
|
fullscreen_ = settings->fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VSync always gets set independent of the screen (though we set it down
|
||||||
|
// here to make sure we have a screen when its set).
|
||||||
|
VSync vsync;
|
||||||
|
switch (settings->vsync) {
|
||||||
|
case VSyncRequest::kNever:
|
||||||
|
vsync = VSync::kNever;
|
||||||
|
break;
|
||||||
|
case VSyncRequest::kAlways:
|
||||||
|
vsync = VSync::kAlways;
|
||||||
|
break;
|
||||||
|
case VSyncRequest::kAuto:
|
||||||
|
vsync = VSync::kAdaptive;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vsync = VSync::kNever;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (vsync != vsync_) {
|
||||||
|
switch (vsync) {
|
||||||
|
case VSync::kUnset:
|
||||||
|
case VSync::kNever: {
|
||||||
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
vsync_actually_enabled_ = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VSync::kAlways: {
|
||||||
|
SDL_GL_SetSwapInterval(1);
|
||||||
|
vsync_actually_enabled_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VSync::kAdaptive: {
|
||||||
|
// In this case, let's try setting to 'adaptive' and turn it off if
|
||||||
|
// that is unsupported.
|
||||||
|
auto result = SDL_GL_SetSwapInterval(-1);
|
||||||
|
if (result == 0) {
|
||||||
|
vsync_actually_enabled_ = true;
|
||||||
|
} else {
|
||||||
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
vsync_actually_enabled_ = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vsync_ = vsync;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This we can set anytime. Probably could have just set it from the logic
|
||||||
|
// thread where we read it, but let's be pedantic and keep everything to
|
||||||
|
// the main thread.
|
||||||
|
max_fps_ = settings->max_fps;
|
||||||
|
|
||||||
|
// Take -1 to mean no max. Otherwise clamp to a reasonable range.
|
||||||
|
if (max_fps_ != -1) {
|
||||||
|
max_fps_ = std::max(10, max_fps_);
|
||||||
|
max_fps_ = std::min(99999, max_fps_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterSDL::RunMainThreadEventLoopToCompletion() {
|
void AppAdapterSDL::RunMainThreadEventLoopToCompletion() {
|
||||||
@ -158,7 +241,7 @@ void AppAdapterSDL::RunMainThreadEventLoopToCompletion() {
|
|||||||
|
|
||||||
auto AppAdapterSDL::TryRender() -> bool {
|
auto AppAdapterSDL::TryRender() -> bool {
|
||||||
if (strict_graphics_context_) {
|
if (strict_graphics_context_) {
|
||||||
// In strict mode, allow graphics stuff in here. Normally we allow it
|
// In strict mode, allow graphics stuff in here. Otherwise we allow it
|
||||||
// anywhere in the main thread.
|
// anywhere in the main thread.
|
||||||
auto allow = ScopedAllowGraphics_(this);
|
auto allow = ScopedAllowGraphics_(this);
|
||||||
|
|
||||||
@ -179,7 +262,7 @@ auto AppAdapterSDL::TryRender() -> bool {
|
|||||||
// Lastly render.
|
// Lastly render.
|
||||||
return g_base->graphics_server->TryRender();
|
return g_base->graphics_server->TryRender();
|
||||||
} else {
|
} else {
|
||||||
// Simple path; just render.
|
// Simpler path; just render.
|
||||||
return g_base->graphics_server->TryRender();
|
return g_base->graphics_server->TryRender();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,7 +271,7 @@ void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) {
|
|||||||
// Special case: if we're hidden, we simply sleep for a long bit; no fancy
|
// Special case: if we're hidden, we simply sleep for a long bit; no fancy
|
||||||
// timing.
|
// timing.
|
||||||
if (hidden_) {
|
if (hidden_) {
|
||||||
g_core->platform->SleepMillisecs(100);
|
g_core->platform->SleepSeconds(0.1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +442,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
if (g_core->GetAppTimeMillisecs() - last_windowevent_close_time_ < 100) {
|
if (g_core->GetAppTimeSeconds() - last_windowevent_close_time_ < 0.1) {
|
||||||
// If they hit the window close button, skip the confirm.
|
// If they hit the window close button, skip the confirm.
|
||||||
g_base->QuitApp(false);
|
g_base->QuitApp(false);
|
||||||
} else {
|
} else {
|
||||||
@ -380,7 +463,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) {
|
|||||||
case SDL_WINDOWEVENT_CLOSE: {
|
case SDL_WINDOWEVENT_CLOSE: {
|
||||||
// Simply note that this happened. We use this to adjust our
|
// Simply note that this happened. We use this to adjust our
|
||||||
// SDL_QUIT behavior (quit is called right after this).
|
// SDL_QUIT behavior (quit is called right after this).
|
||||||
last_windowevent_close_time_ = g_core->GetAppTimeMillisecs();
|
last_windowevent_close_time_ = g_core->GetAppTimeSeconds();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,114 +629,96 @@ auto AppAdapterSDL::GetSDLJoystickInput_(int sdl_joystick_id) const
|
|||||||
return nullptr; // Epic fail.
|
return nullptr; // Epic fail.
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterSDL::SetScreen_(
|
// void AppAdapterSDL::ApplyGraphicsSettings_(const GraphicsSettings_* settings)
|
||||||
bool fullscreen, int max_fps, VSyncRequest vsync_requested,
|
// {
|
||||||
TextureQualityRequest texture_quality_requested,
|
// assert(g_core->InMainThread());
|
||||||
GraphicsQualityRequest graphics_quality_requested) {
|
// assert(!g_core->HeadlessMode());
|
||||||
assert(g_core->InMainThread());
|
|
||||||
assert(!g_core->HeadlessMode());
|
|
||||||
|
|
||||||
// In strict mode, allow graphics stuff in here.
|
// // In strict mode, allow graphics stuff while in here.
|
||||||
auto allow = ScopedAllowGraphics_(this);
|
// auto allow = ScopedAllowGraphics_(this);
|
||||||
|
|
||||||
// If we know what we support, filter our request types to what is
|
// bool do_toggle_fs{};
|
||||||
// supported. This will keep us from rebuilding contexts if request type
|
// bool do_set_existing_fullscreen{};
|
||||||
// is flipping between different types that we don't support.
|
|
||||||
if (g_base->graphics->has_supports_high_quality_graphics_value()) {
|
|
||||||
if (!g_base->graphics->supports_high_quality_graphics()
|
|
||||||
&& graphics_quality_requested > GraphicsQualityRequest::kMedium) {
|
|
||||||
graphics_quality_requested = GraphicsQualityRequest::kMedium;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool do_toggle_fs{};
|
// auto* graphics_server = g_base->graphics_server;
|
||||||
bool do_set_existing_fullscreen{};
|
|
||||||
|
|
||||||
auto* gs = g_base->graphics_server;
|
// // We need a full renderer reload if quality values have changed
|
||||||
|
// // or if we don't have a renderer yet.
|
||||||
|
// bool need_full_reload = ((sdl_window_ == nullptr
|
||||||
|
// || graphics_server->texture_quality_requested()
|
||||||
|
// != settings->texture_quality)
|
||||||
|
// || (graphics_server->graphics_quality_requested()
|
||||||
|
// != settings->graphics_quality));
|
||||||
|
|
||||||
// We need a full renderer reload if quality values have changed
|
// if (need_full_reload) {
|
||||||
// or if we don't have one yet.
|
// ReloadRenderer_(settings->fullscreen, settings->graphics_quality,
|
||||||
bool need_full_reload =
|
// settings->texture_quality);
|
||||||
((sdl_window_ == nullptr
|
// } else if (settings->fullscreen != fullscreen_) {
|
||||||
|| gs->texture_quality_requested() != texture_quality_requested)
|
// SDL_SetWindowFullscreen(
|
||||||
|| (gs->graphics_quality_requested() != graphics_quality_requested)
|
// sdl_window_, settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP :
|
||||||
|| !gs->texture_quality_set() || !gs->graphics_quality_set());
|
// 0);
|
||||||
|
// fullscreen_ = settings->fullscreen;
|
||||||
|
// }
|
||||||
|
|
||||||
if (need_full_reload) {
|
// // VSync always gets set independent of the screen (though we set it down
|
||||||
ReloadRenderer_(fullscreen, graphics_quality_requested,
|
// // here to make sure we have a screen when its set).
|
||||||
texture_quality_requested);
|
// VSync vsync;
|
||||||
} else if (fullscreen != fullscreen_) {
|
// switch (settings->vsync) {
|
||||||
SDL_SetWindowFullscreen(sdl_window_,
|
// case VSyncRequest::kNever:
|
||||||
fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
// vsync = VSync::kNever;
|
||||||
fullscreen_ = fullscreen;
|
// break;
|
||||||
}
|
// case VSyncRequest::kAlways:
|
||||||
|
// vsync = VSync::kAlways;
|
||||||
|
// break;
|
||||||
|
// case VSyncRequest::kAuto:
|
||||||
|
// vsync = VSync::kAdaptive;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// vsync = VSync::kNever;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// if (vsync != vsync_) {
|
||||||
|
// switch (vsync) {
|
||||||
|
// case VSync::kUnset:
|
||||||
|
// case VSync::kNever: {
|
||||||
|
// SDL_GL_SetSwapInterval(0);
|
||||||
|
// vsync_actually_enabled_ = false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case VSync::kAlways: {
|
||||||
|
// SDL_GL_SetSwapInterval(1);
|
||||||
|
// vsync_actually_enabled_ = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// case VSync::kAdaptive: {
|
||||||
|
// // In this case, let's try setting to 'adaptive' and turn it off if
|
||||||
|
// // that is unsupported.
|
||||||
|
// auto result = SDL_GL_SetSwapInterval(-1);
|
||||||
|
// if (result == 0) {
|
||||||
|
// vsync_actually_enabled_ = true;
|
||||||
|
// } else {
|
||||||
|
// SDL_GL_SetSwapInterval(0);
|
||||||
|
// vsync_actually_enabled_ = false;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// vsync_ = vsync;
|
||||||
|
// }
|
||||||
|
|
||||||
// VSync always gets set independent of the screen (though we set it down
|
// // This we can set anytime. Probably could have just set it from the logic
|
||||||
// here to make sure we have a screen when its set).
|
// // thread where we read it, but let's be pedantic and keep everything to
|
||||||
VSync vsync;
|
// // the main thread.
|
||||||
switch (vsync_requested) {
|
// max_fps_ = settings->max_fps;
|
||||||
case VSyncRequest::kNever:
|
|
||||||
vsync = VSync::kNever;
|
|
||||||
break;
|
|
||||||
case VSyncRequest::kAlways:
|
|
||||||
vsync = VSync::kAlways;
|
|
||||||
break;
|
|
||||||
case VSyncRequest::kAuto:
|
|
||||||
vsync = VSync::kAdaptive;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vsync = VSync::kNever;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (vsync != vsync_) {
|
|
||||||
switch (vsync) {
|
|
||||||
case VSync::kUnset:
|
|
||||||
case VSync::kNever: {
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
|
||||||
vsync_actually_enabled_ = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case VSync::kAlways: {
|
|
||||||
SDL_GL_SetSwapInterval(1);
|
|
||||||
vsync_actually_enabled_ = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case VSync::kAdaptive: {
|
|
||||||
// In this case, let's try setting to 'adaptive' and turn it off if
|
|
||||||
// that is unsupported.
|
|
||||||
auto result = SDL_GL_SetSwapInterval(-1);
|
|
||||||
if (result == 0) {
|
|
||||||
vsync_actually_enabled_ = true;
|
|
||||||
} else {
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
|
||||||
vsync_actually_enabled_ = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vsync_ = vsync;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This we can set anytime. Probably could have just set it from the logic
|
// // Take -1 to mean no max. Otherwise clamp to a reasonable range.
|
||||||
// thread where we read it, but let's be pedantic and keep everything to
|
// if (max_fps_ != -1) {
|
||||||
// the main thread.
|
// max_fps_ = std::max(10, max_fps_);
|
||||||
max_fps_ = max_fps;
|
// max_fps_ = std::min(99999, max_fps_);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// Take -1 to mean no max. Otherwise clamp to a reasonable range.
|
void AppAdapterSDL::ReloadRenderer_(const GraphicsSettings_* settings) {
|
||||||
if (max_fps_ != -1) {
|
|
||||||
max_fps_ = std::max(10, max_fps_);
|
|
||||||
max_fps_ = std::min(99999, max_fps_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the logic thread know we've got a graphics system up and running.
|
|
||||||
// It may use this cue to kick off asset loads and other bootstrapping.
|
|
||||||
g_base->logic->event_loop()->PushCall(
|
|
||||||
[] { g_base->logic->OnGraphicsReady(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppAdapterSDL::ReloadRenderer_(
|
|
||||||
bool fullscreen, GraphicsQualityRequest graphics_quality_requested,
|
|
||||||
TextureQualityRequest texture_quality_requested) {
|
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
|
||||||
auto* gs = g_base->graphics_server;
|
auto* gs = g_base->graphics_server;
|
||||||
@ -664,7 +729,7 @@ void AppAdapterSDL::ReloadRenderer_(
|
|||||||
|
|
||||||
// If we don't haven't yet, create our window and renderer.
|
// If we don't haven't yet, create our window and renderer.
|
||||||
if (!sdl_window_) {
|
if (!sdl_window_) {
|
||||||
fullscreen_ = fullscreen;
|
fullscreen_ = settings->fullscreen;
|
||||||
|
|
||||||
// A reasonable default window size.
|
// A reasonable default window size.
|
||||||
auto width = static_cast<int>(kBaseVirtualResX * 0.8f);
|
auto width = static_cast<int>(kBaseVirtualResX * 0.8f);
|
||||||
@ -672,7 +737,7 @@ void AppAdapterSDL::ReloadRenderer_(
|
|||||||
|
|
||||||
uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||||
| SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
| SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
||||||
if (fullscreen) {
|
if (settings->fullscreen) {
|
||||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,15 +794,16 @@ void AppAdapterSDL::ReloadRenderer_(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update graphics quality based on request.
|
// Update graphics-server's qualities based on request.
|
||||||
gs->set_graphics_quality_requested(graphics_quality_requested);
|
gs->set_graphics_quality_requested(settings->graphics_quality);
|
||||||
gs->set_texture_quality_requested(texture_quality_requested);
|
gs->set_texture_quality_requested(settings->texture_quality);
|
||||||
|
|
||||||
gs->LoadRenderer();
|
gs->LoadRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterSDL::UpdateScreenSizes_() {
|
void AppAdapterSDL::UpdateScreenSizes_() {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
// This runs in the main thread in response to SDL events.
|
||||||
|
assert(g_core->InMainThread());
|
||||||
|
|
||||||
// Grab logical window dimensions (points?). This is the coordinate space
|
// Grab logical window dimensions (points?). This is the coordinate space
|
||||||
// SDL's events deal in.
|
// SDL's events deal in.
|
||||||
@ -749,8 +815,13 @@ void AppAdapterSDL::UpdateScreenSizes_() {
|
|||||||
// dimensions.
|
// dimensions.
|
||||||
int pixels_x, pixels_y;
|
int pixels_x, pixels_y;
|
||||||
SDL_GL_GetDrawableSize(sdl_window_, &pixels_x, &pixels_y);
|
SDL_GL_GetDrawableSize(sdl_window_, &pixels_x, &pixels_y);
|
||||||
g_base->graphics_server->SetScreenResolution(static_cast<float>(pixels_x),
|
|
||||||
static_cast<float>(pixels_y));
|
// Push this over to the logic thread which owns the canonical value
|
||||||
|
// for this.
|
||||||
|
g_base->logic->event_loop()->PushCall([pixels_x, pixels_y] {
|
||||||
|
g_base->graphics->SetScreenResolution(static_cast<float>(pixels_x),
|
||||||
|
static_cast<float>(pixels_y));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AppAdapterSDL::InGraphicsContext() -> bool {
|
auto AppAdapterSDL::InGraphicsContext() -> bool {
|
||||||
|
|||||||
@ -41,6 +41,9 @@ class AppAdapterSDL : public AppAdapter {
|
|||||||
auto SupportsMaxFPS() -> bool const override;
|
auto SupportsMaxFPS() -> bool const override;
|
||||||
|
|
||||||
auto HasDirectKeyboardInput() -> bool override;
|
auto HasDirectKeyboardInput() -> bool override;
|
||||||
|
void ApplyGraphicsSettings(const GraphicsSettings* settings) override;
|
||||||
|
|
||||||
|
auto GetGraphicsSettings() -> GraphicsSettings* override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
void DoPushMainThreadRunnable(Runnable* runnable) override;
|
||||||
@ -52,14 +55,11 @@ class AppAdapterSDL : public AppAdapter {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
class ScopedAllowGraphics_;
|
class ScopedAllowGraphics_;
|
||||||
void SetScreen_(bool fullscreen, int max_fps, VSyncRequest vsync_requested,
|
struct GraphicsSettings_;
|
||||||
TextureQualityRequest texture_quality_requested,
|
|
||||||
GraphicsQualityRequest graphics_quality_requested);
|
|
||||||
void HandleSDLEvent_(const SDL_Event& event);
|
void HandleSDLEvent_(const SDL_Event& event);
|
||||||
void UpdateScreenSizes_();
|
void UpdateScreenSizes_();
|
||||||
void ReloadRenderer_(bool fullscreen,
|
void ReloadRenderer_(const GraphicsSettings_* settings);
|
||||||
GraphicsQualityRequest graphics_quality_requested,
|
|
||||||
TextureQualityRequest texture_quality_requested);
|
|
||||||
void OnSDLJoystickAdded_(int index);
|
void OnSDLJoystickAdded_(int index);
|
||||||
void OnSDLJoystickRemoved_(int index);
|
void OnSDLJoystickRemoved_(int index);
|
||||||
// Given an SDL joystick ID, returns our Ballistica input for it.
|
// Given an SDL joystick ID, returns our Ballistica input for it.
|
||||||
@ -70,6 +70,7 @@ class AppAdapterSDL : public AppAdapter {
|
|||||||
void RemoveSDLInputDevice_(int index);
|
void RemoveSDLInputDevice_(int index);
|
||||||
void SleepUntilNextEventCycle_(microsecs_t cycle_start_time);
|
void SleepUntilNextEventCycle_(microsecs_t cycle_start_time);
|
||||||
|
|
||||||
|
int max_fps_{60};
|
||||||
bool done_ : 1 {};
|
bool done_ : 1 {};
|
||||||
bool fullscreen_ : 1 {};
|
bool fullscreen_ : 1 {};
|
||||||
bool vsync_actually_enabled_ : 1 {};
|
bool vsync_actually_enabled_ : 1 {};
|
||||||
@ -85,17 +86,16 @@ class AppAdapterSDL : public AppAdapter {
|
|||||||
/// that require such a setup.
|
/// that require such a setup.
|
||||||
bool strict_graphics_context_ : 1 {};
|
bool strict_graphics_context_ : 1 {};
|
||||||
bool strict_graphics_allowed_ : 1 {};
|
bool strict_graphics_allowed_ : 1 {};
|
||||||
std::mutex strict_graphics_calls_mutex_;
|
|
||||||
std::vector<Runnable*> strict_graphics_calls_;
|
|
||||||
VSync vsync_{VSync::kUnset};
|
VSync vsync_{VSync::kUnset};
|
||||||
uint32_t sdl_runnable_event_id_{};
|
uint32_t sdl_runnable_event_id_{};
|
||||||
int max_fps_{60};
|
std::mutex strict_graphics_calls_mutex_;
|
||||||
|
std::vector<Runnable*> strict_graphics_calls_;
|
||||||
microsecs_t oversleep_{};
|
microsecs_t oversleep_{};
|
||||||
std::vector<JoystickInput*> sdl_joysticks_;
|
std::vector<JoystickInput*> sdl_joysticks_;
|
||||||
Vector2f window_size_{1.0f, 1.0f};
|
Vector2f window_size_{1.0f, 1.0f};
|
||||||
SDL_Window* sdl_window_{};
|
SDL_Window* sdl_window_{};
|
||||||
void* sdl_gl_context_{};
|
void* sdl_gl_context_{};
|
||||||
millisecs_t last_windowevent_close_time_{};
|
seconds_t last_windowevent_close_time_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|||||||
@ -40,7 +40,8 @@ void AppAdapterVR::PushVRSimpleRemoteStateCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterVR::VRSetDrawDimensions(int w, int h) {
|
void AppAdapterVR::VRSetDrawDimensions(int w, int h) {
|
||||||
g_base->graphics_server->SetScreenResolution(w, h);
|
FatalError("FIXME UPDATE SET-SCREEN-RESOLUTION");
|
||||||
|
// g_base->graphics_server->SetScreenResolution(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppAdapterVR::VRPreDraw() {
|
void AppAdapterVR::VRPreDraw() {
|
||||||
|
|||||||
@ -36,8 +36,6 @@ void AppMode::HandleGameQuery(const char* buffer, size_t size,
|
|||||||
|
|
||||||
auto AppMode::DoesWorldFillScreen() -> bool { return false; }
|
auto AppMode::DoesWorldFillScreen() -> bool { return false; }
|
||||||
|
|
||||||
void AppMode::GraphicsQualityChanged(GraphicsQuality quality) {}
|
|
||||||
|
|
||||||
void AppMode::DrawWorld(FrameDef* frame_def) {}
|
void AppMode::DrawWorld(FrameDef* frame_def) {}
|
||||||
|
|
||||||
void AppMode::ChangeGameSpeed(int offs) {}
|
void AppMode::ChangeGameSpeed(int offs) {}
|
||||||
|
|||||||
@ -62,8 +62,6 @@ class AppMode {
|
|||||||
|
|
||||||
virtual void DrawWorld(FrameDef* frame_def);
|
virtual void DrawWorld(FrameDef* frame_def);
|
||||||
|
|
||||||
virtual void GraphicsQualityChanged(GraphicsQuality quality);
|
|
||||||
|
|
||||||
/// Called whenever screen size changes.
|
/// Called whenever screen size changes.
|
||||||
virtual void OnScreenSizeChange();
|
virtual void OnScreenSizeChange();
|
||||||
|
|
||||||
|
|||||||
@ -82,8 +82,9 @@ void Assets::StartLoading() {
|
|||||||
assert(g_base);
|
assert(g_base);
|
||||||
assert(g_base->audio_server && g_base->assets_server
|
assert(g_base->audio_server && g_base->assets_server
|
||||||
&& g_base->graphics_server);
|
&& g_base->graphics_server);
|
||||||
assert(g_base->graphics_server->texture_compression_types_are_set());
|
assert(g_base->graphics->has_client_context());
|
||||||
assert(g_base->graphics_server->texture_quality_set());
|
// assert(g_base->graphics_server->texture_compression_types_are_set());
|
||||||
|
// assert(g_base->graphics_server->texture_quality_set());
|
||||||
|
|
||||||
assert(!asset_loads_allowed_); // We should only be called once.
|
assert(!asset_loads_allowed_); // We should only be called once.
|
||||||
asset_loads_allowed_ = true;
|
asset_loads_allowed_ = true;
|
||||||
@ -1102,10 +1103,13 @@ auto Assets::FindAssetFile(FileType type, const std::string& name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(g_base->graphics_server
|
// Make sure we know what compression/quality to use.
|
||||||
&& g_base->graphics_server->texture_compression_types_are_set());
|
assert(g_base->graphics->has_client_context());
|
||||||
assert(g_base->graphics_server
|
// assert(g_base->graphics_server
|
||||||
&& g_base->graphics_server->texture_quality_set());
|
// &&
|
||||||
|
// g_base->graphics_server->texture_compression_types_are_set());
|
||||||
|
// assert(g_base->graphics_server
|
||||||
|
// && g_base->graphics_server->texture_quality_set());
|
||||||
prefix = "textures/";
|
prefix = "textures/";
|
||||||
|
|
||||||
#if BA_OSTYPE_ANDROID && !BA_ANDROID_DDS_BUILD
|
#if BA_OSTYPE_ANDROID && !BA_ANDROID_DDS_BUILD
|
||||||
|
|||||||
@ -136,20 +136,21 @@ class Assets {
|
|||||||
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> asset_paths_;
|
int language_state_{};
|
||||||
bool have_pending_loads_[static_cast<int>(AssetType::kLast)]{};
|
bool have_pending_loads_[static_cast<int>(AssetType::kLast)]{};
|
||||||
|
|
||||||
|
// Will be true while a AssetListLock exists. Good to debug-verify this
|
||||||
|
// during any asset list access.
|
||||||
|
bool asset_lists_locked_ : 1 {};
|
||||||
|
bool asset_loads_allowed_ : 1 {};
|
||||||
|
bool sys_assets_loaded_ : 1 {};
|
||||||
|
|
||||||
|
std::vector<std::string> asset_paths_;
|
||||||
std::unordered_map<std::string, std::string> packages_;
|
std::unordered_map<std::string, std::string> packages_;
|
||||||
|
|
||||||
// For use by AssetListLock; don't manually acquire.
|
// For use by AssetListLock; don't manually acquire.
|
||||||
std::mutex asset_lists_mutex_;
|
std::mutex asset_lists_mutex_;
|
||||||
|
|
||||||
// Will be true while a AssetListLock exists. Good to debug-verify this
|
|
||||||
// during any asset list access.
|
|
||||||
bool asset_lists_locked_{};
|
|
||||||
|
|
||||||
// 'hard-wired' internal assets
|
|
||||||
bool asset_loads_allowed_{};
|
|
||||||
bool sys_assets_loaded_{};
|
|
||||||
std::vector<Object::Ref<TextureAsset> > system_textures_;
|
std::vector<Object::Ref<TextureAsset> > system_textures_;
|
||||||
std::vector<Object::Ref<TextureAsset> > system_cube_map_textures_;
|
std::vector<Object::Ref<TextureAsset> > system_cube_map_textures_;
|
||||||
std::vector<Object::Ref<SoundAsset> > system_sounds_;
|
std::vector<Object::Ref<SoundAsset> > system_sounds_;
|
||||||
@ -177,7 +178,6 @@ class Assets {
|
|||||||
// Text & Language (need to mold this into more asset-like concepts).
|
// Text & Language (need to mold this into more asset-like concepts).
|
||||||
std::mutex language_mutex_;
|
std::mutex language_mutex_;
|
||||||
std::unordered_map<std::string, std::string> language_;
|
std::unordered_map<std::string, std::string> language_;
|
||||||
int language_state_{};
|
|
||||||
std::mutex special_char_mutex_;
|
std::mutex special_char_mutex_;
|
||||||
std::unordered_map<SpecialChar, std::string> special_char_strings_;
|
std::unordered_map<SpecialChar, std::string> special_char_strings_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "ballistica/base/assets/asset.h"
|
#include "ballistica/base/assets/asset.h"
|
||||||
#include "ballistica/base/assets/assets.h"
|
#include "ballistica/base/assets/assets.h"
|
||||||
|
#include "ballistica/base/graphics/graphics.h"
|
||||||
#include "ballistica/base/graphics/graphics_server.h"
|
#include "ballistica/base/graphics/graphics_server.h"
|
||||||
#include "ballistica/base/support/huffman.h"
|
#include "ballistica/base/support/huffman.h"
|
||||||
#include "ballistica/shared/foundation/event_loop.h"
|
#include "ballistica/shared/foundation/event_loop.h"
|
||||||
@ -221,12 +222,18 @@ void AssetsServer::WriteReplayMessages() {
|
|||||||
void AssetsServer::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_base->assets || !g_base->graphics_server
|
|
||||||
|| !g_base->graphics_server
|
// FIXME - we'll need to revisit this when adding support for
|
||||||
->texture_compression_types_are_set() // NOLINT
|
// renderer switches, since this is not especially thread-safe.
|
||||||
|| !g_base->graphics_server->texture_quality_set()) {
|
|
||||||
|
if (!g_base->graphics->has_client_context()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// if (!g_base->assets ||
|
||||||
|
// || !g_base->graphics->texture_compression_types_are_set() // NOLINT
|
||||||
|
// || !g_base->graphics_server->texture_quality_set()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
// Process exactly 1 preload item. Empty out our non-audio list first
|
// Process exactly 1 preload item. Empty out our non-audio list first
|
||||||
// (audio is less likely to cause noticeable hitches if it needs to be loaded
|
// (audio is less likely to cause noticeable hitches if it needs to be loaded
|
||||||
|
|||||||
@ -93,11 +93,14 @@ auto TextureAsset::GetNameFull() const -> std::string {
|
|||||||
void TextureAsset::DoPreload() {
|
void TextureAsset::DoPreload() {
|
||||||
assert(valid_);
|
assert(valid_);
|
||||||
|
|
||||||
assert(g_base->graphics_server
|
// Make sure we're not loading without knowing what texture types we
|
||||||
&& g_base->graphics_server->texture_compression_types_are_set());
|
// support.
|
||||||
|
// assert(g_base->graphics->has_client_context());
|
||||||
|
// assert(g_base->graphics_server
|
||||||
|
// && g_base->graphics_server->texture_compression_types_are_set());
|
||||||
|
|
||||||
// We figure out which LOD should be our base level based on quality.
|
// Figure out which LOD should be our base level based on texture quality.
|
||||||
TextureQuality texture_quality = g_base->graphics_server->texture_quality();
|
auto texture_quality = g_base->graphics->placeholder_texture_quality();
|
||||||
|
|
||||||
// If we're a text-texture.
|
// If we're a text-texture.
|
||||||
if (packer_.Exists()) {
|
if (packer_.Exists()) {
|
||||||
@ -218,12 +221,14 @@ void TextureAsset::DoPreload() {
|
|||||||
&preload_datas_[0].base_level);
|
&preload_datas_[0].base_level);
|
||||||
|
|
||||||
// We should only be loading this if we support etc1 in hardware.
|
// We should only be loading this if we support etc1 in hardware.
|
||||||
assert(g_base->graphics_server->SupportsTextureCompressionType(
|
assert(g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC1));
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC1));
|
||||||
|
|
||||||
// Decompress dxt1/dxt5 ones if we don't natively support S3TC.
|
// Decompress dxt1/dxt5 ones if we don't natively support S3TC.
|
||||||
if (!g_base->graphics_server->SupportsTextureCompressionType(
|
if (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kS3TC)) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kS3TC)) {
|
||||||
if ((preload_datas_[0].formats[preload_datas_[0].base_level]
|
if ((preload_datas_[0].formats[preload_datas_[0].base_level]
|
||||||
== TextureFormat::kDXT5)
|
== TextureFormat::kDXT5)
|
||||||
|| (preload_datas_[0].formats[preload_datas_[0].base_level]
|
|| (preload_datas_[0].formats[preload_datas_[0].base_level]
|
||||||
@ -241,8 +246,9 @@ void TextureAsset::DoPreload() {
|
|||||||
&preload_datas_[0].base_level);
|
&preload_datas_[0].base_level);
|
||||||
|
|
||||||
// Decompress dxt1/dxt5 if we don't natively support it.
|
// Decompress dxt1/dxt5 if we don't natively support it.
|
||||||
if (!g_base->graphics_server->SupportsTextureCompressionType(
|
if (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kS3TC)) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kS3TC)) {
|
||||||
preload_datas_[0].ConvertToUncompressed(this);
|
preload_datas_[0].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
||||||
@ -264,16 +270,18 @@ void TextureAsset::DoPreload() {
|
|||||||
== TextureFormat::kETC2_RGB)
|
== TextureFormat::kETC2_RGB)
|
||||||
|| (preload_datas_[0].formats[preload_datas_[0].base_level]
|
|| (preload_datas_[0].formats[preload_datas_[0].base_level]
|
||||||
== TextureFormat::kETC2_RGBA))
|
== TextureFormat::kETC2_RGBA))
|
||||||
&& (!g_base->graphics_server->SupportsTextureCompressionType(
|
&& (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC2))) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC2))) {
|
||||||
preload_datas_[0].ConvertToUncompressed(this);
|
preload_datas_[0].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress etc1 if we don't natively support it.
|
// Decompress etc1 if we don't natively support it.
|
||||||
if ((preload_datas_[0].formats[preload_datas_[0].base_level]
|
if ((preload_datas_[0].formats[preload_datas_[0].base_level]
|
||||||
== TextureFormat::kETC1)
|
== TextureFormat::kETC1)
|
||||||
&& (!g_base->graphics_server->SupportsTextureCompressionType(
|
&& (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC1))) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC1))) {
|
||||||
preload_datas_[0].ConvertToUncompressed(this);
|
preload_datas_[0].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +295,9 @@ void TextureAsset::DoPreload() {
|
|||||||
&preload_datas_[0].base_level);
|
&preload_datas_[0].base_level);
|
||||||
|
|
||||||
// We should only be loading this if we support pvr in hardware.
|
// We should only be loading this if we support pvr in hardware.
|
||||||
assert(g_base->graphics_server->SupportsTextureCompressionType(
|
assert(
|
||||||
TextureCompressionType::kPVR));
|
g_base->graphics->placeholder_client_context()
|
||||||
|
->SupportsTextureCompressionType(TextureCompressionType::kPVR));
|
||||||
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
||||||
".nop")) {
|
".nop")) {
|
||||||
// Dummy path for headless; nothing to do here.
|
// Dummy path for headless; nothing to do here.
|
||||||
@ -342,12 +351,14 @@ void TextureAsset::DoPreload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We should only be loading this if we support etc1 in hardware.
|
// We should only be loading this if we support etc1 in hardware.
|
||||||
assert(g_base->graphics_server->SupportsTextureCompressionType(
|
assert(g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC1));
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC1));
|
||||||
|
|
||||||
// Decompress dxt1/dxt5 ones if we don't natively support S3TC.
|
// Decompress dxt1/dxt5 ones if we don't natively support S3TC.
|
||||||
if (!g_base->graphics_server->SupportsTextureCompressionType(
|
if (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kS3TC)) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kS3TC)) {
|
||||||
if ((preload_datas_[d].formats[preload_datas_[d].base_level]
|
if ((preload_datas_[d].formats[preload_datas_[d].base_level]
|
||||||
== TextureFormat::kDXT5)
|
== TextureFormat::kDXT5)
|
||||||
|| (preload_datas_[d].formats[preload_datas_[d].base_level]
|
|| (preload_datas_[d].formats[preload_datas_[d].base_level]
|
||||||
@ -365,8 +376,9 @@ void TextureAsset::DoPreload() {
|
|||||||
&preload_datas_[d].base_level);
|
&preload_datas_[d].base_level);
|
||||||
|
|
||||||
// Decompress dxt1/dxt5 if we don't natively support it.
|
// Decompress dxt1/dxt5 if we don't natively support it.
|
||||||
if (!g_base->graphics_server->SupportsTextureCompressionType(
|
if (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kS3TC)) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kS3TC)) {
|
||||||
preload_datas_[d].ConvertToUncompressed(this);
|
preload_datas_[d].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
} else if (!strcmp(file_name_full_.c_str() + file_name_size - 4,
|
||||||
@ -383,16 +395,18 @@ void TextureAsset::DoPreload() {
|
|||||||
== TextureFormat::kETC2_RGB)
|
== TextureFormat::kETC2_RGB)
|
||||||
|| (preload_datas_[d].formats[preload_datas_[d].base_level]
|
|| (preload_datas_[d].formats[preload_datas_[d].base_level]
|
||||||
== TextureFormat::kETC2_RGBA))
|
== TextureFormat::kETC2_RGBA))
|
||||||
&& (!g_base->graphics_server->SupportsTextureCompressionType(
|
&& (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC2))) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC2))) {
|
||||||
preload_datas_[d].ConvertToUncompressed(this);
|
preload_datas_[d].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress etc1 if we don't natively support it.
|
// Decompress etc1 if we don't natively support it.
|
||||||
if ((preload_datas_[d].formats[preload_datas_[d].base_level]
|
if ((preload_datas_[d].formats[preload_datas_[d].base_level]
|
||||||
== TextureFormat::kETC1)
|
== TextureFormat::kETC1)
|
||||||
&& (!g_base->graphics_server->SupportsTextureCompressionType(
|
&& (!g_base->graphics->placeholder_client_context()
|
||||||
TextureCompressionType::kETC1))) {
|
->SupportsTextureCompressionType(
|
||||||
|
TextureCompressionType::kETC1))) {
|
||||||
preload_datas_[d].ConvertToUncompressed(this);
|
preload_datas_[d].ConvertToUncompressed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "ballistica/base/assets/sound_asset.h"
|
#include "ballistica/base/assets/sound_asset.h"
|
||||||
#include "ballistica/base/audio/audio_server.h"
|
#include "ballistica/base/audio/audio_server.h"
|
||||||
#include "ballistica/base/audio/audio_source.h"
|
#include "ballistica/base/audio/audio_source.h"
|
||||||
|
#include "ballistica/base/graphics/graphics.h"
|
||||||
#include "ballistica/base/support/app_config.h"
|
#include "ballistica/base/support/app_config.h"
|
||||||
#include "ballistica/shared/foundation/event_loop.h"
|
#include "ballistica/shared/foundation/event_loop.h"
|
||||||
|
|
||||||
@ -12,6 +13,19 @@ namespace ballistica::base {
|
|||||||
|
|
||||||
Audio::Audio() = default;
|
Audio::Audio() = default;
|
||||||
|
|
||||||
|
auto Audio::UseLowQualityAudio() -> bool {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
// Currently just piggybacking off graphics quality here.
|
||||||
|
if (g_core->HeadlessMode() || g_base->graphics->has_client_context()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// We don't have a frame-def to look at so need to calc this ourself; ugh.
|
||||||
|
auto quality = Graphics::GraphicsQualityFromRequest(
|
||||||
|
g_base->graphics->settings()->graphics_quality,
|
||||||
|
g_base->graphics->client_context()->auto_graphics_quality);
|
||||||
|
return quality < GraphicsQuality::kMedium;
|
||||||
|
}
|
||||||
|
|
||||||
void Audio::Reset() {
|
void Audio::Reset() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
g_base->audio_server->PushResetCall();
|
g_base->audio_server->PushResetCall();
|
||||||
|
|||||||
@ -29,36 +29,41 @@ class Audio {
|
|||||||
virtual void OnScreenSizeChange();
|
virtual void OnScreenSizeChange();
|
||||||
virtual void StepDisplayTime();
|
virtual void StepDisplayTime();
|
||||||
|
|
||||||
|
/// Can be keyed off of to cut corners in audio (leaving sounds out, etc.)
|
||||||
|
/// Currently just piggybacks off graphics quality settings but this logic
|
||||||
|
/// may get fancier in the future.
|
||||||
|
auto UseLowQualityAudio() -> bool;
|
||||||
|
|
||||||
void SetVolumes(float music_volume, float sound_volume);
|
void SetVolumes(float music_volume, float sound_volume);
|
||||||
|
|
||||||
void SetListenerPosition(const Vector3f& p);
|
void SetListenerPosition(const Vector3f& p);
|
||||||
void SetListenerOrientation(const Vector3f& forward, const Vector3f& up);
|
void SetListenerOrientation(const Vector3f& forward, const Vector3f& up);
|
||||||
void SetSoundPitch(float pitch);
|
void SetSoundPitch(float pitch);
|
||||||
|
|
||||||
// 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
|
||||||
// 0,0,0, etc.).
|
/// 0,0,0, etc.).
|
||||||
// Send the source any immediate commands and then unlock it.
|
/// Send the source any immediate commands and then unlock it.
|
||||||
// For later modifications, re-retrieve the sound with GetPlayingSound()
|
/// For later modifications, re-retrieve the sound with GetPlayingSound()
|
||||||
auto SourceBeginNew() -> AudioSource*;
|
auto SourceBeginNew() -> AudioSource*;
|
||||||
|
|
||||||
// If a sound play id is playing, locks and returns its sound source.
|
/// If a sound play id is playing, locks and returns its sound source.
|
||||||
// on success, you must unlock the source once done with it.
|
/// on success, you must unlock the source once done with it.
|
||||||
auto SourceBeginExisting(uint32_t play_id, int debug_id) -> AudioSource*;
|
auto SourceBeginExisting(uint32_t play_id, int debug_id) -> AudioSource*;
|
||||||
|
|
||||||
// Return true if the sound id is currently valid. This is not guaranteed
|
/// Return true if the sound id is currently valid. This is not guaranteed
|
||||||
// to be super accurate, but can be used to determine if a sound is still
|
/// to be super accurate, but can be used to determine if a sound is still
|
||||||
// playing.
|
/// playing.
|
||||||
auto IsSoundPlaying(uint32_t play_id) -> bool;
|
auto IsSoundPlaying(uint32_t play_id) -> bool;
|
||||||
|
|
||||||
// Simple one-shot play functions.
|
/// Simple one-shot play functions.
|
||||||
auto PlaySound(SoundAsset* s, float volume = 1.0f) -> std::optional<uint32_t>;
|
auto PlaySound(SoundAsset* s, float volume = 1.0f) -> std::optional<uint32_t>;
|
||||||
auto PlaySoundAtPosition(SoundAsset* sound, float volume, float x, float y,
|
auto PlaySoundAtPosition(SoundAsset* sound, float volume, float x, float y,
|
||||||
float z) -> std::optional<uint32_t>;
|
float z) -> std::optional<uint32_t>;
|
||||||
|
|
||||||
// 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
|
||||||
// functions use this under the hood. (PlaySound, PlaySoundAtPosition).
|
/// functions use this under the hood. (PlaySound, PlaySoundAtPosition).
|
||||||
auto ShouldPlay(SoundAsset* s) -> bool;
|
auto ShouldPlay(SoundAsset* s) -> bool;
|
||||||
|
|
||||||
// Hmm; shouldn't these be accessed through the Source class?
|
// Hmm; shouldn't these be accessed through the Source class?
|
||||||
@ -73,15 +78,15 @@ class Audio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 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_;
|
||||||
|
|
||||||
// List of sources that are ready to use.
|
/// List of sources that are ready to use.
|
||||||
// This is kept filled by the audio thread
|
/// This is kept filled by the audio thread
|
||||||
// and used by the client.
|
/// and used by the client.
|
||||||
std::vector<AudioSource*> available_sources_;
|
std::vector<AudioSource*> available_sources_;
|
||||||
|
|
||||||
// This must be locked whenever accessing the availableSources list.
|
/// This must be locked whenever accessing the availableSources list.
|
||||||
std::mutex available_sources_mutex_;
|
std::mutex available_sources_mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -420,6 +420,10 @@ auto BaseFeatureSet::IsUnmodifiedBlessedBuild() -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto BaseFeatureSet::InMainThread() const -> bool {
|
||||||
|
return g_core->InMainThread();
|
||||||
|
}
|
||||||
|
|
||||||
auto BaseFeatureSet::InAssetsThread() const -> bool {
|
auto BaseFeatureSet::InAssetsThread() const -> bool {
|
||||||
if (auto* loop = assets_server->event_loop()) {
|
if (auto* loop = assets_server->event_loop()) {
|
||||||
return loop->ThreadIsCurrent();
|
return loop->ThreadIsCurrent();
|
||||||
|
|||||||
@ -59,6 +59,8 @@ class DataAsset;
|
|||||||
class FrameDef;
|
class FrameDef;
|
||||||
class Graphics;
|
class Graphics;
|
||||||
class GraphicsServer;
|
class GraphicsServer;
|
||||||
|
struct GraphicsSettings;
|
||||||
|
struct GraphicsClientContext;
|
||||||
class Huffman;
|
class Huffman;
|
||||||
class ImageMesh;
|
class ImageMesh;
|
||||||
class Input;
|
class Input;
|
||||||
@ -662,6 +664,7 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
|
|||||||
/// allowing certain functionality before this time.
|
/// allowing certain functionality before this time.
|
||||||
auto IsBaseCompletelyImported() -> bool;
|
auto IsBaseCompletelyImported() -> bool;
|
||||||
|
|
||||||
|
auto InMainThread() const -> bool;
|
||||||
auto InAssetsThread() const -> bool override;
|
auto InAssetsThread() const -> bool override;
|
||||||
auto InLogicThread() const -> bool override;
|
auto InLogicThread() const -> bool override;
|
||||||
auto InAudioThread() const -> bool override;
|
auto InAudioThread() const -> bool override;
|
||||||
|
|||||||
@ -39,10 +39,15 @@ void BGDynamics::Emit(const BGDynamicsEmission& e) {
|
|||||||
void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) {
|
void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
// Don't actually start doing anything until there's a
|
||||||
|
// client-graphics-context. We need this to calculate qualities/etc.
|
||||||
|
if (!g_base->graphics->has_client_context()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The BG dynamics thread just processes steps as fast as it can;
|
// The BG dynamics thread just processes steps as fast as it can;
|
||||||
// we need to throttle what we send or tell it to cut back if its behind
|
// we need to throttle what we send or tell it to cut back if its behind
|
||||||
int step_count = g_base->bg_dynamics_server->step_count();
|
int step_count = g_base->bg_dynamics_server->step_count();
|
||||||
// printf("STEP COUNT %d\n", step_count);
|
|
||||||
|
|
||||||
// If we're really getting behind, start pruning stuff.
|
// If we're really getting behind, start pruning stuff.
|
||||||
if (step_count > 3) {
|
if (step_count > 3) {
|
||||||
@ -62,6 +67,9 @@ void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) {
|
|||||||
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes care
|
// Pass a newly allocated raw pointer to the bg-dynamics thread; it takes care
|
||||||
// of disposing it when done.
|
// of disposing it when done.
|
||||||
auto d = Object::NewDeferred<BGDynamicsServer::StepData>();
|
auto d = Object::NewDeferred<BGDynamicsServer::StepData>();
|
||||||
|
d->graphics_quality = Graphics::GraphicsQualityFromRequest(
|
||||||
|
g_base->graphics->settings()->graphics_quality,
|
||||||
|
g_base->graphics->client_context()->auto_graphics_quality);
|
||||||
d->step_millisecs = step_millisecs;
|
d->step_millisecs = step_millisecs;
|
||||||
d->cam_pos = cam_pos;
|
d->cam_pos = cam_pos;
|
||||||
|
|
||||||
@ -174,7 +182,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
|
|||||||
|
|
||||||
// In high-quality, we draw in the overlay pass so that we don't get wiped
|
// In high-quality, we draw in the overlay pass so that we don't get wiped
|
||||||
// out by depth-of-field.
|
// out by depth-of-field.
|
||||||
bool draw_in_overlay = (frame_def->quality() >= GraphicsQuality::kHigh);
|
bool draw_in_overlay = frame_def->quality() >= GraphicsQuality::kHigh;
|
||||||
SpriteComponent c(draw_in_overlay ? frame_def->overlay_3d_pass()
|
SpriteComponent c(draw_in_overlay ? frame_def->overlay_3d_pass()
|
||||||
: frame_def->beauty_pass());
|
: frame_def->beauty_pass());
|
||||||
c.SetCameraAligned(true);
|
c.SetCameraAligned(true);
|
||||||
@ -232,7 +240,7 @@ void BGDynamics::Draw(FrameDef* frame_def) {
|
|||||||
tendrils_mesh_->SetIndexData(ds->tendril_indices);
|
tendrils_mesh_->SetIndexData(ds->tendril_indices);
|
||||||
tendrils_mesh_->SetData(
|
tendrils_mesh_->SetData(
|
||||||
Object::Ref<MeshBuffer<VertexSmokeFull>>(ds->tendril_vertices));
|
Object::Ref<MeshBuffer<VertexSmokeFull>>(ds->tendril_vertices));
|
||||||
bool draw_in_overlay = (frame_def->quality() >= GraphicsQuality::kHigh);
|
bool draw_in_overlay = frame_def->quality() >= GraphicsQuality::kHigh;
|
||||||
SmokeComponent c(draw_in_overlay ? frame_def->overlay_3d_pass()
|
SmokeComponent c(draw_in_overlay ? frame_def->overlay_3d_pass()
|
||||||
: frame_def->beauty_pass());
|
: frame_def->beauty_pass());
|
||||||
c.SetOverlay(draw_in_overlay);
|
c.SetOverlay(draw_in_overlay);
|
||||||
|
|||||||
@ -2282,7 +2282,8 @@ void BGDynamicsServer::Step(StepData* step_data) {
|
|||||||
auto ref(Object::CompleteDeferred(step_data));
|
auto ref(Object::CompleteDeferred(step_data));
|
||||||
|
|
||||||
// Keep our quality in sync with the graphics thread's.
|
// Keep our quality in sync with the graphics thread's.
|
||||||
graphics_quality_ = g_base->graphics_server->graphics_quality();
|
graphics_quality_ = step_data->graphics_quality;
|
||||||
|
assert(graphics_quality_ != GraphicsQuality::kUnset);
|
||||||
|
|
||||||
cam_pos_ = step_data->cam_pos;
|
cam_pos_ = step_data->cam_pos;
|
||||||
|
|
||||||
|
|||||||
@ -73,6 +73,7 @@ class BGDynamicsServer {
|
|||||||
auto GetDefaultOwnerThread() const -> EventLoopID override {
|
auto GetDefaultOwnerThread() const -> EventLoopID override {
|
||||||
return EventLoopID::kBGDynamics;
|
return EventLoopID::kBGDynamics;
|
||||||
}
|
}
|
||||||
|
GraphicsQuality graphics_quality{};
|
||||||
int step_millisecs{};
|
int step_millisecs{};
|
||||||
Vector3f cam_pos{0.0f, 0.0f, 0.0f};
|
Vector3f cam_pos{0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
|
|||||||
@ -238,10 +238,10 @@ class RendererGL::ProgramGL {
|
|||||||
|
|
||||||
// Update matrices as necessary.
|
// Update matrices as necessary.
|
||||||
|
|
||||||
uint32_t mvpState =
|
int mvp_state =
|
||||||
g_base->graphics_server->GetModelViewProjectionMatrixState();
|
g_base->graphics_server->GetModelViewProjectionMatrixState();
|
||||||
if (mvpState != mvp_state_) {
|
if (mvp_state != mvp_state_) {
|
||||||
mvp_state_ = mvpState;
|
mvp_state_ = mvp_state;
|
||||||
glUniformMatrix4fv(
|
glUniformMatrix4fv(
|
||||||
mvp_uniform_, 1, 0,
|
mvp_uniform_, 1, 0,
|
||||||
g_base->graphics_server->GetModelViewProjectionMatrix().m);
|
g_base->graphics_server->GetModelViewProjectionMatrix().m);
|
||||||
@ -251,7 +251,7 @@ class RendererGL::ProgramGL {
|
|||||||
if (pflags_ & PFLAG_USES_MODEL_WORLD_MATRIX) {
|
if (pflags_ & PFLAG_USES_MODEL_WORLD_MATRIX) {
|
||||||
// With world space points this would be identity; don't waste time.
|
// With world space points this would be identity; don't waste time.
|
||||||
assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS));
|
assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS));
|
||||||
uint32_t state = g_base->graphics_server->GetModelWorldMatrixState();
|
int state = g_base->graphics_server->GetModelWorldMatrixState();
|
||||||
if (state != model_world_matrix_state_) {
|
if (state != model_world_matrix_state_) {
|
||||||
model_world_matrix_state_ = state;
|
model_world_matrix_state_ = state;
|
||||||
glUniformMatrix4fv(model_world_matrix_uniform_, 1, 0,
|
glUniformMatrix4fv(model_world_matrix_uniform_, 1, 0,
|
||||||
@ -264,8 +264,7 @@ class RendererGL::ProgramGL {
|
|||||||
// With world space points this would be identity; don't waste time.
|
// With world space points this would be identity; don't waste time.
|
||||||
assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS));
|
assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS));
|
||||||
// There's no state for just modelview but this works.
|
// There's no state for just modelview but this works.
|
||||||
uint32_t state =
|
int state = g_base->graphics_server->GetModelViewProjectionMatrixState();
|
||||||
g_base->graphics_server->GetModelViewProjectionMatrixState();
|
|
||||||
if (state != model_view_matrix_state_) {
|
if (state != model_view_matrix_state_) {
|
||||||
model_view_matrix_state_ = state;
|
model_view_matrix_state_ = state;
|
||||||
glUniformMatrix4fv(model_view_matrix_uniform_, 1, 0,
|
glUniformMatrix4fv(model_view_matrix_uniform_, 1, 0,
|
||||||
@ -275,7 +274,7 @@ class RendererGL::ProgramGL {
|
|||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
|
|
||||||
if (pflags_ & PFLAG_USES_CAM_POS) {
|
if (pflags_ & PFLAG_USES_CAM_POS) {
|
||||||
uint32_t state = g_base->graphics_server->cam_pos_state();
|
int state = g_base->graphics_server->cam_pos_state();
|
||||||
if (state != cam_pos_state_) {
|
if (state != cam_pos_state_) {
|
||||||
cam_pos_state_ = state;
|
cam_pos_state_ = state;
|
||||||
const Vector3f& p(g_base->graphics_server->cam_pos());
|
const Vector3f& p(g_base->graphics_server->cam_pos());
|
||||||
@ -285,7 +284,7 @@ class RendererGL::ProgramGL {
|
|||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
|
|
||||||
if (pflags_ & PFLAG_USES_CAM_ORIENT_MATRIX) {
|
if (pflags_ & PFLAG_USES_CAM_ORIENT_MATRIX) {
|
||||||
uint32_t state = g_base->graphics_server->GetCamOrientMatrixState();
|
int state = g_base->graphics_server->GetCamOrientMatrixState();
|
||||||
if (state != cam_orient_matrix_state_) {
|
if (state != cam_orient_matrix_state_) {
|
||||||
cam_orient_matrix_state_ = state;
|
cam_orient_matrix_state_ = state;
|
||||||
glUniformMatrix4fv(cam_orient_matrix_uniform_, 1, 0,
|
glUniformMatrix4fv(cam_orient_matrix_uniform_, 1, 0,
|
||||||
@ -295,7 +294,7 @@ class RendererGL::ProgramGL {
|
|||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
|
|
||||||
if (pflags_ & PFLAG_USES_SHADOW_PROJECTION_MATRIX) {
|
if (pflags_ & PFLAG_USES_SHADOW_PROJECTION_MATRIX) {
|
||||||
uint32_t state =
|
int state =
|
||||||
g_base->graphics_server->light_shadow_projection_matrix_state();
|
g_base->graphics_server->light_shadow_projection_matrix_state();
|
||||||
if (state != light_shadow_projection_matrix_state_) {
|
if (state != light_shadow_projection_matrix_state_) {
|
||||||
light_shadow_projection_matrix_state_ = state;
|
light_shadow_projection_matrix_state_ = state;
|
||||||
@ -336,19 +335,19 @@ class RendererGL::ProgramGL {
|
|||||||
Object::Ref<VertexShaderGL> vertex_shader_;
|
Object::Ref<VertexShaderGL> vertex_shader_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
GLuint program_{};
|
GLuint program_{};
|
||||||
int pflags_{};
|
|
||||||
uint32_t mvp_state_{};
|
|
||||||
GLint mvp_uniform_{};
|
GLint mvp_uniform_{};
|
||||||
GLint model_world_matrix_uniform_{};
|
GLint model_world_matrix_uniform_{};
|
||||||
GLint model_view_matrix_uniform_{};
|
GLint model_view_matrix_uniform_{};
|
||||||
GLint light_shadow_projection_matrix_uniform_{};
|
GLint light_shadow_projection_matrix_uniform_{};
|
||||||
uint32_t light_shadow_projection_matrix_state_{};
|
|
||||||
uint32_t model_world_matrix_state_{};
|
|
||||||
uint32_t model_view_matrix_state_{};
|
|
||||||
GLint cam_pos_uniform_{};
|
GLint cam_pos_uniform_{};
|
||||||
uint32_t cam_pos_state_{};
|
|
||||||
GLint cam_orient_matrix_uniform_{};
|
GLint cam_orient_matrix_uniform_{};
|
||||||
GLuint cam_orient_matrix_state_{};
|
int cam_orient_matrix_state_{};
|
||||||
|
int light_shadow_projection_matrix_state_{};
|
||||||
|
int pflags_{};
|
||||||
|
int mvp_state_{};
|
||||||
|
int cam_pos_state_{};
|
||||||
|
int model_world_matrix_state_{};
|
||||||
|
int model_view_matrix_state_{};
|
||||||
BA_DISALLOW_CLASS_COPIES(ProgramGL);
|
BA_DISALLOW_CLASS_COPIES(ProgramGL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -366,7 +366,7 @@ void RendererGL::CheckGLCapabilities_() {
|
|||||||
|
|
||||||
// Both GL 3 and GL ES 3.0 support depth textures (and thus our high
|
// Both GL 3 and GL ES 3.0 support depth textures (and thus our high
|
||||||
// quality mode) as a core feature.
|
// quality mode) as a core feature.
|
||||||
g_base->graphics->SetSupportsHighQualityGraphics(true);
|
// g_base->graphics->SetSupportsHighQualityGraphics(true);
|
||||||
|
|
||||||
// Store the tex-compression type we support.
|
// Store the tex-compression type we support.
|
||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
@ -2598,7 +2598,8 @@ void RendererGL::RetainShader_(ProgramGL* p) { shaders_.emplace_back(p); }
|
|||||||
void RendererGL::Load() {
|
void RendererGL::Load() {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
assert(!data_loaded_);
|
assert(!data_loaded_);
|
||||||
assert(g_base->graphics_server->graphics_quality_set());
|
assert(g_base->graphics_server->graphics_quality()
|
||||||
|
!= GraphicsQuality::kUnset);
|
||||||
BA_DEBUG_CHECK_GL_ERROR;
|
BA_DEBUG_CHECK_GL_ERROR;
|
||||||
if (!got_screen_framebuffer_) {
|
if (!got_screen_framebuffer_) {
|
||||||
got_screen_framebuffer_ = true;
|
got_screen_framebuffer_ = true;
|
||||||
|
|||||||
@ -115,9 +115,14 @@ void Graphics::OnAppShutdownComplete() { assert(g_base->InLogicThread()); }
|
|||||||
void Graphics::DoApplyAppConfig() {
|
void Graphics::DoApplyAppConfig() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
// Any time we load the config we ship a new graphics-settings to
|
||||||
|
// the graphics server since something likely changed.
|
||||||
|
graphics_settings_dirty_ = true;
|
||||||
|
|
||||||
show_fps_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowFPS);
|
show_fps_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowFPS);
|
||||||
show_ping_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowPing);
|
show_ping_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowPing);
|
||||||
tv_border_ = g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder);
|
// tv_border_ =
|
||||||
|
// g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder);
|
||||||
|
|
||||||
bool disable_camera_shake =
|
bool disable_camera_shake =
|
||||||
g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraShake);
|
g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraShake);
|
||||||
@ -126,6 +131,52 @@ void Graphics::DoApplyAppConfig() {
|
|||||||
bool disable_camera_gyro =
|
bool disable_camera_gyro =
|
||||||
g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraGyro);
|
g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraGyro);
|
||||||
set_camera_gyro_explicitly_disabled(disable_camera_gyro);
|
set_camera_gyro_explicitly_disabled(disable_camera_gyro);
|
||||||
|
|
||||||
|
applied_app_config_ = true;
|
||||||
|
|
||||||
|
// At this point we may want to send initial graphics settings to the
|
||||||
|
// graphics server if we haven't.
|
||||||
|
UpdateInitialGraphicsSettingsSend_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::UpdateInitialGraphicsSettingsSend_() {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
if (sent_initial_graphics_settings_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to send an initial graphics-settings to the server to kick
|
||||||
|
// things off, but we need a few things to be in place first.
|
||||||
|
auto app_config_ready = applied_app_config_;
|
||||||
|
// At some point we may want to wait to know our actual screen res before
|
||||||
|
// sending. This won't apply everywhere though since on some platforms the
|
||||||
|
// screen doesn't exist until we send this.
|
||||||
|
auto screen_resolution_ready = true;
|
||||||
|
|
||||||
|
if (app_config_ready && screen_resolution_ready) {
|
||||||
|
// Update/grab the current settings snapshot.
|
||||||
|
auto* settings = GetGraphicsSettingsSnapshot();
|
||||||
|
|
||||||
|
// We need to explicitly push settings to the graphics server to kick
|
||||||
|
// things off. We need to keep this settings instance alive until
|
||||||
|
// handled by the graphics context (which might be in another thread
|
||||||
|
// where we're not allowed to muck with settings' refs from). So let's
|
||||||
|
// explicitly increment its refcount here in the logic thread now and
|
||||||
|
// then push a call back here to decrement it when we're done.
|
||||||
|
settings->ObjectIncrementStrongRefCount();
|
||||||
|
// auto* s = settings_.Get();
|
||||||
|
g_base->app_adapter->PushGraphicsContextCall([settings] {
|
||||||
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
g_base->graphics_server->ApplySettings(settings->Get());
|
||||||
|
g_base->logic->event_loop()->PushCall([settings] {
|
||||||
|
// Release our strong ref back here in the logic thread.
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
settings->ObjectDecrementStrongRefCount();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
sent_initial_graphics_settings_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::StepDisplayTime() { assert(g_base->InLogicThread()); }
|
void Graphics::StepDisplayTime() { assert(g_base->InLogicThread()); }
|
||||||
@ -976,6 +1027,20 @@ auto Graphics::GetEmptyFrameDef() -> FrameDef* {
|
|||||||
return frame_def;
|
return frame_def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Graphics::GetGraphicsSettingsSnapshot() -> Snapshot<GraphicsSettings>* {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
// If need be, ask the app-adapter to build us a new settings instance.
|
||||||
|
if (graphics_settings_dirty_) {
|
||||||
|
auto* new_settings = g_base->app_adapter->GetGraphicsSettings();
|
||||||
|
new_settings->index = next_settings_index_++;
|
||||||
|
settings_snapshot_ = Object::New<Snapshot<GraphicsSettings>>(new_settings);
|
||||||
|
graphics_settings_dirty_ = false;
|
||||||
|
}
|
||||||
|
assert(settings_snapshot_.Exists());
|
||||||
|
return settings_snapshot_.Get();
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::ClearFrameDefDeleteList() {
|
void Graphics::ClearFrameDefDeleteList() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
std::scoped_lock lock(frame_def_delete_list_mutex_);
|
std::scoped_lock lock(frame_def_delete_list_mutex_);
|
||||||
@ -1120,6 +1185,8 @@ void Graphics::DrawDevUI(FrameDef* frame_def) {
|
|||||||
|
|
||||||
void Graphics::BuildAndPushFrameDef() {
|
void Graphics::BuildAndPushFrameDef() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete());
|
||||||
assert(camera_.Exists());
|
assert(camera_.Exists());
|
||||||
assert(!g_core->HeadlessMode());
|
assert(!g_core->HeadlessMode());
|
||||||
|
|
||||||
@ -1128,10 +1195,6 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
assert(!building_frame_def_);
|
assert(!building_frame_def_);
|
||||||
building_frame_def_ = true;
|
building_frame_def_ = true;
|
||||||
|
|
||||||
// We should not be building/pushing any frames until the native
|
|
||||||
// layer is fully bootstrapped.
|
|
||||||
BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete());
|
|
||||||
|
|
||||||
microsecs_t app_time_microsecs = g_core->GetAppTimeMicrosecs();
|
microsecs_t app_time_microsecs = g_core->GetAppTimeMicrosecs();
|
||||||
|
|
||||||
// Store how much time this frame_def represents.
|
// Store how much time this frame_def represents.
|
||||||
@ -1187,13 +1250,6 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
internal_components_inited_ = true;
|
internal_components_inited_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If graphics quality has changed since our last draw, inform anyone who
|
|
||||||
// wants to know.
|
|
||||||
if (last_frame_def_graphics_quality_ != frame_def->quality()) {
|
|
||||||
last_frame_def_graphics_quality_ = frame_def->quality();
|
|
||||||
g_base->app_mode()->GraphicsQualityChanged(frame_def->quality());
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplyCamera(frame_def);
|
ApplyCamera(frame_def);
|
||||||
|
|
||||||
if (progress_bar_) {
|
if (progress_bar_) {
|
||||||
@ -1254,7 +1310,7 @@ void Graphics::BuildAndPushFrameDef() {
|
|||||||
RunCleanFrameCommands();
|
RunCleanFrameCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_def->Finalize();
|
frame_def->Complete();
|
||||||
|
|
||||||
// Include all mesh-data loads and unloads that have accumulated up to
|
// Include all mesh-data loads and unloads that have accumulated up to
|
||||||
// this point the graphics thread will have to handle these before
|
// this point the graphics thread will have to handle these before
|
||||||
@ -1555,11 +1611,6 @@ void Graphics::DrawBlotches(FrameDef* frame_def) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::SetSupportsHighQualityGraphics(bool s) {
|
|
||||||
supports_high_quality_graphics_ = s;
|
|
||||||
has_supports_high_quality_graphics_value_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::ClearScreenMessageTranslations() {
|
void Graphics::ClearScreenMessageTranslations() {
|
||||||
assert(g_base && g_base->InLogicThread());
|
assert(g_base && g_base->InLogicThread());
|
||||||
for (auto&& i : screen_messages_) {
|
for (auto&& i : screen_messages_) {
|
||||||
@ -1922,20 +1973,55 @@ auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& {
|
|||||||
|
|
||||||
void Graphics::OnScreenSizeChange() {}
|
void Graphics::OnScreenSizeChange() {}
|
||||||
|
|
||||||
void Graphics::SetScreenSize(float virtual_width, float virtual_height,
|
void Graphics::CalcVirtualRes_(float* x, float* y) {
|
||||||
float pixel_width, float pixel_height) {
|
float x_in = *x;
|
||||||
|
float y_in = *y;
|
||||||
|
if (*x / *y > static_cast<float>(kBaseVirtualResX)
|
||||||
|
/ static_cast<float>(kBaseVirtualResY)) {
|
||||||
|
*y = kBaseVirtualResY;
|
||||||
|
*x = *y * (x_in / y_in);
|
||||||
|
} else {
|
||||||
|
*x = kBaseVirtualResX;
|
||||||
|
*y = *x * (y_in / x_in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::SetScreenResolution(float x, float y) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
res_x_virtual_ = virtual_width;
|
|
||||||
res_y_virtual_ = virtual_height;
|
// Ignore redundant sets.
|
||||||
res_x_ = pixel_width;
|
if (res_x_ == x && res_y_ == y) {
|
||||||
res_y_ = pixel_height;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll need to ship a new settings to the server with this change.
|
||||||
|
graphics_settings_dirty_ = true;
|
||||||
|
|
||||||
|
res_x_ = x;
|
||||||
|
res_y_ = y;
|
||||||
|
|
||||||
|
// Calc virtual res. In vr mode our virtual res is independent of our
|
||||||
|
// screen size (since it gets drawn to an overlay).
|
||||||
|
if (g_core->IsVRMode()) {
|
||||||
|
res_x_virtual_ = kBaseVirtualResX;
|
||||||
|
res_y_virtual_ = kBaseVirtualResY;
|
||||||
|
} else {
|
||||||
|
res_x_virtual_ = res_x_;
|
||||||
|
res_y_virtual_ = res_y_;
|
||||||
|
CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_);
|
||||||
|
}
|
||||||
|
|
||||||
// Need to rebuild internal components (some are sized to the screen).
|
// Need to rebuild internal components (some are sized to the screen).
|
||||||
internal_components_inited_ = false;
|
internal_components_inited_ = false;
|
||||||
|
|
||||||
// This will inform all applicable logic thread subsystems.
|
// Inform all our logic thread buddies of this change.
|
||||||
g_base->logic->OnScreenSizeChange(virtual_width, virtual_height, pixel_width,
|
g_base->logic->OnScreenSizeChange(res_x_virtual_, res_y_virtual_, res_x_,
|
||||||
pixel_height);
|
res_y_);
|
||||||
|
|
||||||
|
// This may trigger us sending initial graphics settings to the
|
||||||
|
// graphics-server to kick off drawing.
|
||||||
|
got_screen_resolution_ = true;
|
||||||
|
UpdateInitialGraphicsSettingsSend_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::ScreenMessageEntry::UpdateTranslation() {
|
void Graphics::ScreenMessageEntry::UpdateTranslation() {
|
||||||
@ -2030,4 +2116,61 @@ void Graphics::LanguageChanged() {
|
|||||||
ClearScreenMessageTranslations();
|
ClearScreenMessageTranslations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request,
|
||||||
|
GraphicsQuality auto_val)
|
||||||
|
-> GraphicsQuality {
|
||||||
|
switch (request) {
|
||||||
|
case GraphicsQualityRequest::kLow:
|
||||||
|
return GraphicsQuality::kLow;
|
||||||
|
case GraphicsQualityRequest::kMedium:
|
||||||
|
return GraphicsQuality::kMedium;
|
||||||
|
case GraphicsQualityRequest::kHigh:
|
||||||
|
return GraphicsQuality::kHigh;
|
||||||
|
case GraphicsQualityRequest::kHigher:
|
||||||
|
return GraphicsQuality::kHigher;
|
||||||
|
case GraphicsQualityRequest::kAuto:
|
||||||
|
return auto_val;
|
||||||
|
default:
|
||||||
|
Log(LogLevel::kError, "Unhandled GraphicsQualityRequest value: "
|
||||||
|
+ std::to_string(static_cast<int>(request)));
|
||||||
|
return GraphicsQuality::kLow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto Graphics::TextureQualityFromRequest(TextureQualityRequest request,
|
||||||
|
TextureQuality auto_val)
|
||||||
|
-> TextureQuality {
|
||||||
|
switch (request) {
|
||||||
|
case TextureQualityRequest::kLow:
|
||||||
|
return TextureQuality::kLow;
|
||||||
|
case TextureQualityRequest::kMedium:
|
||||||
|
return TextureQuality::kMedium;
|
||||||
|
case TextureQualityRequest::kHigh:
|
||||||
|
return TextureQuality::kHigh;
|
||||||
|
case TextureQualityRequest::kAuto:
|
||||||
|
return auto_val;
|
||||||
|
default:
|
||||||
|
Log(LogLevel::kError, "Unhandled TextureQualityRequest value: "
|
||||||
|
+ std::to_string(static_cast<int>(request)));
|
||||||
|
return TextureQuality::kLow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::set_client_context(Snapshot<GraphicsClientContext>* context) {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
// Currently we only expect this to be set once. That will change
|
||||||
|
// once we support renderer swapping/etc.
|
||||||
|
assert(!g_base->logic->graphics_ready());
|
||||||
|
assert(!client_context_snapshot_.Exists());
|
||||||
|
client_context_snapshot_ = context;
|
||||||
|
|
||||||
|
// Update our static placeholder value (we don't want to calc it dynamically
|
||||||
|
// since it can be accessed from other threads).
|
||||||
|
texture_quality_placeholder_ = TextureQualityFromRequest(
|
||||||
|
settings()->texture_quality, client_context()->auto_texture_quality);
|
||||||
|
|
||||||
|
// Let the logic system know its free to proceed beyond bootstrapping.
|
||||||
|
g_base->logic->OnGraphicsReady();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|||||||
@ -6,13 +6,15 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ballistica/base/base.h"
|
#include "ballistica/base/base.h"
|
||||||
|
#include "ballistica/base/graphics/support/graphics_client_context.h"
|
||||||
|
#include "ballistica/base/graphics/support/graphics_settings.h"
|
||||||
#include "ballistica/shared/foundation/object.h"
|
#include "ballistica/shared/foundation/object.h"
|
||||||
#include "ballistica/shared/foundation/types.h"
|
#include "ballistica/shared/foundation/types.h"
|
||||||
|
#include "ballistica/shared/generic/snapshot.h"
|
||||||
#include "ballistica/shared/math/matrix44f.h"
|
#include "ballistica/shared/math/matrix44f.h"
|
||||||
#include "ballistica/shared/math/rect.h"
|
#include "ballistica/shared/math/rect.h"
|
||||||
#include "ballistica/shared/math/vector2f.h"
|
#include "ballistica/shared/math/vector2f.h"
|
||||||
@ -62,10 +64,10 @@ class Graphics {
|
|||||||
void OnScreenSizeChange();
|
void OnScreenSizeChange();
|
||||||
void DoApplyAppConfig();
|
void DoApplyAppConfig();
|
||||||
|
|
||||||
/// Called by the graphics server to keep us up to date in the logic
|
/// Should be called by the app-adapter to keep the engine informed
|
||||||
/// thread. Dispatches the news to all logic subsystems that care.
|
/// on the drawable area it has to work with (in pixels).
|
||||||
void SetScreenSize(float virtual_width, float virtual_height,
|
void SetScreenResolution(float x, float y);
|
||||||
float physical_width, float physical_height);
|
|
||||||
void StepDisplayTime();
|
void StepDisplayTime();
|
||||||
|
|
||||||
auto TextureQualityFromAppConfig() -> TextureQualityRequest;
|
auto TextureQualityFromAppConfig() -> TextureQualityRequest;
|
||||||
@ -97,13 +99,25 @@ class Graphics {
|
|||||||
// Called when the GraphicsServer has sent us a frame-def for deletion.
|
// Called when the GraphicsServer has sent us a frame-def for deletion.
|
||||||
void ReturnCompletedFrameDef(FrameDef* frame_def);
|
void ReturnCompletedFrameDef(FrameDef* frame_def);
|
||||||
|
|
||||||
auto screen_pixel_width() const { return res_x_; }
|
auto screen_pixel_width() const {
|
||||||
auto screen_pixel_height() const { return res_y_; }
|
assert(g_base->InLogicThread());
|
||||||
|
return res_x_;
|
||||||
|
}
|
||||||
|
auto screen_pixel_height() const {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
return res_y_;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the size of the virtual screen. This value should always
|
// Return the current size of the virtual screen. This value should always
|
||||||
// be used for interface positioning, etc.
|
// be used for interface positioning, etc.
|
||||||
auto screen_virtual_width() const { return res_x_virtual_; }
|
auto screen_virtual_width() const {
|
||||||
auto screen_virtual_height() const { return res_y_virtual_; }
|
assert(g_base->InLogicThread());
|
||||||
|
return res_x_virtual_;
|
||||||
|
}
|
||||||
|
auto screen_virtual_height() const {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
return res_y_virtual_;
|
||||||
|
}
|
||||||
|
|
||||||
void ClearScreenMessageTranslations();
|
void ClearScreenMessageTranslations();
|
||||||
|
|
||||||
@ -226,10 +240,10 @@ class Graphics {
|
|||||||
float upper_top);
|
float upper_top);
|
||||||
void ReleaseFadeEndCommand();
|
void ReleaseFadeEndCommand();
|
||||||
|
|
||||||
auto tv_border() const {
|
// auto tv_border() const {
|
||||||
assert(g_base->InLogicThread());
|
// assert(g_base->InLogicThread());
|
||||||
return tv_border_;
|
// return tv_border_;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Nodes that draw flat stuff into the overlay pass should query this z value
|
// Nodes that draw flat stuff into the overlay pass should query this z value
|
||||||
// for where to draw in z.
|
// for where to draw in z.
|
||||||
@ -270,17 +284,6 @@ class Graphics {
|
|||||||
return y * (res_y_virtual_ / res_y_);
|
return y * (res_y_virtual_ / res_y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This should probably move to Renderer or AppAdapter once we
|
|
||||||
// support switching renderers.
|
|
||||||
auto supports_high_quality_graphics() const {
|
|
||||||
assert(has_supports_high_quality_graphics_value_);
|
|
||||||
return supports_high_quality_graphics_;
|
|
||||||
}
|
|
||||||
void SetSupportsHighQualityGraphics(bool s);
|
|
||||||
auto has_supports_high_quality_graphics_value() const {
|
|
||||||
return has_supports_high_quality_graphics_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_internal_components_inited(bool val) {
|
void set_internal_components_inited(bool val) {
|
||||||
internal_components_inited_ = val;
|
internal_components_inited_ = val;
|
||||||
}
|
}
|
||||||
@ -322,19 +325,65 @@ class Graphics {
|
|||||||
camera_gyro_explicitly_disabled_ = disabled;
|
camera_gyro_explicitly_disabled_ = disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* settings() const {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
assert(settings_snapshot_.Exists());
|
||||||
|
return settings_snapshot_.Get()->Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetGraphicsSettingsSnapshot() -> Snapshot<GraphicsSettings>*;
|
||||||
|
|
||||||
|
/// Called by the graphics-server when a new client context is ready.
|
||||||
|
void set_client_context(Snapshot<GraphicsClientContext>* context);
|
||||||
|
|
||||||
|
auto has_client_context() -> bool {
|
||||||
|
return client_context_snapshot_.Exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto client_context() const -> const GraphicsClientContext* {
|
||||||
|
assert(g_base->InLogicThread());
|
||||||
|
assert(client_context_snapshot_.Exists());
|
||||||
|
return client_context_snapshot_.Get()->Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto GraphicsQualityFromRequest(GraphicsQualityRequest request,
|
||||||
|
GraphicsQuality auto_val)
|
||||||
|
-> GraphicsQuality;
|
||||||
|
static auto TextureQualityFromRequest(TextureQualityRequest request,
|
||||||
|
TextureQuality auto_val)
|
||||||
|
-> TextureQuality;
|
||||||
|
|
||||||
|
/// For temporary use from arbitrary threads. This should be removed when
|
||||||
|
/// possible and replaced with proper safe thread-specific access patterns
|
||||||
|
/// (so we can support switching renderers/etc.).
|
||||||
|
auto placeholder_texture_quality() const {
|
||||||
|
assert(client_context_snapshot_.Exists());
|
||||||
|
return texture_quality_placeholder_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For temporary use in arbitrary threads. This should be removed when
|
||||||
|
/// possible and replaced with proper safe thread-specific access
|
||||||
|
/// patterns (so we can support switching renderers/etc.).
|
||||||
|
auto placeholder_client_context() const -> const GraphicsClientContext* {
|
||||||
|
// Using this from arbitrary threads is currently ok currently since
|
||||||
|
// context never changes once set. Will need to kill this call once that
|
||||||
|
// can happen though.
|
||||||
|
assert(client_context_snapshot_.Exists());
|
||||||
|
return client_context_snapshot_.Get()->Get();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
class ScreenMessageEntry;
|
||||||
|
|
||||||
Graphics();
|
Graphics();
|
||||||
virtual ~Graphics();
|
virtual ~Graphics();
|
||||||
virtual void DoDrawFade(FrameDef* frame_def, float amt);
|
virtual void DoDrawFade(FrameDef* frame_def, float amt);
|
||||||
|
static void CalcVirtualRes_(float* x, float* y);
|
||||||
private:
|
|
||||||
class ScreenMessageEntry;
|
|
||||||
void DrawBoxingGlovesTest(FrameDef* frame_def);
|
void DrawBoxingGlovesTest(FrameDef* frame_def);
|
||||||
void DrawBlotches(FrameDef* frame_def);
|
void DrawBlotches(FrameDef* frame_def);
|
||||||
void DrawCursor(FrameDef* frame_def);
|
void DrawCursor(FrameDef* frame_def);
|
||||||
void DrawFades(FrameDef* frame_def);
|
void DrawFades(FrameDef* frame_def);
|
||||||
void DrawDebugBuffers(RenderPass* pass);
|
void DrawDebugBuffers(RenderPass* pass);
|
||||||
|
|
||||||
void UpdateAndDrawProgressBar(FrameDef* frame_def);
|
void UpdateAndDrawProgressBar(FrameDef* frame_def);
|
||||||
void DoDrawBlotch(std::vector<uint16_t>* indices,
|
void DoDrawBlotch(std::vector<uint16_t>* indices,
|
||||||
std::vector<VertexSprite>* verts, const Vector3f& pos,
|
std::vector<VertexSprite>* verts, const Vector3f& pos,
|
||||||
@ -347,44 +396,47 @@ class Graphics {
|
|||||||
void DrawProgressBar(RenderPass* pass, float opacity);
|
void DrawProgressBar(RenderPass* pass, float opacity);
|
||||||
void UpdateProgressBarProgress(float target);
|
void UpdateProgressBarProgress(float target);
|
||||||
void UpdateGyro(microsecs_t time, microsecs_t elapsed);
|
void UpdateGyro(microsecs_t time, microsecs_t elapsed);
|
||||||
|
void UpdateInitialGraphicsSettingsSend_();
|
||||||
|
|
||||||
bool drawing_transparent_only_{};
|
int last_total_frames_rendered_{};
|
||||||
bool drawing_opaque_only_{};
|
int last_fps_{};
|
||||||
bool has_supports_high_quality_graphics_value_{};
|
int progress_bar_loads_{};
|
||||||
bool supports_high_quality_graphics_{};
|
int frame_def_count_{};
|
||||||
bool internal_components_inited_{};
|
int frame_def_count_filtered_{};
|
||||||
bool fade_out_{true};
|
int next_settings_index_{};
|
||||||
bool progress_bar_{};
|
TextureQuality texture_quality_placeholder_{};
|
||||||
bool progress_bar_fade_in_{};
|
bool drawing_transparent_only_ : 1 {};
|
||||||
bool debug_draw_{};
|
bool drawing_opaque_only_ : 1 {};
|
||||||
bool network_debug_display_enabled_{};
|
bool internal_components_inited_ : 1 {};
|
||||||
bool hardware_cursor_visible_{};
|
bool fade_out_ : 1 {true};
|
||||||
bool camera_shake_disabled_{};
|
bool progress_bar_ : 1 {};
|
||||||
bool camera_gyro_explicitly_disabled_{};
|
bool progress_bar_fade_in_ : 1 {};
|
||||||
bool gyro_enabled_{true};
|
bool debug_draw_ : 1 {};
|
||||||
bool show_fps_{};
|
bool network_debug_display_enabled_ : 1 {};
|
||||||
bool show_ping_{};
|
bool hardware_cursor_visible_ : 1 {};
|
||||||
bool show_net_info_{};
|
bool camera_shake_disabled_ : 1 {};
|
||||||
bool tv_border_{};
|
bool camera_gyro_explicitly_disabled_ : 1 {};
|
||||||
bool floor_reflection_{};
|
bool gyro_enabled_ : 1 {true};
|
||||||
bool building_frame_def_{};
|
bool show_fps_ : 1 {};
|
||||||
bool shadow_ortho_{};
|
bool show_ping_ : 1 {};
|
||||||
bool fetched_overlay_node_z_depth_{};
|
bool show_net_info_ : 1 {};
|
||||||
bool gyro_broken_{};
|
bool tv_border_ : 1 {};
|
||||||
GraphicsQuality last_frame_def_graphics_quality_{GraphicsQuality::kUnset};
|
bool floor_reflection_ : 1 {};
|
||||||
std::list<Object::Ref<PythonContextCall>> clean_frame_commands_;
|
bool building_frame_def_ : 1 {};
|
||||||
std::vector<MeshData*> mesh_data_creates_;
|
bool shadow_ortho_ : 1 {};
|
||||||
std::vector<MeshData*> mesh_data_destroys_;
|
bool fetched_overlay_node_z_depth_ : 1 {};
|
||||||
microsecs_t last_create_frame_def_time_microsecs_{};
|
bool gyro_broken_ : 1 {};
|
||||||
millisecs_t last_create_frame_def_time_millisecs_{};
|
bool set_fade_start_on_next_draw_ : 1 {};
|
||||||
|
bool graphics_settings_dirty_ : 1 {true};
|
||||||
|
bool applied_app_config_ : 1 {};
|
||||||
|
bool sent_initial_graphics_settings_ : 1 {};
|
||||||
|
bool got_screen_resolution_ : 1 {};
|
||||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||||
Vector2f shadow_scale_{1.0f, 1.0f};
|
Vector2f shadow_scale_{1.0f, 1.0f};
|
||||||
Vector3f tint_{1.0f, 1.0f, 1.0f};
|
Vector3f tint_{1.0f, 1.0f, 1.0f};
|
||||||
Vector3f ambient_color_{1.0f, 1.0f, 1.0f};
|
Vector3f ambient_color_{1.0f, 1.0f, 1.0f};
|
||||||
Vector3f vignette_outer_{0.0f, 0.0f, 0.0f};
|
Vector3f vignette_outer_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f vignette_inner_{1.0f, 1.0f, 1.0f};
|
Vector3f vignette_inner_{1.0f, 1.0f, 1.0f};
|
||||||
std::vector<FrameDef*> recycle_frame_defs_;
|
|
||||||
millisecs_t last_jitter_update_time_{};
|
|
||||||
Vector3f jitter_{0.0f, 0.0f, 0.0f};
|
Vector3f jitter_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f accel_smoothed_{0.0f, 0.0f, 0.0f};
|
Vector3f accel_smoothed_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f accel_smoothed2_{0.0f, 0.0f, 0.0f};
|
Vector3f accel_smoothed2_{0.0f, 0.0f, 0.0f};
|
||||||
@ -394,8 +446,50 @@ class Graphics {
|
|||||||
Vector3f tilt_smoothed_{0.0f, 0.0f, 0.0f};
|
Vector3f tilt_smoothed_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f tilt_vel_{0.0f, 0.0f, 0.0f};
|
Vector3f tilt_vel_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f tilt_pos_{0.0f, 0.0f, 0.0f};
|
Vector3f tilt_pos_{0.0f, 0.0f, 0.0f};
|
||||||
|
Vector3f gyro_vals_{0.0f, 0.0, 0.0f};
|
||||||
|
std::string fps_string_;
|
||||||
|
std::string ping_string_;
|
||||||
|
std::string net_info_string_;
|
||||||
|
std::map<std::string, Object::Ref<NetGraph>> debug_graphs_;
|
||||||
|
std::mutex frame_def_delete_list_mutex_;
|
||||||
|
std::list<Object::Ref<PythonContextCall>> clean_frame_commands_;
|
||||||
|
std::list<ScreenMessageEntry> screen_messages_;
|
||||||
|
std::list<ScreenMessageEntry> screen_messages_top_;
|
||||||
|
std::vector<FrameDef*> recycle_frame_defs_;
|
||||||
|
std::vector<uint16_t> blotch_indices_;
|
||||||
|
std::vector<VertexSprite> blotch_verts_;
|
||||||
|
std::vector<uint16_t> blotch_soft_indices_;
|
||||||
|
std::vector<VertexSprite> blotch_soft_verts_;
|
||||||
|
std::vector<uint16_t> blotch_soft_obj_indices_;
|
||||||
|
std::vector<VertexSprite> blotch_soft_obj_verts_;
|
||||||
|
std::vector<FrameDef*> frame_def_delete_list_;
|
||||||
|
std::vector<MeshData*> mesh_data_creates_;
|
||||||
|
std::vector<MeshData*> mesh_data_destroys_;
|
||||||
|
float fade_{};
|
||||||
|
float res_x_{256.0f};
|
||||||
|
float res_y_{256.0f};
|
||||||
|
float res_x_virtual_{256.0f};
|
||||||
|
float res_y_virtual_{256.0f};
|
||||||
float gyro_mag_test_{};
|
float gyro_mag_test_{};
|
||||||
float overlay_node_z_depth_{};
|
float overlay_node_z_depth_{};
|
||||||
|
float progress_bar_progress_{};
|
||||||
|
float screen_gamma_{1.0f};
|
||||||
|
float shadow_lower_bottom_{-4.0f};
|
||||||
|
float shadow_lower_top_{4.0f};
|
||||||
|
float shadow_upper_bottom_{30.0f};
|
||||||
|
float shadow_upper_top_{40.0f};
|
||||||
|
millisecs_t fade_start_{};
|
||||||
|
millisecs_t fade_time_{};
|
||||||
|
millisecs_t next_stat_update_time_{};
|
||||||
|
millisecs_t progress_bar_end_time_{-9999};
|
||||||
|
millisecs_t last_progress_bar_draw_time_{};
|
||||||
|
millisecs_t last_progress_bar_start_time_{};
|
||||||
|
microsecs_t last_suppress_gyro_time_{};
|
||||||
|
millisecs_t last_cursor_visibility_event_time_{};
|
||||||
|
microsecs_t next_frame_number_filtered_increment_time_{};
|
||||||
|
microsecs_t last_create_frame_def_time_microsecs_{};
|
||||||
|
millisecs_t last_create_frame_def_time_millisecs_{};
|
||||||
|
millisecs_t last_jitter_update_time_{};
|
||||||
Object::Ref<ImageMesh> screen_mesh_;
|
Object::Ref<ImageMesh> screen_mesh_;
|
||||||
Object::Ref<ImageMesh> progress_bar_bottom_mesh_;
|
Object::Ref<ImageMesh> progress_bar_bottom_mesh_;
|
||||||
Object::Ref<ImageMesh> progress_bar_top_mesh_;
|
Object::Ref<ImageMesh> progress_bar_top_mesh_;
|
||||||
@ -406,49 +500,10 @@ class Graphics {
|
|||||||
Object::Ref<SpriteMesh> shadow_blotch_mesh_;
|
Object::Ref<SpriteMesh> shadow_blotch_mesh_;
|
||||||
Object::Ref<SpriteMesh> shadow_blotch_soft_mesh_;
|
Object::Ref<SpriteMesh> shadow_blotch_soft_mesh_;
|
||||||
Object::Ref<SpriteMesh> shadow_blotch_soft_obj_mesh_;
|
Object::Ref<SpriteMesh> shadow_blotch_soft_obj_mesh_;
|
||||||
std::string fps_string_;
|
|
||||||
std::string ping_string_;
|
|
||||||
std::string net_info_string_;
|
|
||||||
std::vector<uint16_t> blotch_indices_;
|
|
||||||
std::vector<VertexSprite> blotch_verts_;
|
|
||||||
std::vector<uint16_t> blotch_soft_indices_;
|
|
||||||
std::vector<VertexSprite> blotch_soft_verts_;
|
|
||||||
std::vector<uint16_t> blotch_soft_obj_indices_;
|
|
||||||
std::vector<VertexSprite> blotch_soft_obj_verts_;
|
|
||||||
std::map<std::string, Object::Ref<NetGraph>> debug_graphs_;
|
|
||||||
std::mutex frame_def_delete_list_mutex_;
|
|
||||||
std::vector<FrameDef*> frame_def_delete_list_;
|
|
||||||
Object::Ref<Camera> camera_;
|
Object::Ref<Camera> camera_;
|
||||||
millisecs_t next_stat_update_time_{};
|
|
||||||
int last_total_frames_rendered_{};
|
|
||||||
int last_fps_{};
|
|
||||||
std::list<ScreenMessageEntry> screen_messages_;
|
|
||||||
std::list<ScreenMessageEntry> screen_messages_top_;
|
|
||||||
bool set_fade_start_on_next_draw_{};
|
|
||||||
millisecs_t fade_start_{};
|
|
||||||
millisecs_t fade_time_{};
|
|
||||||
float fade_{};
|
|
||||||
Vector3f gyro_vals_{0.0f, 0.0, 0.0f};
|
|
||||||
float res_x_{100};
|
|
||||||
float res_y_{100};
|
|
||||||
float res_x_virtual_{100};
|
|
||||||
float res_y_virtual_{100};
|
|
||||||
int progress_bar_loads_{};
|
|
||||||
millisecs_t progress_bar_end_time_{-9999};
|
|
||||||
millisecs_t last_progress_bar_draw_time_{};
|
|
||||||
millisecs_t last_progress_bar_start_time_{};
|
|
||||||
float progress_bar_progress_{};
|
|
||||||
float screen_gamma_{1.0f};
|
|
||||||
float shadow_lower_bottom_{-4.0f};
|
|
||||||
float shadow_lower_top_{4.0f};
|
|
||||||
float shadow_upper_bottom_{30.0f};
|
|
||||||
float shadow_upper_top_{40.0f};
|
|
||||||
millisecs_t last_cursor_visibility_event_time_{};
|
|
||||||
microsecs_t next_frame_number_filtered_increment_time_{};
|
|
||||||
int64_t frame_def_count_{};
|
|
||||||
int64_t frame_def_count_filtered_{};
|
|
||||||
microsecs_t last_suppress_gyro_time_{};
|
|
||||||
Object::Ref<PythonContextCall> fade_end_call_;
|
Object::Ref<PythonContextCall> fade_end_call_;
|
||||||
|
Object::Ref<Snapshot<GraphicsSettings>> settings_snapshot_;
|
||||||
|
Object::Ref<Snapshot<GraphicsClientContext>> client_context_snapshot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|||||||
@ -32,15 +32,88 @@ void GraphicsServer::EnqueueFrameDef(FrameDef* framedef) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsServer::ApplySettings(const GraphicsSettings* settings) {
|
||||||
|
assert(g_base->InGraphicsContext());
|
||||||
|
|
||||||
|
// Only push each unique settings instance through once.
|
||||||
|
if (settings->index == settings_index_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settings_index_ = settings->index;
|
||||||
|
|
||||||
|
assert(settings->resolution.x >= 0.0f && settings->resolution.y >= 0.0f
|
||||||
|
&& settings->resolution_virtual.x >= 0.0f
|
||||||
|
&& settings->resolution_virtual.y >= 0.0f);
|
||||||
|
|
||||||
|
// Pull a few things out ourself such as screen resolution.
|
||||||
|
tv_border_ = settings->tv_border;
|
||||||
|
if (renderer_) {
|
||||||
|
renderer_->set_pixel_scale(settings->pixel_scale);
|
||||||
|
}
|
||||||
|
// Note: not checking virtual res here; assuming it only changes when
|
||||||
|
// actual res changes.
|
||||||
|
if (res_x_ != settings->resolution.x || res_y_ != settings->resolution.y) {
|
||||||
|
res_x_ = settings->resolution.x;
|
||||||
|
res_y_ = settings->resolution.y;
|
||||||
|
res_x_virtual_ = settings->resolution_virtual.x;
|
||||||
|
res_y_virtual_ = settings->resolution_virtual.y;
|
||||||
|
if (renderer_) {
|
||||||
|
renderer_->OnScreenSizeChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick this over to the app-adapter to apply whatever settings they
|
||||||
|
// gathered for themself.
|
||||||
|
g_base->app_adapter->ApplyGraphicsSettings(settings);
|
||||||
|
|
||||||
|
// Lastly, if we've not yet sent a context to the client, do so.
|
||||||
|
if (client_context_ == nullptr) {
|
||||||
|
set_client_context(g_base->app_adapter->GetGraphicsClientContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsServer::set_client_context(GraphicsClientContext* context) {
|
||||||
|
assert(g_base->InGraphicsContext());
|
||||||
|
|
||||||
|
// We have to do a bit of a song and dance with these context pointers.
|
||||||
|
// We wrap the context in an immutable object wrapper which is owned by
|
||||||
|
// the logic thread and that takes care of killing it when no longer
|
||||||
|
// used there, but we also need to keep it alive here in our thread.
|
||||||
|
// (which may not be the logic thread). So to accomplish that, we
|
||||||
|
// immediately ship a refcount increment over to the logic thread, and
|
||||||
|
// once we're done with an obj we ship a decrement.
|
||||||
|
|
||||||
|
auto* old_wrapper = client_context_;
|
||||||
|
auto* new_wrapper =
|
||||||
|
Object::NewDeferred<Snapshot<GraphicsClientContext>>(context);
|
||||||
|
|
||||||
|
client_context_ = new_wrapper;
|
||||||
|
|
||||||
|
g_base->logic->event_loop()->PushCall([old_wrapper, new_wrapper] {
|
||||||
|
// (This has to happen in logic thread).
|
||||||
|
auto ref = Object::CompleteDeferred(new_wrapper);
|
||||||
|
|
||||||
|
// Free the old one which the graphics server doesn't need anymore.
|
||||||
|
if (old_wrapper) {
|
||||||
|
old_wrapper->ObjectDecrementStrongRefCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the new one alive for the graphics server.
|
||||||
|
ref->ObjectIncrementStrongRefCount();
|
||||||
|
|
||||||
|
// Plug the new one in for logic to start using.
|
||||||
|
g_base->graphics->set_client_context(new_wrapper);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
auto GraphicsServer::TryRender() -> bool {
|
auto GraphicsServer::TryRender() -> bool {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
|
||||||
bool success{};
|
bool success{};
|
||||||
|
|
||||||
if (FrameDef* frame_def = WaitForRenderFrameDef_()) {
|
if (FrameDef* frame_def = WaitForRenderFrameDef_()) {
|
||||||
// Apply settings such as tv-mode that were passed along via the
|
// Apply any new graphics settings passed along via the frame-def.
|
||||||
// frame-def.
|
ApplySettings(frame_def->settings());
|
||||||
ApplyFrameDefSettings(frame_def);
|
|
||||||
|
|
||||||
// Note: we run mesh-updates on each frame-def that comes through even
|
// Note: we run mesh-updates on each frame-def that comes through even
|
||||||
// if we don't actually render the frame.
|
// if we don't actually render the frame.
|
||||||
@ -58,6 +131,7 @@ auto GraphicsServer::TryRender() -> bool {
|
|||||||
// Send this frame_def back to the logic thread for deletion or recycling.
|
// Send this frame_def back to the logic thread for deletion or recycling.
|
||||||
g_base->graphics->ReturnCompletedFrameDef(frame_def);
|
g_base->graphics->ReturnCompletedFrameDef(frame_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,11 +187,6 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsServer::ApplyFrameDefSettings(FrameDef* frame_def) {
|
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
|
||||||
tv_border_ = frame_def->tv_border();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs any mesh updates contained in the frame-def.
|
// Runs any mesh updates contained in the frame-def.
|
||||||
void GraphicsServer::RunFrameDefMeshUpdates(FrameDef* frame_def) {
|
void GraphicsServer::RunFrameDefMeshUpdates(FrameDef* frame_def) {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
assert(g_base->app_adapter->InGraphicsContext());
|
||||||
@ -250,14 +319,15 @@ void GraphicsServer::SetNullGraphics() {
|
|||||||
SetTextureCompressionTypes(c_types);
|
SetTextureCompressionTypes(c_types);
|
||||||
graphics_quality_requested_ = GraphicsQualityRequest::kLow;
|
graphics_quality_requested_ = GraphicsQualityRequest::kLow;
|
||||||
graphics_quality_ = GraphicsQuality::kLow;
|
graphics_quality_ = GraphicsQuality::kLow;
|
||||||
graphics_quality_set_ = true;
|
// graphics_quality_set_ = true;
|
||||||
texture_quality_requested_ = TextureQualityRequest::kLow;
|
texture_quality_requested_ = TextureQualityRequest::kLow;
|
||||||
texture_quality_ = TextureQuality::kLow;
|
texture_quality_ = TextureQuality::kLow;
|
||||||
texture_quality_set_ = true;
|
// texture_quality_set_ = true;
|
||||||
|
|
||||||
|
FatalError("FIXME REWORK THIS");
|
||||||
// Let the logic thread know screen creation is done (or lack thereof).
|
// Let the logic thread know screen creation is done (or lack thereof).
|
||||||
g_base->logic->event_loop()->PushCall(
|
// g_base->logic->event_loop()->PushCall(
|
||||||
[] { g_base->logic->OnGraphicsReady(); });
|
// [] { g_base->logic->OnGraphicsReady(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsServer::set_renderer(Renderer* renderer) {
|
void GraphicsServer::set_renderer(Renderer* renderer) {
|
||||||
@ -279,59 +349,43 @@ void GraphicsServer::LoadRenderer() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (graphics_quality_requested_) {
|
graphics_quality_ = Graphics::GraphicsQualityFromRequest(
|
||||||
case GraphicsQualityRequest::kLow:
|
graphics_quality_requested_, renderer_->GetAutoGraphicsQuality());
|
||||||
graphics_quality_ = GraphicsQuality::kLow;
|
|
||||||
break;
|
texture_quality_ = Graphics::TextureQualityFromRequest(
|
||||||
case GraphicsQualityRequest::kMedium:
|
texture_quality_requested_, renderer_->GetAutoTextureQuality());
|
||||||
graphics_quality_ = GraphicsQuality::kMedium;
|
|
||||||
break;
|
|
||||||
case GraphicsQualityRequest::kHigh:
|
|
||||||
graphics_quality_ = GraphicsQuality::kHigh;
|
|
||||||
break;
|
|
||||||
case GraphicsQualityRequest::kHigher:
|
|
||||||
graphics_quality_ = GraphicsQuality::kHigher;
|
|
||||||
break;
|
|
||||||
case GraphicsQualityRequest::kAuto:
|
|
||||||
graphics_quality_ = renderer_->GetAutoGraphicsQuality();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log(LogLevel::kError,
|
|
||||||
"Unhandled GraphicsQualityRequest value: "
|
|
||||||
+ std::to_string(static_cast<int>(graphics_quality_requested_)));
|
|
||||||
graphics_quality_ = GraphicsQuality::kLow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't support high quality graphics, make sure we're no higher than
|
// If we don't support high quality graphics, make sure we're no higher than
|
||||||
// medium.
|
// medium.
|
||||||
BA_PRECONDITION(g_base->graphics->has_supports_high_quality_graphics_value());
|
// BA_PRECONDITION(g_base->graphics->has_supports_high_quality_graphics_value());
|
||||||
if (!g_base->graphics->supports_high_quality_graphics()
|
// if (!g_base->graphics->supports_high_quality_graphics()
|
||||||
&& graphics_quality_ > GraphicsQuality::kMedium) {
|
// && graphics_quality_ > GraphicsQuality::kMedium) {
|
||||||
graphics_quality_ = GraphicsQuality::kMedium;
|
// graphics_quality_ = GraphicsQuality::kMedium;
|
||||||
}
|
// }
|
||||||
graphics_quality_set_ = true;
|
// graphics_quality_set_ = true;
|
||||||
|
|
||||||
// Update texture quality based on request.
|
// Update texture quality based on request.
|
||||||
switch (texture_quality_requested_) {
|
// switch (texture_quality_requested_) {
|
||||||
case TextureQualityRequest::kLow:
|
// case TextureQualityRequest::kLow:
|
||||||
texture_quality_ = TextureQuality::kLow;
|
// texture_quality_ = TextureQuality::kLow;
|
||||||
break;
|
// break;
|
||||||
case TextureQualityRequest::kMedium:
|
// case TextureQualityRequest::kMedium:
|
||||||
texture_quality_ = TextureQuality::kMedium;
|
// texture_quality_ = TextureQuality::kMedium;
|
||||||
break;
|
// break;
|
||||||
case TextureQualityRequest::kHigh:
|
// case TextureQualityRequest::kHigh:
|
||||||
texture_quality_ = TextureQuality::kHigh;
|
// texture_quality_ = TextureQuality::kHigh;
|
||||||
break;
|
// break;
|
||||||
case TextureQualityRequest::kAuto:
|
// case TextureQualityRequest::kAuto:
|
||||||
texture_quality_ = renderer_->GetAutoTextureQuality();
|
// texture_quality_ = renderer_->GetAutoTextureQuality();
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
Log(LogLevel::kError,
|
// Log(LogLevel::kError,
|
||||||
"Unhandled TextureQualityRequest value: "
|
// "Unhandled TextureQualityRequest value: "
|
||||||
+ std::to_string(static_cast<int>(texture_quality_requested_)));
|
// +
|
||||||
texture_quality_ = TextureQuality::kLow;
|
// std::to_string(static_cast<int>(texture_quality_requested_)));
|
||||||
}
|
// texture_quality_ = TextureQuality::kLow;
|
||||||
texture_quality_set_ = true;
|
// }
|
||||||
|
// texture_quality_set_ = true;
|
||||||
|
|
||||||
// Ok we've got our qualities figured out; now load/update the renderer.
|
// Ok we've got our qualities figured out; now load/update the renderer.
|
||||||
renderer_->Load();
|
renderer_->Load();
|
||||||
@ -389,56 +443,56 @@ void GraphicsServer::UnloadRenderer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Given physical res, calculate virtual res.
|
// Given physical res, calculate virtual res.
|
||||||
void GraphicsServer::CalcVirtualRes_(float* x, float* y) {
|
// void GraphicsServer::CalcVirtualRes_(float* x, float* y) {
|
||||||
float x_in = *x;
|
// float x_in = *x;
|
||||||
float y_in = *y;
|
// float y_in = *y;
|
||||||
if (*x / *y > static_cast<float>(kBaseVirtualResX)
|
// if (*x / *y > static_cast<float>(kBaseVirtualResX)
|
||||||
/ static_cast<float>(kBaseVirtualResY)) {
|
// / static_cast<float>(kBaseVirtualResY)) {
|
||||||
*y = kBaseVirtualResY;
|
// *y = kBaseVirtualResY;
|
||||||
*x = *y * (x_in / y_in);
|
// *x = *y * (x_in / y_in);
|
||||||
} else {
|
// } else {
|
||||||
*x = kBaseVirtualResX;
|
// *x = kBaseVirtualResX;
|
||||||
*y = *x * (y_in / x_in);
|
// *y = *x * (y_in / x_in);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void GraphicsServer::UpdateVirtualScreenRes_() {
|
// void GraphicsServer::UpdateVirtualScreenRes_() {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
// assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
|
||||||
// In vr mode our virtual res is independent of our screen size.
|
// // In vr mode our virtual res is independent of our screen size.
|
||||||
// (since it gets drawn to an overlay)
|
// // (since it gets drawn to an overlay)
|
||||||
if (g_core->IsVRMode()) {
|
// if (g_core->IsVRMode()) {
|
||||||
res_x_virtual_ = kBaseVirtualResX;
|
// res_x_virtual_ = kBaseVirtualResX;
|
||||||
res_y_virtual_ = kBaseVirtualResY;
|
// res_y_virtual_ = kBaseVirtualResY;
|
||||||
} else {
|
// } else {
|
||||||
res_x_virtual_ = res_x_;
|
// res_x_virtual_ = res_x_;
|
||||||
res_y_virtual_ = res_y_;
|
// res_y_virtual_ = res_y_;
|
||||||
CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_);
|
// CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void GraphicsServer::SetScreenResolution(float h, float v) {
|
// void GraphicsServer::SetScreenResolution(float h, float v) {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
// assert(g_base->app_adapter->InGraphicsContext());
|
||||||
|
|
||||||
// Ignore redundant sets.
|
// // Ignore redundant sets.
|
||||||
if (res_x_ == h && res_y_ == v) {
|
// if (res_x_ == h && res_y_ == v) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
res_x_ = h;
|
// res_x_ = h;
|
||||||
res_y_ = v;
|
// res_y_ = v;
|
||||||
UpdateVirtualScreenRes_();
|
// // UpdateVirtualScreenRes_();
|
||||||
|
|
||||||
// Inform renderer of the change.
|
// // Inform renderer of the change.
|
||||||
if (renderer_) {
|
// if (renderer_) {
|
||||||
renderer_->OnScreenSizeChange();
|
// renderer_->OnScreenSizeChange();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Inform all logic thread bits of this change.
|
// // Inform all logic thread bits of this change.
|
||||||
g_base->logic->event_loop()->PushCall(
|
// g_base->logic->event_loop()->PushCall(
|
||||||
[vx = res_x_virtual_, vy = res_y_virtual_, x = res_x_, y = res_y_] {
|
// [vx = res_x_virtual_, vy = res_y_virtual_, x = res_x_, y = res_y_] {
|
||||||
g_base->graphics->SetScreenSize(vx, vy, x, y);
|
// g_base->graphics->SetScreenSize(vx, vy, x, y);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// FIXME: Shouldn't have android-specific code in here.
|
// FIXME: Shouldn't have android-specific code in here.
|
||||||
void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) {
|
void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) {
|
||||||
@ -579,15 +633,15 @@ void GraphicsServer::PushReloadMediaCall() {
|
|||||||
g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); });
|
g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) {
|
// void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) {
|
||||||
g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] {
|
// g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] {
|
||||||
assert(g_base->app_adapter->InGraphicsContext());
|
// assert(g_base->app_adapter->InGraphicsContext());
|
||||||
if (!renderer_) {
|
// if (!renderer_) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
renderer_->set_pixel_scale(pixel_scale);
|
// renderer_->set_pixel_scale(pixel_scale);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
void GraphicsServer::PushComponentUnloadCall(
|
void GraphicsServer::PushComponentUnloadCall(
|
||||||
const std::vector<Object::Ref<Asset>*>& components) {
|
const std::vector<Object::Ref<Asset>*>& components) {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "ballistica/base/base.h"
|
#include "ballistica/base/base.h"
|
||||||
#include "ballistica/shared/foundation/object.h"
|
#include "ballistica/shared/foundation/object.h"
|
||||||
|
#include "ballistica/shared/generic/snapshot.h"
|
||||||
#include "ballistica/shared/math/matrix44f.h"
|
#include "ballistica/shared/math/matrix44f.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
@ -51,16 +52,18 @@ class GraphicsServer {
|
|||||||
return renderer_loaded_;
|
return renderer_loaded_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplySettings(const GraphicsSettings* settings);
|
||||||
|
|
||||||
/// The AppAdapter should call this to inform the engine of screen size
|
/// The AppAdapter should call this to inform the engine of screen size
|
||||||
/// changes. Changes will be applied to the server and then sent to the
|
/// changes. Changes will be applied to the server and then sent to the
|
||||||
/// logic thread to apply to various app systems (ui, etc.).
|
/// logic thread to apply to various app systems (ui, etc.).
|
||||||
void SetScreenResolution(float h, float v);
|
// void SetScreenResolution(float h, float v);
|
||||||
|
|
||||||
/// Used by headless builds to init the graphics-server into a
|
/// Used by headless builds to init the graphics-server into a
|
||||||
/// non-functional state.
|
/// non-functional state.
|
||||||
void SetNullGraphics();
|
void SetNullGraphics();
|
||||||
|
|
||||||
void PushSetScreenPixelScaleCall(float pixel_scale);
|
// void PushSetScreenPixelScaleCall(float pixel_scale);
|
||||||
void PushReloadMediaCall();
|
void PushReloadMediaCall();
|
||||||
void PushRemoveRenderHoldCall();
|
void PushRemoveRenderHoldCall();
|
||||||
void PushComponentUnloadCall(
|
void PushComponentUnloadCall(
|
||||||
@ -71,8 +74,6 @@ class GraphicsServer {
|
|||||||
/// rendering.
|
/// rendering.
|
||||||
void EnqueueFrameDef(FrameDef* framedef);
|
void EnqueueFrameDef(FrameDef* framedef);
|
||||||
|
|
||||||
void ApplyFrameDefSettings(FrameDef* frame_def);
|
|
||||||
|
|
||||||
void RunFrameDefMeshUpdates(FrameDef* frame_def);
|
void RunFrameDefMeshUpdates(FrameDef* frame_def);
|
||||||
|
|
||||||
// Renders shadow passes and other common parts of a frame_def.
|
// Renders shadow passes and other common parts of a frame_def.
|
||||||
@ -108,9 +109,7 @@ class GraphicsServer {
|
|||||||
projection_matrix_state_++;
|
projection_matrix_state_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto projection_matrix_state() -> uint32_t {
|
auto projection_matrix_state() { return projection_matrix_state_; }
|
||||||
return projection_matrix_state_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLightShadowProjectionMatrix(const Matrix44f& p) {
|
void SetLightShadowProjectionMatrix(const Matrix44f& p) {
|
||||||
// This will generally get repeatedly set to the same value
|
// This will generally get repeatedly set to the same value
|
||||||
@ -121,61 +120,57 @@ class GraphicsServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto light_shadow_projection_matrix_state() const -> uint32_t {
|
auto light_shadow_projection_matrix_state() const {
|
||||||
return light_shadow_projection_matrix_state_;
|
return light_shadow_projection_matrix_state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto light_shadow_projection_matrix() const -> const Matrix44f& {
|
const auto& light_shadow_projection_matrix() const {
|
||||||
return light_shadow_projection_matrix_;
|
return light_shadow_projection_matrix_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the modelview * projection matrix.
|
// Return the modelview * projection matrix.
|
||||||
auto GetModelViewProjectionMatrix() -> const Matrix44f& {
|
const auto& GetModelViewProjectionMatrix() {
|
||||||
UpdateModelViewProjectionMatrix_();
|
UpdateModelViewProjectionMatrix_();
|
||||||
return model_view_projection_matrix_;
|
return model_view_projection_matrix_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetModelViewProjectionMatrixState() -> uint32_t {
|
auto GetModelViewProjectionMatrixState() {
|
||||||
UpdateModelViewProjectionMatrix_();
|
UpdateModelViewProjectionMatrix_();
|
||||||
return model_view_projection_matrix_state_;
|
return model_view_projection_matrix_state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetModelWorldMatrix() -> const Matrix44f& {
|
const auto& GetModelWorldMatrix() {
|
||||||
UpdateModelWorldMatrix_();
|
UpdateModelWorldMatrix_();
|
||||||
return model_world_matrix_;
|
return model_world_matrix_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetModelWorldMatrixState() -> uint32_t {
|
auto GetModelWorldMatrixState() {
|
||||||
UpdateModelWorldMatrix_();
|
UpdateModelWorldMatrix_();
|
||||||
return model_world_matrix_state_;
|
return model_world_matrix_state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cam_pos() -> const Vector3f& { return cam_pos_; }
|
const auto& cam_pos() { return cam_pos_; }
|
||||||
|
|
||||||
auto cam_pos_state() -> uint32_t { return cam_pos_state_; }
|
auto cam_pos_state() { return cam_pos_state_; }
|
||||||
|
|
||||||
auto GetCamOrientMatrix() -> const Matrix44f& {
|
const auto& GetCamOrientMatrix() {
|
||||||
UpdateCamOrientMatrix_();
|
UpdateCamOrientMatrix_();
|
||||||
return cam_orient_matrix_;
|
return cam_orient_matrix_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetCamOrientMatrixState() -> uint32_t {
|
auto GetCamOrientMatrixState() {
|
||||||
UpdateCamOrientMatrix_();
|
UpdateCamOrientMatrix_();
|
||||||
return cam_orient_matrix_state_;
|
return cam_orient_matrix_state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto model_view_matrix() const -> const Matrix44f& {
|
const auto& model_view_matrix() const { return model_view_matrix_; }
|
||||||
return model_view_matrix_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetModelViewMatrix(const Matrix44f& m) {
|
void SetModelViewMatrix(const Matrix44f& m) {
|
||||||
model_view_matrix_ = m;
|
model_view_matrix_ = m;
|
||||||
model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true;
|
model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto projection_matrix() const -> const Matrix44f& {
|
const auto& projection_matrix() const { return projection_matrix_; }
|
||||||
return projection_matrix_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushTransform() {
|
void PushTransform() {
|
||||||
model_view_stack_.push_back(model_view_matrix_);
|
model_view_stack_.push_back(model_view_matrix_);
|
||||||
@ -209,32 +204,34 @@ class GraphicsServer {
|
|||||||
model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true;
|
model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto quality() const -> GraphicsQuality {
|
auto quality() const {
|
||||||
assert(graphics_quality_set_);
|
assert(InGraphicsContext_());
|
||||||
|
assert(graphics_quality_ != GraphicsQuality::kUnset);
|
||||||
return graphics_quality_;
|
return graphics_quality_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto texture_quality() const -> TextureQuality {
|
auto texture_quality() const {
|
||||||
assert(texture_quality_set_);
|
assert(InGraphicsContext_());
|
||||||
|
assert(texture_quality_ != TextureQuality::kUnset);
|
||||||
return texture_quality_;
|
return texture_quality_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto screen_pixel_width() const -> float {
|
auto screen_pixel_width() const {
|
||||||
assert(InGraphicsContext_());
|
assert(InGraphicsContext_());
|
||||||
return res_x_;
|
return res_x_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto screen_pixel_height() const -> float {
|
auto screen_pixel_height() const {
|
||||||
assert(InGraphicsContext_());
|
assert(InGraphicsContext_());
|
||||||
return res_y_;
|
return res_y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto screen_virtual_width() const -> float {
|
auto screen_virtual_width() const {
|
||||||
assert(InGraphicsContext_());
|
assert(InGraphicsContext_());
|
||||||
return res_x_virtual_;
|
return res_x_virtual_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto screen_virtual_height() const -> float {
|
auto screen_virtual_height() const {
|
||||||
assert(InGraphicsContext_());
|
assert(InGraphicsContext_());
|
||||||
return res_y_virtual_;
|
return res_y_virtual_;
|
||||||
}
|
}
|
||||||
@ -244,45 +241,69 @@ class GraphicsServer {
|
|||||||
return tv_border_;
|
return tv_border_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto graphics_quality_set() const { return graphics_quality_set_; }
|
// auto graphics_quality_set() const {
|
||||||
|
// return graphics_quality_ != GraphicsQuality::kUnset;
|
||||||
|
// }
|
||||||
|
|
||||||
auto texture_quality_set() const { return texture_quality_set_; }
|
// auto texture_quality_set() const {
|
||||||
|
// return texture_quality_ != TextureQuality::kUnset;
|
||||||
|
// }
|
||||||
|
|
||||||
auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool {
|
auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
assert(texture_compression_types_set_);
|
assert(texture_compression_types_set_);
|
||||||
return ((texture_compression_types_ & (0x01u << static_cast<uint32_t>(t)))
|
return ((texture_compression_types_ & (0x01u << static_cast<uint32_t>(t)))
|
||||||
!= 0u);
|
!= 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTextureCompressionTypes(
|
void SetTextureCompressionTypes(
|
||||||
const std::list<TextureCompressionType>& types);
|
const std::list<TextureCompressionType>& types);
|
||||||
|
|
||||||
auto texture_compression_types_are_set() const {
|
// auto texture_compression_types_are_set() const {
|
||||||
return texture_compression_types_set_;
|
// return texture_compression_types_set_;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void set_renderer_context_lost(bool lost) { renderer_context_lost_ = lost; }
|
void set_renderer_context_lost(bool lost) { renderer_context_lost_ = lost; }
|
||||||
|
|
||||||
auto renderer_context_lost() const { return renderer_context_lost_; }
|
auto renderer_context_lost() const { return renderer_context_lost_; }
|
||||||
|
|
||||||
auto graphics_quality_requested() const {
|
auto graphics_quality_requested() const {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
return graphics_quality_requested_;
|
return graphics_quality_requested_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_graphics_quality_requested(GraphicsQualityRequest val) {
|
void set_graphics_quality_requested(GraphicsQualityRequest val) {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
graphics_quality_requested_ = val;
|
graphics_quality_requested_ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_texture_quality_requested(TextureQualityRequest val) {
|
void set_texture_quality_requested(TextureQualityRequest val) {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
texture_quality_requested_ = val;
|
texture_quality_requested_ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto graphics_quality() const { return graphics_quality_; }
|
auto graphics_quality() const {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
|
return graphics_quality_;
|
||||||
|
}
|
||||||
|
|
||||||
auto texture_quality_requested() const { return texture_quality_requested_; }
|
auto texture_quality_requested() const {
|
||||||
|
assert(InGraphicsContext_());
|
||||||
|
return texture_quality_requested_;
|
||||||
|
}
|
||||||
|
|
||||||
void HandlePushAndroidRes(const std::string& android_res);
|
void HandlePushAndroidRes(const std::string& android_res);
|
||||||
|
|
||||||
|
auto texture_compression_types() const {
|
||||||
|
assert(texture_compression_types_set_);
|
||||||
|
return texture_compression_types_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Pass a freshly allocated GraphicsContext instance, which the graphics
|
||||||
|
/// system will take ownership of.
|
||||||
|
void set_client_context(GraphicsClientContext* context);
|
||||||
|
|
||||||
// So we don't have to include app_adapter.h here for asserts.
|
// So we don't have to include app_adapter.h here for asserts.
|
||||||
auto InGraphicsContext_() const -> bool;
|
auto InGraphicsContext_() const -> bool;
|
||||||
|
|
||||||
@ -293,8 +314,8 @@ class GraphicsServer {
|
|||||||
auto WaitForRenderFrameDef_() -> FrameDef*;
|
auto WaitForRenderFrameDef_() -> FrameDef*;
|
||||||
|
|
||||||
// Update virtual screen dimensions based on the current physical ones.
|
// Update virtual screen dimensions based on the current physical ones.
|
||||||
static void CalcVirtualRes_(float* x, float* y);
|
// static void CalcVirtualRes_(float* x, float* y);
|
||||||
void UpdateVirtualScreenRes_();
|
// void UpdateVirtualScreenRes_();
|
||||||
void UpdateCamOrientMatrix_();
|
void UpdateCamOrientMatrix_();
|
||||||
void ReloadMedia_();
|
void ReloadMedia_();
|
||||||
void UpdateModelViewProjectionMatrix_() {
|
void UpdateModelViewProjectionMatrix_() {
|
||||||
@ -314,23 +335,17 @@ class GraphicsServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool renderer_loaded_ : 1 {};
|
bool renderer_loaded_ : 1 {};
|
||||||
bool v_sync_ : 1 {};
|
|
||||||
bool auto_vsync_ : 1 {};
|
|
||||||
bool model_view_projection_matrix_dirty_ : 1 {true};
|
bool model_view_projection_matrix_dirty_ : 1 {true};
|
||||||
bool model_world_matrix_dirty_ : 1 {true};
|
bool model_world_matrix_dirty_ : 1 {true};
|
||||||
bool graphics_quality_set_ : 1 {};
|
|
||||||
bool texture_quality_set_ : 1 {};
|
|
||||||
bool tv_border_ : 1 {};
|
bool tv_border_ : 1 {};
|
||||||
bool renderer_context_lost_ : 1 {};
|
bool renderer_context_lost_ : 1 {};
|
||||||
bool texture_compression_types_set_ : 1 {};
|
bool texture_compression_types_set_ : 1 {};
|
||||||
bool cam_orient_matrix_dirty_ : 1 {true};
|
bool cam_orient_matrix_dirty_ : 1 {true};
|
||||||
TextureQualityRequest texture_quality_requested_{
|
Snapshot<GraphicsClientContext>* client_context_{};
|
||||||
TextureQualityRequest::kUnset};
|
TextureQualityRequest texture_quality_requested_{};
|
||||||
TextureQuality texture_quality_{TextureQuality::kLow};
|
TextureQuality texture_quality_{};
|
||||||
GraphicsQualityRequest graphics_quality_requested_{
|
GraphicsQualityRequest graphics_quality_requested_{};
|
||||||
GraphicsQualityRequest::kUnset};
|
GraphicsQuality graphics_quality_{};
|
||||||
GraphicsQuality graphics_quality_{GraphicsQuality::kUnset};
|
|
||||||
int render_hold_{};
|
|
||||||
float res_x_{};
|
float res_x_{};
|
||||||
float res_y_{};
|
float res_y_{};
|
||||||
float res_x_virtual_{};
|
float res_x_virtual_{};
|
||||||
@ -340,20 +355,21 @@ class GraphicsServer {
|
|||||||
Matrix44f projection_matrix_{kMatrix44fIdentity};
|
Matrix44f projection_matrix_{kMatrix44fIdentity};
|
||||||
Matrix44f model_view_projection_matrix_{kMatrix44fIdentity};
|
Matrix44f model_view_projection_matrix_{kMatrix44fIdentity};
|
||||||
Matrix44f model_world_matrix_{kMatrix44fIdentity};
|
Matrix44f model_world_matrix_{kMatrix44fIdentity};
|
||||||
std::vector<Matrix44f> model_view_stack_;
|
|
||||||
uint32_t texture_compression_types_{};
|
uint32_t texture_compression_types_{};
|
||||||
uint32_t projection_matrix_state_{1};
|
int render_hold_{};
|
||||||
uint32_t model_view_projection_matrix_state_{1};
|
int projection_matrix_state_{};
|
||||||
uint32_t model_world_matrix_state_{1};
|
int model_view_projection_matrix_state_{};
|
||||||
uint32_t light_shadow_projection_matrix_state_{1};
|
int model_world_matrix_state_{};
|
||||||
uint32_t cam_pos_state_{1};
|
int light_shadow_projection_matrix_state_{};
|
||||||
uint32_t cam_orient_matrix_state_{1};
|
int cam_pos_state_{};
|
||||||
|
int cam_orient_matrix_state_{};
|
||||||
|
int settings_index_{-1};
|
||||||
Vector3f cam_pos_{0.0f, 0.0f, 0.0f};
|
Vector3f cam_pos_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f cam_target_{0.0f, 0.0f, 0.0f};
|
Vector3f cam_target_{0.0f, 0.0f, 0.0f};
|
||||||
Matrix44f light_shadow_projection_matrix_{kMatrix44fIdentity};
|
Matrix44f light_shadow_projection_matrix_{kMatrix44fIdentity};
|
||||||
Matrix44f cam_orient_matrix_ = kMatrix44fIdentity;
|
Matrix44f cam_orient_matrix_ = kMatrix44fIdentity;
|
||||||
|
std::vector<Matrix44f> model_view_stack_;
|
||||||
std::list<MeshData*> mesh_datas_;
|
std::list<MeshData*> mesh_datas_;
|
||||||
Timer* render_timer_{};
|
|
||||||
Renderer* renderer_{};
|
Renderer* renderer_{};
|
||||||
FrameDef* frame_def_{};
|
FrameDef* frame_def_{};
|
||||||
std::mutex frame_def_mutex_{};
|
std::mutex frame_def_mutex_{};
|
||||||
|
|||||||
@ -487,7 +487,7 @@ void RenderPass::SetFrustum(float near_val, float far_val) {
|
|||||||
g_base->graphics_server->SetProjectionMatrix(projection_matrix_);
|
g_base->graphics_server->SetProjectionMatrix(projection_matrix_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPass::Finalize() {
|
void RenderPass::Complete() {
|
||||||
if (UsesWorldLists()) {
|
if (UsesWorldLists()) {
|
||||||
for (auto& command : commands_) {
|
for (auto& command : commands_) {
|
||||||
command->Finalize();
|
command->Finalize();
|
||||||
|
|||||||
@ -112,7 +112,7 @@ class RenderPass {
|
|||||||
return model_view_projection_matrix_;
|
return model_view_projection_matrix_;
|
||||||
}
|
}
|
||||||
auto HasDrawCommands() const -> bool;
|
auto HasDrawCommands() const -> bool;
|
||||||
void Finalize();
|
void Complete();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
// Whether this pass draws stuff from the per-shader command lists
|
// Whether this pass draws stuff from the per-shader command lists
|
||||||
|
|||||||
@ -35,10 +35,12 @@ void Renderer::PreprocessFrameDef(FrameDef* frame_def) {
|
|||||||
|
|
||||||
// If this frame_def was made in a different quality mode than we're
|
// If this frame_def was made in a different quality mode than we're
|
||||||
// currently in, don't attempt to render it.
|
// currently in, don't attempt to render it.
|
||||||
if (frame_def->quality() != g_base->graphics_server->quality()) {
|
// UPDATE - scratch that; we now set our quality FROM the frame def.
|
||||||
frame_def->set_rendering(false);
|
// if (frame_def->quality() != g_base->graphics_server->quality()) {
|
||||||
return;
|
// frame_def->set_rendering(false);
|
||||||
}
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
frame_def->set_rendering(true);
|
frame_def->set_rendering(true);
|
||||||
|
|
||||||
// Some VR environments muck with render states before/after
|
// Some VR environments muck with render states before/after
|
||||||
|
|||||||
@ -82,7 +82,6 @@ class Renderer {
|
|||||||
auto light_pitch() const -> float { return light_pitch_; }
|
auto light_pitch() const -> float { return light_pitch_; }
|
||||||
auto light_heading() const -> float { return light_heading_; }
|
auto light_heading() const -> float { return light_heading_; }
|
||||||
void set_pixel_scale(float s) { pixel_scale_requested_ = s; }
|
void set_pixel_scale(float s) { pixel_scale_requested_ = s; }
|
||||||
// void set_screen_gamma(float val) { screen_gamma_requested_ = val; }
|
|
||||||
void set_debug_draw_mode(bool debugModeIn) { debug_draw_mode_ = debugModeIn; }
|
void set_debug_draw_mode(bool debugModeIn) { debug_draw_mode_ = debugModeIn; }
|
||||||
auto debug_draw_mode() -> bool { return debug_draw_mode_; }
|
auto debug_draw_mode() -> bool { return debug_draw_mode_; }
|
||||||
|
|
||||||
@ -269,7 +268,6 @@ class Renderer {
|
|||||||
Vector3f vignette_outer_{0.0f, 0.0f, 0.0f};
|
Vector3f vignette_outer_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f vignette_inner_{1.0f, 1.0f, 1.0f};
|
Vector3f vignette_inner_{1.0f, 1.0f, 1.0f};
|
||||||
int shadow_res_{-1};
|
int shadow_res_{-1};
|
||||||
// float screen_gamma_requested_{1.0f};
|
|
||||||
float screen_gamma_{1.0f};
|
float screen_gamma_{1.0f};
|
||||||
float pixel_scale_requested_{1.0f};
|
float pixel_scale_requested_{1.0f};
|
||||||
float pixel_scale_{1.0f};
|
float pixel_scale_{1.0f};
|
||||||
|
|||||||
@ -1013,7 +1013,7 @@ void Camera::ApplyToFrameDef(FrameDef* frame_def) {
|
|||||||
up_, 4, 1000.0f,
|
up_, 4, 1000.0f,
|
||||||
-1.0f, // Auto x fov.
|
-1.0f, // Auto x fov.
|
||||||
final_fov_y
|
final_fov_y
|
||||||
* (g_base->graphics->tv_border() ? (1.0f + kTVBorder) : 1.0f),
|
* (frame_def->settings()->tv_border ? (1.0f + kTVBorder) : 1.0f),
|
||||||
false, 0, 0, 0, 0, // Not using tangent fovs.
|
false, 0, 0, 0, 0, // Not using tangent fovs.
|
||||||
area_of_interest_points_);
|
area_of_interest_points_);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,13 @@ auto FrameDef::GetOverlayFlatPass() -> RenderPass* {
|
|||||||
|
|
||||||
void FrameDef::Reset() {
|
void FrameDef::Reset() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
|
|
||||||
|
// Update & grab the current settings.
|
||||||
|
settings_snapshot_ = g_base->graphics->GetGraphicsSettingsSnapshot();
|
||||||
|
|
||||||
|
auto* settings = settings_snapshot_->Get();
|
||||||
|
auto* client_context = g_base->graphics->client_context();
|
||||||
|
|
||||||
app_time_microsecs_ = 0;
|
app_time_microsecs_ = 0;
|
||||||
display_time_microsecs_ = 0;
|
display_time_microsecs_ = 0;
|
||||||
display_time_elapsed_microsecs_ = 0;
|
display_time_elapsed_microsecs_ = 0;
|
||||||
@ -68,11 +75,17 @@ void FrameDef::Reset() {
|
|||||||
mesh_index_sizes_.clear();
|
mesh_index_sizes_.clear();
|
||||||
mesh_buffers_.clear();
|
mesh_buffers_.clear();
|
||||||
|
|
||||||
quality_ = g_base->graphics_server->quality();
|
quality_ = Graphics::GraphicsQualityFromRequest(
|
||||||
|
settings->graphics_quality, client_context->auto_graphics_quality);
|
||||||
|
|
||||||
assert(g_base->graphics->has_supports_high_quality_graphics_value());
|
texture_quality_ = Graphics::TextureQualityFromRequest(
|
||||||
|
settings->texture_quality, client_context->auto_texture_quality);
|
||||||
|
|
||||||
|
// pixel_scale_ = g_base->graphics->settings()->pixel_scale;
|
||||||
|
|
||||||
|
// assert(g_base->graphics->has_supports_high_quality_graphics_value());
|
||||||
orbiting_ = (g_base->graphics->camera()->mode() == CameraMode::kOrbit);
|
orbiting_ = (g_base->graphics->camera()->mode() == CameraMode::kOrbit);
|
||||||
tv_border_ = g_base->graphics->tv_border();
|
// tv_border_ = g_base->graphics->tv_border();
|
||||||
|
|
||||||
shadow_offset_ = g_base->graphics->shadow_offset();
|
shadow_offset_ = g_base->graphics->shadow_offset();
|
||||||
shadow_scale_ = g_base->graphics->shadow_scale();
|
shadow_scale_ = g_base->graphics->shadow_scale();
|
||||||
@ -99,21 +112,21 @@ void FrameDef::Reset() {
|
|||||||
beauty_pass_->set_floor_reflection(g_base->graphics->floor_reflection());
|
beauty_pass_->set_floor_reflection(g_base->graphics->floor_reflection());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameDef::Finalize() {
|
void FrameDef::Complete() {
|
||||||
assert(!defining_component_);
|
assert(!defining_component_);
|
||||||
light_pass_->Finalize();
|
light_pass_->Complete();
|
||||||
light_shadow_pass_->Finalize();
|
light_shadow_pass_->Complete();
|
||||||
beauty_pass_->Finalize();
|
beauty_pass_->Complete();
|
||||||
beauty_pass_bg_->Finalize();
|
beauty_pass_bg_->Complete();
|
||||||
overlay_pass_->Finalize();
|
overlay_pass_->Complete();
|
||||||
overlay_front_pass_->Finalize();
|
overlay_front_pass_->Complete();
|
||||||
if (g_core->IsVRMode()) {
|
if (g_core->IsVRMode()) {
|
||||||
overlay_fixed_pass_->Finalize();
|
overlay_fixed_pass_->Complete();
|
||||||
overlay_flat_pass_->Finalize();
|
overlay_flat_pass_->Complete();
|
||||||
vr_cover_pass_->Finalize();
|
vr_cover_pass_->Complete();
|
||||||
}
|
}
|
||||||
overlay_3d_pass_->Finalize();
|
overlay_3d_pass_->Complete();
|
||||||
blit_pass_->Finalize();
|
blit_pass_->Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameDef::AddMesh(Mesh* mesh) {
|
void FrameDef::AddMesh(Mesh* mesh) {
|
||||||
|
|||||||
@ -7,13 +7,14 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ballistica/base/assets/asset.h"
|
#include "ballistica/base/assets/asset.h"
|
||||||
|
#include "ballistica/shared/generic/snapshot.h"
|
||||||
#include "ballistica/shared/math/matrix44f.h"
|
#include "ballistica/shared/math/matrix44f.h"
|
||||||
#include "ballistica/shared/math/vector2f.h"
|
#include "ballistica/shared/math/vector2f.h"
|
||||||
|
|
||||||
namespace ballistica::base {
|
namespace ballistica::base {
|
||||||
|
|
||||||
/// A flattened representation of a frame; generated by the logic thread and
|
/// A flattened representation of a frame; generated by the logic thread and
|
||||||
/// sent to the graphics thread to render.
|
/// sent to the graphics server to render.
|
||||||
class FrameDef {
|
class FrameDef {
|
||||||
public:
|
public:
|
||||||
auto light_pass() -> RenderPass* { return light_pass_.get(); }
|
auto light_pass() -> RenderPass* { return light_pass_.get(); }
|
||||||
@ -49,15 +50,15 @@ class FrameDef {
|
|||||||
|
|
||||||
// A number incremented for each frame renderered. Note that graphics code
|
// A number incremented for each frame renderered. Note that graphics code
|
||||||
// should not plug this directly into things like flash calculations since
|
// should not plug this directly into things like flash calculations since
|
||||||
// frame-rates will vary a lot these days. A 30hz flash will look a lot
|
// frame-rates vary a lot these days. A 30hz flash will look a lot
|
||||||
// different than a 240hz flash. Use frame_number_filtered() for such
|
// different than a 240hz flash. Use frame_number_filtered() for such
|
||||||
// purposes.
|
// purposes.
|
||||||
auto frame_number() const { return frame_number_; }
|
auto frame_number() const { return frame_number_; }
|
||||||
|
|
||||||
// A number incremented for each frame rendered, but a maximum of 60 times
|
// A number incremented for each frame rendered, but a maximum of 60 times
|
||||||
// per second. Code for drawing flashes or other exact effects should use
|
// per second. Code for drawing flashes or other crisp blink-y effects
|
||||||
// this value instead of regular frame_number so that things don't turn
|
// should use this value instead of regular frame_number so that things
|
||||||
// muddy at extremely high frame rates.
|
// don't turn muddy at extremely high frame rates.
|
||||||
auto frame_number_filtered() const { return frame_number_filtered_; }
|
auto frame_number_filtered() const { return frame_number_filtered_; }
|
||||||
|
|
||||||
// Returns the display-time this frame-def was created at (tries to match
|
// Returns the display-time this frame-def was created at (tries to match
|
||||||
@ -66,14 +67,19 @@ class FrameDef {
|
|||||||
auto display_time_millisecs() const -> millisecs_t {
|
auto display_time_millisecs() const -> millisecs_t {
|
||||||
return display_time_microsecs_ / 1000;
|
return display_time_microsecs_ / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto display_time_microsecs() const -> microsecs_t {
|
auto display_time_microsecs() const -> microsecs_t {
|
||||||
return display_time_microsecs_;
|
return display_time_microsecs_;
|
||||||
}
|
}
|
||||||
auto display_time() const -> double {
|
|
||||||
return static_cast<double>(display_time_microsecs_) / 1000000.0;
|
auto display_time() const -> seconds_t {
|
||||||
|
return static_cast<seconds_t>(display_time_microsecs_) / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto display_time_elapsed() const -> seconds_t {
|
||||||
|
return static_cast<seconds_t>(display_time_elapsed_microsecs_) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// How much display time does this frame-def represent.
|
|
||||||
auto display_time_elapsed_millisecs() const -> millisecs_t {
|
auto display_time_elapsed_millisecs() const -> millisecs_t {
|
||||||
return display_time_elapsed_millisecs_;
|
return display_time_elapsed_millisecs_;
|
||||||
}
|
}
|
||||||
@ -82,7 +88,9 @@ class FrameDef {
|
|||||||
return display_time_elapsed_microsecs_;
|
return display_time_elapsed_microsecs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto quality() const -> GraphicsQuality { return quality_; }
|
auto quality() const { return quality_; }
|
||||||
|
auto texture_quality() const { return texture_quality_; }
|
||||||
|
|
||||||
auto orbiting() const -> bool { return orbiting_; }
|
auto orbiting() const -> bool { return orbiting_; }
|
||||||
auto shadow_offset() const -> const Vector3f& { return shadow_offset_; }
|
auto shadow_offset() const -> const Vector3f& { return shadow_offset_; }
|
||||||
auto shadow_scale() const -> const Vector2f& { return shadow_scale_; }
|
auto shadow_scale() const -> const Vector2f& { return shadow_scale_; }
|
||||||
@ -115,11 +123,12 @@ class FrameDef {
|
|||||||
vr_overlay_screen_matrix_fixed_ = mat;
|
vr_overlay_screen_matrix_fixed_ = mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Effects requiring availability of a depth texture should
|
// Effects requiring availability of a depth texture should check this to
|
||||||
// check this to determine whether they should draw.
|
// determine whether they should draw.
|
||||||
auto has_depth_texture() const -> bool {
|
auto HasDepthTexture() const -> bool {
|
||||||
return (quality_ >= GraphicsQuality::kHigh);
|
return (quality_ >= GraphicsQuality::kHigh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddComponent(const Object::Ref<Asset>& component) {
|
void AddComponent(const Object::Ref<Asset>& component) {
|
||||||
// Add a reference to this component only if we havn't yet.
|
// Add a reference to this component only if we havn't yet.
|
||||||
if (component->last_frame_def_num() != frame_number_) {
|
if (component->last_frame_def_num() != frame_number_) {
|
||||||
@ -134,7 +143,7 @@ class FrameDef {
|
|||||||
FrameDef();
|
FrameDef();
|
||||||
~FrameDef();
|
~FrameDef();
|
||||||
void Reset();
|
void Reset();
|
||||||
void Finalize();
|
void Complete();
|
||||||
|
|
||||||
void set_display_time_elapsed_microsecs(microsecs_t val) {
|
void set_display_time_elapsed_microsecs(microsecs_t val) {
|
||||||
display_time_elapsed_microsecs_ = val;
|
display_time_elapsed_microsecs_ = val;
|
||||||
@ -187,7 +196,7 @@ class FrameDef {
|
|||||||
auto media_components() const -> const std::vector<Object::Ref<Asset>>& {
|
auto media_components() const -> const std::vector<Object::Ref<Asset>>& {
|
||||||
return media_components_;
|
return media_components_;
|
||||||
}
|
}
|
||||||
auto tv_border() const { return tv_border_; }
|
// auto tv_border() const { return tv_border_; }
|
||||||
|
|
||||||
void set_camera_mode(CameraMode val) { camera_mode_ = val; }
|
void set_camera_mode(CameraMode val) { camera_mode_ = val; }
|
||||||
void set_rendering(bool val) { rendering_ = val; }
|
void set_rendering(bool val) { rendering_ = val; }
|
||||||
@ -204,18 +213,27 @@ class FrameDef {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// auto pixel_scale() const { return pixel_scale_; }
|
||||||
|
|
||||||
|
auto* settings() const {
|
||||||
|
assert(settings_snapshot_.Exists());
|
||||||
|
return settings_snapshot_->Get();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool needs_clear_{};
|
Object::Ref<Snapshot<GraphicsSettings>> settings_snapshot_;
|
||||||
bool rendering_{};
|
bool needs_clear_ : 1 {};
|
||||||
bool orbiting_{};
|
bool rendering_ : 1 {};
|
||||||
bool tv_border_{};
|
bool orbiting_ : 1 {};
|
||||||
bool shadow_ortho_{};
|
// bool tv_border_ : 1 {};
|
||||||
|
bool shadow_ortho_ : 1 {};
|
||||||
BenchmarkType benchmark_type_{BenchmarkType::kNone};
|
BenchmarkType benchmark_type_{BenchmarkType::kNone};
|
||||||
CameraMode camera_mode_{CameraMode::kFollow};
|
CameraMode camera_mode_{CameraMode::kFollow};
|
||||||
Vector3f cam_original_{0.0f, 0.0f, 0.0f};
|
Vector3f cam_original_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f cam_target_original_{0.0f, 0.0f, 0.0f};
|
Vector3f cam_target_original_{0.0f, 0.0f, 0.0f};
|
||||||
Vector3f shake_original_{0.0f, 0.0f, 0.0f};
|
Vector3f shake_original_{0.0f, 0.0f, 0.0f};
|
||||||
float vr_near_clip_{};
|
float vr_near_clip_{};
|
||||||
|
// float pixel_scale_{};
|
||||||
Matrix44f vr_overlay_screen_matrix_ = kMatrix44fIdentity;
|
Matrix44f vr_overlay_screen_matrix_ = kMatrix44fIdentity;
|
||||||
Matrix44f vr_overlay_screen_matrix_fixed_ = kMatrix44fIdentity;
|
Matrix44f vr_overlay_screen_matrix_fixed_ = kMatrix44fIdentity;
|
||||||
std::vector<MeshData*> mesh_data_creates_;
|
std::vector<MeshData*> mesh_data_creates_;
|
||||||
@ -245,7 +263,8 @@ class FrameDef {
|
|||||||
std::unique_ptr<RenderPass> vr_cover_pass_;
|
std::unique_ptr<RenderPass> vr_cover_pass_;
|
||||||
std::unique_ptr<RenderPass> overlay_3d_pass_;
|
std::unique_ptr<RenderPass> overlay_3d_pass_;
|
||||||
std::unique_ptr<RenderPass> blit_pass_;
|
std::unique_ptr<RenderPass> blit_pass_;
|
||||||
GraphicsQuality quality_{GraphicsQuality::kLow};
|
GraphicsQuality quality_{};
|
||||||
|
TextureQuality texture_quality_{};
|
||||||
microsecs_t app_time_microsecs_{};
|
microsecs_t app_time_microsecs_{};
|
||||||
microsecs_t display_time_microsecs_{};
|
microsecs_t display_time_microsecs_{};
|
||||||
microsecs_t display_time_elapsed_microsecs_{};
|
microsecs_t display_time_elapsed_microsecs_{};
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
#include "ballistica/base/graphics/support/graphics_client_context.h"
|
||||||
|
|
||||||
|
#include "ballistica/base/graphics/graphics_server.h"
|
||||||
|
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||||
|
|
||||||
|
namespace ballistica::base {
|
||||||
|
|
||||||
|
GraphicsClientContext::GraphicsClientContext()
|
||||||
|
: auto_graphics_quality{g_base->graphics_server->renderer()
|
||||||
|
->GetAutoGraphicsQuality()},
|
||||||
|
auto_texture_quality{
|
||||||
|
g_base->graphics_server->renderer()->GetAutoTextureQuality()},
|
||||||
|
texture_compression_types{
|
||||||
|
g_base->graphics_server->texture_compression_types()} {}
|
||||||
|
|
||||||
|
GraphicsClientContext::GraphicsClientContext(int dummy)
|
||||||
|
: auto_graphics_quality{GraphicsQuality::kLow},
|
||||||
|
auto_texture_quality{TextureQuality::kLow},
|
||||||
|
texture_compression_types{0} {}
|
||||||
|
|
||||||
|
} // namespace ballistica::base
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_
|
||||||
|
#define BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_
|
||||||
|
|
||||||
|
#include "ballistica/base/base.h"
|
||||||
|
|
||||||
|
namespace ballistica::base {
|
||||||
|
|
||||||
|
/// Represents a valid graphics setup delivered by the graphics server to
|
||||||
|
/// the logic thread. It contains various info about concrete graphics
|
||||||
|
/// settings and capabilities.
|
||||||
|
struct GraphicsClientContext {
|
||||||
|
GraphicsClientContext();
|
||||||
|
|
||||||
|
/// Special constructor to create a dummy context (used by headless builds).
|
||||||
|
explicit GraphicsClientContext(int dummy);
|
||||||
|
|
||||||
|
auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool {
|
||||||
|
return ((texture_compression_types & (0x01u << static_cast<uint32_t>(t)))
|
||||||
|
!= 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsQuality auto_graphics_quality;
|
||||||
|
TextureQuality auto_texture_quality;
|
||||||
|
uint32_t texture_compression_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ballistica::base
|
||||||
|
|
||||||
|
#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_
|
||||||
27
src/ballistica/base/graphics/support/graphics_settings.cc
Normal file
27
src/ballistica/base/graphics/support/graphics_settings.cc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
#include "ballistica/base/graphics/support/graphics_settings.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "ballistica/base/graphics/graphics.h"
|
||||||
|
#include "ballistica/base/support/app_config.h"
|
||||||
|
#include "ballistica/shared/foundation/object.h"
|
||||||
|
|
||||||
|
namespace ballistica::base {
|
||||||
|
|
||||||
|
GraphicsSettings::GraphicsSettings()
|
||||||
|
|
||||||
|
: resolution{g_base->graphics->screen_pixel_width(),
|
||||||
|
g_base->graphics->screen_pixel_height()},
|
||||||
|
resolution_virtual{g_base->graphics->screen_virtual_width(),
|
||||||
|
g_base->graphics->screen_virtual_height()},
|
||||||
|
pixel_scale{std::clamp(
|
||||||
|
g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale),
|
||||||
|
0.1f, 1.0f)},
|
||||||
|
graphics_quality{g_base->graphics->GraphicsQualityFromAppConfig()},
|
||||||
|
texture_quality{g_base->graphics->TextureQualityFromAppConfig()},
|
||||||
|
tv_border{
|
||||||
|
g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder)} {}
|
||||||
|
|
||||||
|
} // namespace ballistica::base
|
||||||
33
src/ballistica/base/graphics/support/graphics_settings.h
Normal file
33
src/ballistica/base/graphics/support/graphics_settings.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_
|
||||||
|
#define BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_
|
||||||
|
|
||||||
|
#include "ballistica/base/base.h"
|
||||||
|
#include "ballistica/shared/math/vector2f.h"
|
||||||
|
|
||||||
|
namespace ballistica::base {
|
||||||
|
|
||||||
|
/// A set of settings for graphics, covering things like screen
|
||||||
|
/// resolution, texture quality, etc. These are filled out by the
|
||||||
|
/// AppAdapter in the logic thread and passed up to the GraphicsServer
|
||||||
|
/// either through standalone calls or attached to a FrameDef. Generally
|
||||||
|
/// AppAdapters define their own subclass of this containing additional
|
||||||
|
/// settings specific to themselves or the renderer(s) they use.
|
||||||
|
struct GraphicsSettings {
|
||||||
|
GraphicsSettings();
|
||||||
|
// Each new settings instance will be assigned a unique incrementing index.
|
||||||
|
int index{-1};
|
||||||
|
|
||||||
|
// Some standard settings used by most renderers.
|
||||||
|
Vector2f resolution;
|
||||||
|
Vector2f resolution_virtual;
|
||||||
|
float pixel_scale;
|
||||||
|
GraphicsQualityRequest graphics_quality;
|
||||||
|
TextureQualityRequest texture_quality;
|
||||||
|
bool tv_border;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ballistica::base
|
||||||
|
|
||||||
|
#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_
|
||||||
@ -159,16 +159,16 @@ void Input::AnnounceConnects_() {
|
|||||||
|
|
||||||
// For the first announcement just say "X controllers detected" and don't
|
// For the first announcement just say "X controllers detected" and don't
|
||||||
// have a sound.
|
// have a sound.
|
||||||
if (first_print && g_core->GetAppTimeMillisecs() < 10000) {
|
if (first_print && g_core->GetAppTimeSeconds() < 5.0) {
|
||||||
first_print = false;
|
first_print = false;
|
||||||
|
|
||||||
// Disabling this completely for now; being more lenient with devices
|
// Disabling this completely on Android for now; we often get large
|
||||||
// allowed on Android means this will often come back with large
|
// numbers of devices there that aren't actually devices.
|
||||||
// numbers.
|
|
||||||
bool do_print{false};
|
bool do_print_initial_counts{!g_buildconfig.ostype_android()};
|
||||||
|
|
||||||
// If there's been several connected, just give a number.
|
// If there's been several connected, just give a number.
|
||||||
if (explicit_bool(do_print)) {
|
if (explicit_bool(do_print_initial_counts)) {
|
||||||
if (newly_connected_controllers_.size() > 1) {
|
if (newly_connected_controllers_.size() > 1) {
|
||||||
std::string s =
|
std::string s =
|
||||||
g_base->assets->GetResourceString("controllersDetectedText");
|
g_base->assets->GetResourceString("controllersDetectedText");
|
||||||
|
|||||||
@ -76,11 +76,11 @@ void Logic::OnAppStart() {
|
|||||||
|
|
||||||
void Logic::OnGraphicsReady() {
|
void Logic::OnGraphicsReady() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (on_initial_screen_creation_complete_called_) {
|
if (graphics_ready_) {
|
||||||
// Only want to fire this logic the first time.
|
// Only want to fire this logic the first time.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
on_initial_screen_creation_complete_called_ = true;
|
graphics_ready_ = true;
|
||||||
|
|
||||||
// Ok; graphics-server is telling us we've got a screen (or no screen in
|
// Ok; graphics-server is telling us we've got a screen (or no screen in
|
||||||
// the case of headless-mode). We use this as a cue to kick off our
|
// the case of headless-mode). We use this as a cue to kick off our
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#define BALLISTICA_BASE_LOGIC_LOGIC_H_
|
#define BALLISTICA_BASE_LOGIC_LOGIC_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ballistica/shared/foundation/object.h"
|
#include "ballistica/shared/foundation/object.h"
|
||||||
@ -118,6 +117,8 @@ class Logic {
|
|||||||
auto shutting_down() const { return shutting_down_; }
|
auto shutting_down() const { return shutting_down_; }
|
||||||
auto shutdown_completed() const { return shutdown_completed_; }
|
auto shutdown_completed() const { return shutdown_completed_; }
|
||||||
|
|
||||||
|
auto graphics_ready() const { return graphics_ready_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateDisplayTimeForFrameDraw_();
|
void UpdateDisplayTimeForFrameDraw_();
|
||||||
void UpdateDisplayTimeForHeadlessMode_();
|
void UpdateDisplayTimeForHeadlessMode_();
|
||||||
@ -127,31 +128,31 @@ class Logic {
|
|||||||
void UpdatePendingWorkTimer_();
|
void UpdatePendingWorkTimer_();
|
||||||
void StepDisplayTime_();
|
void StepDisplayTime_();
|
||||||
|
|
||||||
double display_time_{};
|
seconds_t display_time_{};
|
||||||
double display_time_increment_{1.0 / 60.0};
|
seconds_t display_time_increment_{1.0 / 60.0};
|
||||||
microsecs_t display_time_microsecs_{};
|
microsecs_t display_time_microsecs_{};
|
||||||
microsecs_t display_time_increment_microsecs_{1000000 / 60};
|
microsecs_t display_time_increment_microsecs_{1000000 / 60};
|
||||||
|
|
||||||
// GUI scheduling.
|
|
||||||
double last_display_time_update_app_time_{-1.0};
|
|
||||||
double recent_display_time_increments_[kDisplayTimeSampleCount]{};
|
|
||||||
int recent_display_time_increments_index_{-1};
|
|
||||||
|
|
||||||
// Headless scheduling.
|
// Headless scheduling.
|
||||||
Timer* headless_display_time_step_timer_{};
|
Timer* headless_display_time_step_timer_{};
|
||||||
|
|
||||||
Timer* process_pending_work_timer_{};
|
// GUI scheduling.
|
||||||
Timer* asset_prune_timer_{};
|
seconds_t last_display_time_update_app_time_{-1.0};
|
||||||
Timer* debug_timer_{};
|
seconds_t recent_display_time_increments_[kDisplayTimeSampleCount]{};
|
||||||
EventLoop* event_loop_{};
|
int recent_display_time_increments_index_{-1};
|
||||||
std::unique_ptr<TimerList> display_timers_;
|
|
||||||
bool app_bootstrapping_complete_ : 1 {};
|
bool app_bootstrapping_complete_ : 1 {};
|
||||||
bool have_pending_loads_ : 1 {};
|
bool have_pending_loads_ : 1 {};
|
||||||
bool debug_log_display_time_ : 1 {};
|
bool debug_log_display_time_ : 1 {};
|
||||||
bool applied_app_config_ : 1 {};
|
bool applied_app_config_ : 1 {};
|
||||||
bool shutting_down_ : 1 {};
|
bool shutting_down_ : 1 {};
|
||||||
bool shutdown_completed_ : 1 {};
|
bool shutdown_completed_ : 1 {};
|
||||||
bool on_initial_screen_creation_complete_called_ : 1 {};
|
bool graphics_ready_ : 1 {};
|
||||||
|
Timer* process_pending_work_timer_{};
|
||||||
|
Timer* asset_prune_timer_{};
|
||||||
|
Timer* debug_timer_{};
|
||||||
|
EventLoop* event_loop_{};
|
||||||
|
std::unique_ptr<TimerList> display_timers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica::base
|
} // namespace ballistica::base
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "ballistica/base/platform/apple/base_platform_apple.h"
|
#include "ballistica/base/platform/apple/base_platform_apple.h"
|
||||||
|
|
||||||
#if BA_XCODE_BUILD
|
#if BA_XCODE_BUILD
|
||||||
|
#include <BallisticaKit-Swift.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
@ -53,9 +54,14 @@ void BasePlatformApple::PurchaseAck(const std::string& purchase,
|
|||||||
|
|
||||||
void BasePlatformApple::DoOpenURL(const std::string& url) {
|
void BasePlatformApple::DoOpenURL(const std::string& url) {
|
||||||
#if BA_XCODE_BUILD
|
#if BA_XCODE_BUILD
|
||||||
|
#if BA_OSTYPE_MACOS
|
||||||
|
BallisticaKit::CocoaFromCppOpenURL(url);
|
||||||
|
#else
|
||||||
|
BallisticaKit::UIKitFromCppOpenURL(url);
|
||||||
|
#endif
|
||||||
// Go ahead and do this ourself. Though perhaps the default
|
// Go ahead and do this ourself. Though perhaps the default
|
||||||
// Python path would be fine.
|
// Python path would be fine.
|
||||||
AppleUtils::OpenURL(url.c_str());
|
// AppleUtils::OpenURL(url.c_str());
|
||||||
#else
|
#else
|
||||||
// Otherwise go with the default (Python webbrowser module).
|
// Otherwise go with the default (Python webbrowser module).
|
||||||
BasePlatform::DoOpenURL(url);
|
BasePlatform::DoOpenURL(url);
|
||||||
|
|||||||
@ -810,9 +810,9 @@ static PyMethodDef PySetStressTestingDef = {
|
|||||||
"(internal)",
|
"(internal)",
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------ display_log ----------------------------------
|
// -------------------------------- emit_log -----------------------------------
|
||||||
|
|
||||||
static auto PyDisplayLog(PyObject* self, PyObject* args, PyObject* keywds)
|
static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
|
||||||
-> PyObject* {
|
-> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
static const char* kwlist[] = {"name", "level", "message", nullptr};
|
static const char* kwlist[] = {"name", "level", "message", nullptr};
|
||||||
@ -839,25 +839,25 @@ static auto PyDisplayLog(PyObject* self, PyObject* args, PyObject* keywds)
|
|||||||
level = LogLevel::kCritical;
|
level = LogLevel::kCritical;
|
||||||
} else {
|
} else {
|
||||||
// Assume we should avoid Log() calls here since it could infinite loop.
|
// Assume we should avoid Log() calls here since it could infinite loop.
|
||||||
fprintf(stderr, "Invalid log level to display_log(): %s\n", levelstr);
|
fprintf(stderr, "Invalid log level to emit_log(): %s\n", levelstr);
|
||||||
level = LogLevel::kInfo;
|
level = LogLevel::kInfo;
|
||||||
}
|
}
|
||||||
Logging::DisplayLog(name, level, message);
|
Logging::EmitLog(name, level, message);
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef PyDisplayLogDef = {
|
static PyMethodDef PyEmitLogDef = {
|
||||||
"display_log", // name
|
"emit_log", // name
|
||||||
(PyCFunction)PyDisplayLog, // method
|
(PyCFunction)PyEmitLog, // method
|
||||||
METH_VARARGS | METH_KEYWORDS, // flags
|
METH_VARARGS | METH_KEYWORDS, // flags
|
||||||
|
|
||||||
"display_log(name: str, level: str, message: str) -> None\n"
|
"emit_log(name: str, level: str, message: str) -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"(internal)\n"
|
"(internal)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Sends a log message to the in-game console and any per-platform\n"
|
"Sends a log message to the in-app console and any per-platform\n"
|
||||||
"log destinations (Android log, etc.). This generally is not called\n"
|
"log destinations (Android log, etc.). This generally is not called\n"
|
||||||
"directly and should instead be fed Python logging output.",
|
"directly and should instead be fed Python logging output.",
|
||||||
};
|
};
|
||||||
@ -1654,7 +1654,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
PyAppNameUpperDef,
|
PyAppNameUpperDef,
|
||||||
PyIsXCodeBuildDef,
|
PyIsXCodeBuildDef,
|
||||||
PyCanDisplayFullUnicodeDef,
|
PyCanDisplayFullUnicodeDef,
|
||||||
PyDisplayLogDef,
|
PyEmitLogDef,
|
||||||
PyV1CloudLogDef,
|
PyV1CloudLogDef,
|
||||||
PySetStressTestingDef,
|
PySetStressTestingDef,
|
||||||
PyEnvDef,
|
PyEnvDef,
|
||||||
|
|||||||
@ -348,13 +348,14 @@ static PyMethodDef PySafeColorDef = {
|
|||||||
|
|
||||||
static auto PyGetMaxGraphicsQuality(PyObject* self) -> PyObject* {
|
static auto PyGetMaxGraphicsQuality(PyObject* self) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
if (g_base->graphics
|
// if (g_base->graphics
|
||||||
&& g_base->graphics->has_supports_high_quality_graphics_value()
|
// && g_base->graphics->has_supports_high_quality_graphics_value()
|
||||||
&& g_base->graphics->supports_high_quality_graphics()) {
|
// && g_base->graphics->supports_high_quality_graphics()) {
|
||||||
return Py_BuildValue("s", "High");
|
// return Py_BuildValue("s", "High");
|
||||||
} else {
|
// } else {
|
||||||
return Py_BuildValue("s", "Medium");
|
// return Py_BuildValue("s", "Medium");
|
||||||
}
|
// }
|
||||||
|
return Py_BuildValue("s", "Higher");
|
||||||
BA_PYTHON_CATCH;
|
BA_PYTHON_CATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -147,17 +147,17 @@ auto CorePlatformApple::IsRunningOnDesktop() -> bool {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatformApple::DisplayLog(const std::string& name, LogLevel level,
|
void CorePlatformApple::EmitPlatformLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg) {
|
const std::string& msg) {
|
||||||
#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD
|
#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD
|
||||||
|
|
||||||
// HMM: do we want to use proper logging APIs here or simple printing?
|
// HMM: do we want to use proper logging APIs here or simple printing?
|
||||||
// base::AppleUtils::NSLogStr(msg);
|
// base::AppleUtils::NSLogStr(msg);
|
||||||
CorePlatform::DisplayLog(name, level, msg);
|
CorePlatform::EmitPlatformLog(name, level, msg);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Fall back to default handler...
|
// Fall back to default handler...
|
||||||
CorePlatform::DisplayLog(name, level, msg);
|
CorePlatform::EmitPlatformLog(name, level, msg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,8 +26,8 @@ class CorePlatformApple : public CorePlatform {
|
|||||||
auto DoHasTouchScreen() -> bool override;
|
auto DoHasTouchScreen() -> bool override;
|
||||||
auto GetDefaultUIScale() -> UIScale override;
|
auto GetDefaultUIScale() -> UIScale override;
|
||||||
auto IsRunningOnDesktop() -> bool override;
|
auto IsRunningOnDesktop() -> bool override;
|
||||||
void DisplayLog(const std::string& name, LogLevel level,
|
void EmitPlatformLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg) override;
|
const std::string& msg) override;
|
||||||
void GetTextBoundsAndWidth(const std::string& text, Rect* r,
|
void GetTextBoundsAndWidth(const std::string& text, Rect* r,
|
||||||
float* width) override;
|
float* width) override;
|
||||||
void FreeTextTexture(void* tex) override;
|
void FreeTextTexture(void* tex) override;
|
||||||
|
|||||||
@ -465,12 +465,17 @@ auto CorePlatform::IsRunningOnDesktop() -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::SleepMillisecs(millisecs_t ms) {
|
void CorePlatform::SleepSeconds(seconds_t duration) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::microseconds(static_cast<microsecs_t>(duration * 1000000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::SleepMicrosecs(millisecs_t ms) {
|
void CorePlatform::SleepMillisecs(millisecs_t duration) {
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(ms));
|
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CorePlatform::SleepMicrosecs(millisecs_t duration) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@ -481,8 +486,8 @@ auto CorePlatform::GetDefaultUIScale() -> UIScale {
|
|||||||
return UIScale::kLarge;
|
return UIScale::kLarge;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorePlatform::DisplayLog(const std::string& name, LogLevel level,
|
void CorePlatform::EmitPlatformLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg) {
|
const std::string& msg) {
|
||||||
// Do nothing by default.
|
// Do nothing by default.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -99,8 +99,8 @@ class CorePlatform {
|
|||||||
/// Display a message to any default log for the platform (android log,
|
/// Display a message to any default log for the platform (android log,
|
||||||
/// etc.) Note that this can be called from any thread. Default
|
/// etc.) Note that this can be called from any thread. Default
|
||||||
/// implementation does nothing.
|
/// implementation does nothing.
|
||||||
virtual void DisplayLog(const std::string& name, LogLevel level,
|
virtual void EmitPlatformLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg);
|
const std::string& msg);
|
||||||
|
|
||||||
#pragma mark ENVIRONMENT -------------------------------------------------------
|
#pragma mark ENVIRONMENT -------------------------------------------------------
|
||||||
|
|
||||||
@ -381,9 +381,9 @@ class CorePlatform {
|
|||||||
/// to not go backwards.
|
/// to not go backwards.
|
||||||
static auto GetCurrentWholeSeconds() -> int64_t;
|
static auto GetCurrentWholeSeconds() -> int64_t;
|
||||||
|
|
||||||
static void SleepMillisecs(millisecs_t ms);
|
static void SleepSeconds(seconds_t duration);
|
||||||
|
static void SleepMillisecs(millisecs_t duration);
|
||||||
static void SleepMicrosecs(microsecs_t ms);
|
static void SleepMicrosecs(microsecs_t duration);
|
||||||
|
|
||||||
/// Given a C++ symbol, attempt to return a pretty one.
|
/// Given a C++ symbol, attempt to return a pretty one.
|
||||||
virtual auto DemangleCXXSymbol(const std::string& s) -> std::string;
|
virtual auto DemangleCXXSymbol(const std::string& s) -> std::string;
|
||||||
|
|||||||
@ -827,11 +827,12 @@ std::string CorePlatformWindows::DoGetDeviceName() {
|
|||||||
|
|
||||||
bool CorePlatformWindows::DoHasTouchScreen() { return false; }
|
bool CorePlatformWindows::DoHasTouchScreen() { return false; }
|
||||||
|
|
||||||
void CorePlatformWindows::DisplayLog(const std::string& name, LogLevel level,
|
void CorePlatformWindows::EmitPlatformLog(const std::string& name,
|
||||||
const std::string& msg) {
|
LogLevel level,
|
||||||
|
const std::string& msg) {
|
||||||
// if (have_stdin_stdout_) {
|
// if (have_stdin_stdout_) {
|
||||||
// // On headless builds we use default handler (simple stdout).
|
// // On headless builds we use default handler (simple stdout).
|
||||||
// return CorePlatform::DisplayLog(msg);
|
// return CorePlatform::EmitPlatformLog(msg);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Also spit this out as a debug-string for when running from msvc.
|
// Also spit this out as a debug-string for when running from msvc.
|
||||||
|
|||||||
@ -41,8 +41,8 @@ class CorePlatformWindows : public CorePlatform {
|
|||||||
auto GetLocale() -> std::string override;
|
auto GetLocale() -> std::string override;
|
||||||
auto DoGetDeviceName() -> std::string override;
|
auto DoGetDeviceName() -> std::string override;
|
||||||
auto DoHasTouchScreen() -> bool override;
|
auto DoHasTouchScreen() -> bool override;
|
||||||
void DisplayLog(const std::string& name, LogLevel level,
|
void EmitPlatformLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg) override;
|
const std::string& msg) override;
|
||||||
void SetEnv(const std::string& name, const std::string& value) override;
|
void SetEnv(const std::string& name, const std::string& value) override;
|
||||||
auto GetEnv(const std::string& name) -> std::optional<std::string> override;
|
auto GetEnv(const std::string& name) -> std::optional<std::string> override;
|
||||||
auto GetIsStdinATerminal() -> bool override;
|
auto GetIsStdinATerminal() -> bool override;
|
||||||
|
|||||||
@ -307,8 +307,8 @@ void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) {
|
|||||||
"CorePython::LoggingCall() called before Python"
|
"CorePython::LoggingCall() called before Python"
|
||||||
" logging available."};
|
" logging available."};
|
||||||
if (g_core->platform) {
|
if (g_core->platform) {
|
||||||
g_core->platform->DisplayLog("root", LogLevel::kError, errmsg);
|
g_core->platform->EmitPlatformLog("root", LogLevel::kError, errmsg);
|
||||||
g_core->platform->DisplayLog("root", loglevel, msg);
|
g_core->platform->EmitPlatformLog("root", loglevel, msg);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "%s\n%s\n", errmsg, msg.c_str());
|
fprintf(stderr, "%s\n%s\n", errmsg, msg.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ class CorePython {
|
|||||||
|
|
||||||
/// Calls Python logging function (logging.error, logging.warning, etc.)
|
/// Calls Python logging function (logging.error, logging.warning, etc.)
|
||||||
/// Can be called from any thread at any time. If called before Python
|
/// Can be called from any thread at any time. If called before Python
|
||||||
/// logging is available, logs locally using Logging::DisplayLog()
|
/// logging is available, logs locally using Logging::EmitPlatformLog()
|
||||||
/// (with an added warning).
|
/// (with an added warning).
|
||||||
void LoggingCall(LogLevel loglevel, const std::string& msg);
|
void LoggingCall(LogLevel loglevel, const std::string& msg);
|
||||||
void ImportPythonObjs();
|
void ImportPythonObjs();
|
||||||
|
|||||||
@ -12,11 +12,12 @@
|
|||||||
|
|
||||||
namespace ballistica::scene_v1 {
|
namespace ballistica::scene_v1 {
|
||||||
|
|
||||||
// Stores info about an occurring collision.
|
/// Stores info about an occurring collision.
|
||||||
// Note than just because a collision exists between two parts doesn't mean
|
///
|
||||||
// they're physically colliding in the simulation. It is just a shortcut to
|
/// Note than just because a collision exists between two parts doesn't mean
|
||||||
// determine what behavior, if any, exists between two parts which are currently
|
/// they're physically colliding in the simulation. It is just a shortcut to
|
||||||
// overlapping in the simulation.
|
/// determine what behavior, if any, exists between two parts which are
|
||||||
|
/// currently overlapping in the simulation.
|
||||||
class Collision : public Object {
|
class Collision : public Object {
|
||||||
public:
|
public:
|
||||||
explicit Collision(Scene* scene) : src_context(scene), dst_context(scene) {}
|
explicit Collision(Scene* scene) : src_context(scene), dst_context(scene) {}
|
||||||
|
|||||||
@ -66,77 +66,77 @@ void do_dBodyGetLocalFeedback(dBodyID b, dReal px, dReal py, dReal pz,
|
|||||||
|
|
||||||
// Stores info about a collision needing a reset
|
// Stores info about a collision needing a reset
|
||||||
// (used when parts change materials).
|
// (used when parts change materials).
|
||||||
class Dynamics::CollisionReset {
|
class Dynamics::CollisionReset_ {
|
||||||
public:
|
public:
|
||||||
int node1;
|
int node1;
|
||||||
int node2;
|
int node2;
|
||||||
int part1;
|
int part1;
|
||||||
int part2;
|
int part2;
|
||||||
CollisionReset(int node1_in, int part1_in, int node2_in, int part2_in)
|
CollisionReset_(int node1_in, int part1_in, int node2_in, int part2_in)
|
||||||
: node1(node1_in), node2(node2_in), part1(part1_in), part2(part2_in) {}
|
: node1(node1_in), node2(node2_in), part1(part1_in), part2(part2_in) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamics::CollisionEvent {
|
class Dynamics::CollisionEvent_ {
|
||||||
public:
|
public:
|
||||||
Object::Ref<MaterialAction> action;
|
Object::Ref<MaterialAction> action;
|
||||||
Object::Ref<Collision> collision;
|
Object::Ref<Collision> collision;
|
||||||
Object::WeakRef<Node> node1; // first event node
|
Object::WeakRef<Node> node1; // first event node
|
||||||
Object::WeakRef<Node> node2; // second event node
|
Object::WeakRef<Node> node2; // second event node
|
||||||
CollisionEvent(Node* node1_in, Node* node2_in,
|
CollisionEvent_(Node* node1_in, Node* node2_in,
|
||||||
const Object::Ref<MaterialAction>& action_in,
|
const Object::Ref<MaterialAction>& action_in,
|
||||||
const Object::Ref<Collision>& collision_in)
|
const Object::Ref<Collision>& collision_in)
|
||||||
: node1(node1_in),
|
: node1(node1_in),
|
||||||
node2(node2_in),
|
node2(node2_in),
|
||||||
action(action_in),
|
action(action_in),
|
||||||
collision(collision_in) {}
|
collision(collision_in) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamics::SrcPartCollideMap {
|
class Dynamics::SrcPartCollideMap_ {
|
||||||
public:
|
public:
|
||||||
std::unordered_map<int, Object::Ref<Collision> > dst_part_collisions;
|
std::unordered_map<int, Object::Ref<Collision> > dst_part_collisions;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamics::DstNodeCollideMap {
|
class Dynamics::DstNodeCollideMap_ {
|
||||||
public:
|
public:
|
||||||
std::unordered_map<int, SrcPartCollideMap> src_parts;
|
std::unordered_map<int, SrcPartCollideMap_> src_parts;
|
||||||
int collideDisabled;
|
int collideDisabled;
|
||||||
DstNodeCollideMap() : collideDisabled(0) {}
|
DstNodeCollideMap_() : collideDisabled(0) {}
|
||||||
~DstNodeCollideMap() = default;
|
~DstNodeCollideMap_() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamics::SrcNodeCollideMap {
|
class Dynamics::SrcNodeCollideMap_ {
|
||||||
public:
|
public:
|
||||||
std::unordered_map<int64_t, DstNodeCollideMap> dst_nodes;
|
std::unordered_map<int64_t, DstNodeCollideMap_> dst_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Dynamics::Impl {
|
class Dynamics::Impl_ {
|
||||||
public:
|
public:
|
||||||
explicit Impl(Dynamics* dynamics) : dynamics_(dynamics) {}
|
explicit Impl_(Dynamics* dynamics) : dynamics_(dynamics) {}
|
||||||
|
|
||||||
// NOTE: we need to implement this here in an Impl class because
|
// NOTE: we need to implement this here in an Impl class because
|
||||||
// gcc currently chokes on unordered_maps with forward-declared types,
|
// gcc currently chokes on unordered_maps with forward-declared types,
|
||||||
// so we can't have this in our header without pushing all our map/collision
|
// so we can't have this in our header without pushing all our map/collision
|
||||||
// types there too.
|
// types there too.
|
||||||
void HandleDisconnect(
|
void HandleDisconnect(
|
||||||
const std::unordered_map<int64_t, Dynamics::SrcNodeCollideMap>::iterator&
|
const std::unordered_map<int64_t, Dynamics::SrcNodeCollideMap_>::iterator&
|
||||||
i,
|
i,
|
||||||
const std::unordered_map<int64_t, Dynamics::DstNodeCollideMap>::iterator&
|
const std::unordered_map<int64_t, Dynamics::DstNodeCollideMap_>::iterator&
|
||||||
j,
|
j,
|
||||||
const std::unordered_map<int, SrcPartCollideMap>::iterator& k,
|
const std::unordered_map<int, SrcPartCollideMap_>::iterator& k,
|
||||||
const std::unordered_map<int, Object::Ref<Collision> >::iterator& l);
|
const std::unordered_map<int, Object::Ref<Collision> >::iterator& l);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Dynamics* dynamics_{};
|
Dynamics* dynamics_{};
|
||||||
// Contains in-progress collisions for current nodes.
|
// Contains in-progress collisions for current nodes.
|
||||||
std::unordered_map<int64_t, SrcNodeCollideMap> node_collisions_;
|
std::unordered_map<int64_t, SrcNodeCollideMap_> node_collisions_;
|
||||||
friend class Dynamics;
|
friend class Dynamics;
|
||||||
};
|
};
|
||||||
|
|
||||||
Dynamics::Dynamics(Scene* scene_in)
|
Dynamics::Dynamics(Scene* scene_in)
|
||||||
: scene_(scene_in),
|
: scene_(scene_in),
|
||||||
collision_cache_(new base::CollisionCache()),
|
collision_cache_(new base::CollisionCache()),
|
||||||
impl_(std::make_unique<Impl>(this)) {
|
impl_(std::make_unique<Impl_>(this)) {
|
||||||
ResetODE();
|
ResetODE_();
|
||||||
}
|
}
|
||||||
|
|
||||||
Dynamics::~Dynamics() {
|
Dynamics::~Dynamics() {
|
||||||
@ -145,7 +145,7 @@ Dynamics::~Dynamics() {
|
|||||||
"Dynamics going down within Process() call;"
|
"Dynamics going down within Process() call;"
|
||||||
" should not happen.");
|
" should not happen.");
|
||||||
}
|
}
|
||||||
ShutdownODE();
|
ShutdownODE_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::Draw(base::FrameDef* frame_def) {
|
void Dynamics::Draw(base::FrameDef* frame_def) {
|
||||||
@ -203,7 +203,7 @@ void Dynamics::RemoveTrimesh(dGeomID g) {
|
|||||||
throw Exception("trimesh not found");
|
throw Exception("trimesh not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Dynamics::AreColliding(const Part& p1_in, const Part& p2_in) -> bool {
|
auto Dynamics::AreColliding_(const Part& p1_in, const Part& p2_in) -> bool {
|
||||||
const Part* p1;
|
const Part* p1;
|
||||||
const Part* p2;
|
const Part* p2;
|
||||||
if (IsInStoreOrder(p1_in.node()->id(), p1_in.id(), p2_in.node()->id(),
|
if (IsInStoreOrder(p1_in.node()->id(), p1_in.id(), p2_in.node()->id(),
|
||||||
@ -279,7 +279,7 @@ auto Dynamics::GetCollision(Part* p1_in, Part* p2_in, MaterialContext** cc1,
|
|||||||
p2->ApplyMaterials(*cc2, p2, p1);
|
p2->ApplyMaterials(*cc2, p2, p1);
|
||||||
|
|
||||||
// If either disabled collisions between these two nodes, store that.
|
// If either disabled collisions between these two nodes, store that.
|
||||||
DstNodeCollideMap* dncm =
|
DstNodeCollideMap_* dncm =
|
||||||
&impl_->node_collisions_[p1->node()->id()].dst_nodes[p2->node()->id()];
|
&impl_->node_collisions_[p1->node()->id()].dst_nodes[p2->node()->id()];
|
||||||
if (!(*cc1)->node_collide || !(*cc2)->node_collide) {
|
if (!(*cc1)->node_collide || !(*cc2)->node_collide) {
|
||||||
dncm->collideDisabled = true;
|
dncm->collideDisabled = true;
|
||||||
@ -319,10 +319,12 @@ auto Dynamics::GetCollision(Part* p1_in, Part* p2_in, MaterialContext** cc1,
|
|||||||
return &(*(i.first->second));
|
return &(*(i.first->second));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::Impl::HandleDisconnect(
|
void Dynamics::Impl_::HandleDisconnect(
|
||||||
const std::unordered_map<int64_t, Dynamics::SrcNodeCollideMap>::iterator& i,
|
const std::unordered_map<int64_t, Dynamics::SrcNodeCollideMap_>::iterator&
|
||||||
const std::unordered_map<int64_t, Dynamics::DstNodeCollideMap>::iterator& j,
|
i,
|
||||||
const std::unordered_map<int, SrcPartCollideMap>::iterator& k,
|
const std::unordered_map<int64_t, Dynamics::DstNodeCollideMap_>::iterator&
|
||||||
|
j,
|
||||||
|
const std::unordered_map<int, SrcPartCollideMap_>::iterator& k,
|
||||||
const std::unordered_map<int, Object::Ref<Collision> >::iterator& l) {
|
const std::unordered_map<int, Object::Ref<Collision> >::iterator& l) {
|
||||||
// Handle disconnect equivalents if they were colliding.
|
// Handle disconnect equivalents if they were colliding.
|
||||||
if (l->second->collide) {
|
if (l->second->collide) {
|
||||||
@ -367,7 +369,7 @@ void Dynamics::Impl::HandleDisconnect(
|
|||||||
k->second.dst_part_collisions.erase(l);
|
k->second.dst_part_collisions.erase(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::ProcessCollisions() {
|
void Dynamics::ProcessCollision_() {
|
||||||
processing_collisions_ = true;
|
processing_collisions_ = true;
|
||||||
|
|
||||||
collision_count_ = 0;
|
collision_count_ = 0;
|
||||||
@ -441,10 +443,10 @@ void Dynamics::ProcessCollisions() {
|
|||||||
// Process all standard collisions. This will trigger our callback which
|
// Process all standard collisions. This will trigger our callback which
|
||||||
// do the real work (add collisions to list, store commands to be
|
// do the real work (add collisions to list, store commands to be
|
||||||
// called, etc).
|
// called, etc).
|
||||||
dSpaceCollide(ode_space_, this, &DoCollideCallback);
|
dSpaceCollide(ode_space_, this, &DoCollideCallback_);
|
||||||
|
|
||||||
// Collide our trimeshes against everything.
|
// Collide our trimeshes against everything.
|
||||||
collision_cache_->CollideAgainstSpace(ode_space_, this, &DoCollideCallback);
|
collision_cache_->CollideAgainstSpace(ode_space_, this, &DoCollideCallback_);
|
||||||
|
|
||||||
// Do a bit of precalc each cycle.
|
// Do a bit of precalc each cycle.
|
||||||
collision_cache_->Precalc();
|
collision_cache_->Precalc();
|
||||||
@ -453,9 +455,9 @@ void Dynamics::ProcessCollisions() {
|
|||||||
// setting parts' currently-colliding-with lists
|
// setting parts' currently-colliding-with lists
|
||||||
// based on current info,
|
// based on current info,
|
||||||
// removing unclaimed collisions and empty groups.
|
// removing unclaimed collisions and empty groups.
|
||||||
std::unordered_map<int64_t, SrcNodeCollideMap>::iterator i_next;
|
std::unordered_map<int64_t, SrcNodeCollideMap_>::iterator i_next;
|
||||||
std::unordered_map<int64_t, DstNodeCollideMap>::iterator j_next;
|
std::unordered_map<int64_t, DstNodeCollideMap_>::iterator j_next;
|
||||||
std::unordered_map<int, SrcPartCollideMap>::iterator k_next;
|
std::unordered_map<int, SrcPartCollideMap_>::iterator k_next;
|
||||||
std::unordered_map<int, Object::Ref<Collision> >::iterator l_next;
|
std::unordered_map<int, Object::Ref<Collision> >::iterator l_next;
|
||||||
for (auto i = impl_->node_collisions_.begin();
|
for (auto i = impl_->node_collisions_.begin();
|
||||||
i != impl_->node_collisions_.end(); i = i_next) {
|
i != impl_->node_collisions_.end(); i = i_next) {
|
||||||
@ -507,26 +509,26 @@ void Dynamics::ProcessCollisions() {
|
|||||||
collision_events_.clear();
|
collision_events_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::process() {
|
void Dynamics::Process() {
|
||||||
in_process_ = true;
|
in_process_ = true;
|
||||||
// Update this once so we can recycle results.
|
// Update this once so we can recycle results.
|
||||||
real_time_ = g_core->GetAppTimeMillisecs();
|
real_time_ = g_core->GetAppTimeMillisecs();
|
||||||
ProcessCollisions();
|
ProcessCollision_();
|
||||||
dWorldQuickStep(ode_world_, kGameStepSeconds);
|
dWorldQuickStep(ode_world_, kGameStepSeconds);
|
||||||
dJointGroupEmpty(ode_contact_group_);
|
dJointGroupEmpty(ode_contact_group_);
|
||||||
in_process_ = false;
|
in_process_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::DoCollideCallback(void* data, dGeomID o1, dGeomID o2) {
|
void Dynamics::DoCollideCallback_(void* data, dGeomID o1, dGeomID o2) {
|
||||||
auto* d = static_cast<Dynamics*>(data);
|
auto* d = static_cast<Dynamics*>(data);
|
||||||
d->CollideCallback(o1, o2);
|
d->CollideCallback_(o1, o2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run collisions for everything. Store any callbacks that will need to be made
|
// Run collisions for everything. Store any callbacks that will need to be made
|
||||||
// and run them after all collision constraints are made.
|
// and run them after all collision constraints are made.
|
||||||
// This way we know all bodies and their associated nodes, etc are valid
|
// This way we know all bodies and their associated nodes, etc are valid
|
||||||
// throughout collision processing.
|
// throughout collision processing.
|
||||||
void Dynamics::CollideCallback(dGeomID o1, dGeomID o2) {
|
void Dynamics::CollideCallback_(dGeomID o1, dGeomID o2) {
|
||||||
dBodyID b1 = dGeomGetBody(o1);
|
dBodyID b1 = dGeomGetBody(o1);
|
||||||
dBodyID b2 = dGeomGetBody(o2);
|
dBodyID b2 = dGeomGetBody(o2);
|
||||||
|
|
||||||
@ -1103,7 +1105,7 @@ void Dynamics::CollideCallback(dGeomID o1, dGeomID o2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::ShutdownODE() {
|
void Dynamics::ShutdownODE_() {
|
||||||
if (ode_space_) {
|
if (ode_space_) {
|
||||||
dSpaceDestroy(ode_space_);
|
dSpaceDestroy(ode_space_);
|
||||||
ode_space_ = nullptr;
|
ode_space_ = nullptr;
|
||||||
@ -1118,8 +1120,8 @@ void Dynamics::ShutdownODE() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dynamics::ResetODE() {
|
void Dynamics::ResetODE_() {
|
||||||
ShutdownODE();
|
ShutdownODE_();
|
||||||
ode_world_ = dWorldCreate();
|
ode_world_ = dWorldCreate();
|
||||||
assert(ode_world_);
|
assert(ode_world_);
|
||||||
dWorldSetGravity(ode_world_, 0, -20, 0);
|
dWorldSetGravity(ode_world_, 0, -20, 0);
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#define BALLISTICA_SCENE_V1_DYNAMICS_DYNAMICS_H_
|
#define BALLISTICA_SCENE_V1_DYNAMICS_DYNAMICS_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ballistica/base/base.h"
|
#include "ballistica/base/base.h"
|
||||||
@ -16,12 +15,12 @@ namespace ballistica::scene_v1 {
|
|||||||
|
|
||||||
class Dynamics : public Object {
|
class Dynamics : public Object {
|
||||||
public:
|
public:
|
||||||
explicit Dynamics(Scene* scene_in);
|
explicit Dynamics(Scene* scene);
|
||||||
~Dynamics() override;
|
~Dynamics() override;
|
||||||
void Draw(base::FrameDef* frame_def); // Draw any debug stuff, etc.
|
void Draw(base::FrameDef* frame_def); // Draw any debug stuff, etc.
|
||||||
auto ode_world() -> dWorldID { return ode_world_; }
|
auto ode_world() -> dWorldID { return ode_world_; }
|
||||||
auto getContactGroup() -> dJointGroupID { return ode_contact_group_; }
|
auto ode_contact_group() -> dJointGroupID { return ode_contact_group_; }
|
||||||
auto space() -> dSpaceID { return ode_space_; }
|
auto ode_space() -> dSpaceID { return ode_space_; }
|
||||||
|
|
||||||
// Discontinues a collision. Used by parts when changing materials
|
// Discontinues a collision. Used by parts when changing materials
|
||||||
// so that new collisions may enter effect.
|
// so that new collisions may enter effect.
|
||||||
@ -37,6 +36,7 @@ class Dynamics : public Object {
|
|||||||
: active_collide_src_node_)
|
: active_collide_src_node_)
|
||||||
.Get();
|
.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by collision callbacks - internal.
|
// Used by collision callbacks - internal.
|
||||||
auto GetActiveCollideDstNode() -> Node* {
|
auto GetActiveCollideDstNode() -> Node* {
|
||||||
assert(active_collision_);
|
assert(active_collision_);
|
||||||
@ -49,19 +49,19 @@ class Dynamics : public Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Used by collide message handlers.
|
// Used by collide message handlers.
|
||||||
void set_collide_message_state(bool inCollideMessageIn,
|
void set_collide_message_state(bool in_collide_message,
|
||||||
bool target_other_in = false) {
|
bool target_other = false) {
|
||||||
in_collide_message_ = inCollideMessageIn;
|
in_collide_message_ = in_collide_message;
|
||||||
collide_message_reverse_order_ = target_other_in;
|
collide_message_reverse_order_ = target_other;
|
||||||
}
|
}
|
||||||
auto in_collide_message() const -> bool { return in_collide_message_; }
|
auto in_collide_message() const { return in_collide_message_; }
|
||||||
void process();
|
void Process();
|
||||||
void increment_skid_sound_count() { skid_sound_count_++; }
|
void IncrementSkidSoundCount() { skid_sound_count_++; }
|
||||||
void decrement_skid_sound_count() { skid_sound_count_--; }
|
void DecrementSkidSoundCount() { skid_sound_count_--; }
|
||||||
auto skid_sound_count() const -> int { return skid_sound_count_; }
|
auto skid_sound_count() const { return skid_sound_count_; }
|
||||||
void incrementRollSoundCount() { roll_sound_count_++; }
|
void IncrementRollSoundCount() { roll_sound_count_++; }
|
||||||
void decrement_roll_sound_count() { roll_sound_count_--; }
|
void DecrementRollSoundCount() { roll_sound_count_--; }
|
||||||
auto getRollSoundCount() const -> int { return roll_sound_count_; }
|
auto roll_sound_count() const { return roll_sound_count_; }
|
||||||
|
|
||||||
// We do some fancy collision testing stuff for trimeshes instead
|
// We do some fancy collision testing stuff for trimeshes instead
|
||||||
// of going through regular ODE space collision testing.. so we have
|
// of going through regular ODE space collision testing.. so we have
|
||||||
@ -69,55 +69,52 @@ class Dynamics : public Object {
|
|||||||
void AddTrimesh(dGeomID g);
|
void AddTrimesh(dGeomID g);
|
||||||
void RemoveTrimesh(dGeomID g);
|
void RemoveTrimesh(dGeomID g);
|
||||||
|
|
||||||
auto collision_count() const -> int { return collision_count_; }
|
auto collision_count() const { return collision_count_; }
|
||||||
auto process_real_time() const -> millisecs_t { return real_time_; }
|
auto process_real_time() const { return real_time_; }
|
||||||
auto last_impact_sound_time() const -> millisecs_t {
|
auto last_impact_sound_time() const { return last_impact_sound_time_; }
|
||||||
return last_impact_sound_time_;
|
auto in_process() const { return in_process_; }
|
||||||
}
|
|
||||||
auto in_process() const -> bool { return in_process_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto AreColliding(const Part& p1, const Part& p2) -> bool;
|
auto AreColliding_(const Part& p1, const Part& p2) -> bool;
|
||||||
class SrcNodeCollideMap;
|
class SrcNodeCollideMap_;
|
||||||
class DstNodeCollideMap;
|
class DstNodeCollideMap_;
|
||||||
class SrcPartCollideMap;
|
class SrcPartCollideMap_;
|
||||||
class CollisionEvent;
|
class CollisionEvent_;
|
||||||
class CollisionReset;
|
class CollisionReset_;
|
||||||
class Impl;
|
class Impl_;
|
||||||
std::vector<CollisionReset> collision_resets_;
|
std::vector<CollisionReset_> collision_resets_;
|
||||||
|
|
||||||
// Return a collision object between these two parts,
|
// Return a collision object between these two parts,
|
||||||
// creating a new one if need be.
|
// creating a new one if need be.
|
||||||
auto GetCollision(Part* p1, Part* p2, MaterialContext** cc1,
|
auto GetCollision(Part* p1, Part* p2, MaterialContext** cc1,
|
||||||
MaterialContext** cc2) -> Collision*;
|
MaterialContext** cc2) -> Collision*;
|
||||||
|
|
||||||
std::vector<CollisionEvent> collision_events_;
|
std::vector<CollisionEvent_> collision_events_;
|
||||||
void ResetODE();
|
void ResetODE_();
|
||||||
void ShutdownODE();
|
void ShutdownODE_();
|
||||||
static void DoCollideCallback(void* data, dGeomID o1, dGeomID o2);
|
static void DoCollideCallback_(void* data, dGeomID o1, dGeomID o2);
|
||||||
void CollideCallback(dGeomID o1, dGeomID o2);
|
void CollideCallback_(dGeomID o1, dGeomID o2);
|
||||||
void ProcessCollisions();
|
void ProcessCollision_();
|
||||||
|
|
||||||
std::unique_ptr<Impl> impl_;
|
int skid_sound_count_{};
|
||||||
bool processing_collisions_{};
|
int roll_sound_count_{};
|
||||||
|
int collision_count_{};
|
||||||
|
bool in_process_ : 1 {};
|
||||||
|
bool in_collide_message_ : 1 {};
|
||||||
|
bool collide_message_reverse_order_ : 1 {};
|
||||||
|
bool processing_collisions_ : 1 {};
|
||||||
dWorldID ode_world_{};
|
dWorldID ode_world_{};
|
||||||
dJointGroupID ode_contact_group_{};
|
dJointGroupID ode_contact_group_{};
|
||||||
dSpaceID ode_space_{};
|
dSpaceID ode_space_{};
|
||||||
millisecs_t real_time_{};
|
millisecs_t real_time_{};
|
||||||
bool in_process_{};
|
|
||||||
std::vector<dGeomID> trimeshes_;
|
|
||||||
millisecs_t last_impact_sound_time_{};
|
millisecs_t last_impact_sound_time_{};
|
||||||
int skid_sound_count_{};
|
|
||||||
int roll_sound_count_{};
|
|
||||||
int collision_count_{};
|
|
||||||
Scene* scene_{};
|
Scene* scene_{};
|
||||||
bool in_collide_message_{};
|
|
||||||
bool collide_message_reverse_order_{};
|
|
||||||
Collision* active_collision_{};
|
Collision* active_collision_{};
|
||||||
Object::WeakRef<Node> active_collide_src_node_;
|
Object::WeakRef<Node> active_collide_src_node_;
|
||||||
Object::WeakRef<Node> active_collide_dst_node_;
|
Object::WeakRef<Node> active_collide_dst_node_;
|
||||||
|
std::vector<dGeomID> trimeshes_;
|
||||||
|
std::unique_ptr<Impl_> impl_;
|
||||||
std::unique_ptr<base::CollisionCache> collision_cache_;
|
std::unique_ptr<base::CollisionCache> collision_cache_;
|
||||||
friend class Impl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica::scene_v1
|
} // namespace ballistica::scene_v1
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ballistica/scene_v1/dynamics/material/impact_sound_material_action.h"
|
#include "ballistica/scene_v1/dynamics/material/impact_sound_material_action.h"
|
||||||
|
|
||||||
#include "ballistica/base/graphics/graphics_server.h"
|
#include "ballistica/base/audio/audio.h"
|
||||||
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
||||||
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
||||||
#include "ballistica/scene_v1/support/client_session.h"
|
#include "ballistica/scene_v1/support/client_session.h"
|
||||||
@ -50,10 +50,8 @@ void ImpactSoundMaterialAction::Apply(MaterialContext* context,
|
|||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
|
|
||||||
// For now lets avoid this in low-quality graphics mode (should we make
|
// Avoid this if we're cutting corners.
|
||||||
// a low-quality sound mode?)
|
if (g_base->audio->UseLowQualityAudio()) {
|
||||||
if (g_base->graphics_server
|
|
||||||
&& g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,7 @@ MaterialContext::SkidSoundEntry::SkidSoundEntry(
|
|||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
#endif
|
#endif
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
context->dynamics->increment_skid_sound_count();
|
context->dynamics->IncrementSkidSoundCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialContext::SkidSoundEntry::SkidSoundEntry(MaterialContext* context_in,
|
MaterialContext::SkidSoundEntry::SkidSoundEntry(MaterialContext* context_in,
|
||||||
@ -57,13 +57,13 @@ MaterialContext::SkidSoundEntry::SkidSoundEntry(MaterialContext* context_in,
|
|||||||
assert(context);
|
assert(context);
|
||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
context->dynamics->increment_skid_sound_count();
|
context->dynamics->IncrementSkidSoundCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialContext::SkidSoundEntry::~SkidSoundEntry() {
|
MaterialContext::SkidSoundEntry::~SkidSoundEntry() {
|
||||||
assert(context);
|
assert(context);
|
||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
context->dynamics->decrement_skid_sound_count();
|
context->dynamics->DecrementSkidSoundCount();
|
||||||
if (playing) {
|
if (playing) {
|
||||||
g_base->audio->PushSourceFadeOutCall(play_id, 200);
|
g_base->audio->PushSourceFadeOutCall(play_id, 200);
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ MaterialContext::RollSoundEntry::RollSoundEntry(MaterialContext* context_in,
|
|||||||
assert(context);
|
assert(context);
|
||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
context->dynamics->incrementRollSoundCount();
|
context->dynamics->IncrementRollSoundCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialContext::RollSoundEntry::RollSoundEntry(
|
MaterialContext::RollSoundEntry::RollSoundEntry(
|
||||||
@ -90,13 +90,13 @@ MaterialContext::RollSoundEntry::RollSoundEntry(
|
|||||||
assert(context);
|
assert(context);
|
||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
context->dynamics->incrementRollSoundCount();
|
context->dynamics->IncrementRollSoundCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialContext::RollSoundEntry::~RollSoundEntry() {
|
MaterialContext::RollSoundEntry::~RollSoundEntry() {
|
||||||
assert(context);
|
assert(context);
|
||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
context->dynamics->decrement_roll_sound_count();
|
context->dynamics->DecrementRollSoundCount();
|
||||||
if (playing) {
|
if (playing) {
|
||||||
g_base->audio->PushSourceFadeOutCall(play_id, 200);
|
g_base->audio->PushSourceFadeOutCall(play_id, 200);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ballistica/scene_v1/dynamics/material/roll_sound_material_action.h"
|
#include "ballistica/scene_v1/dynamics/material/roll_sound_material_action.h"
|
||||||
|
|
||||||
#include "ballistica/base/graphics/graphics_server.h"
|
#include "ballistica/base/audio/audio.h"
|
||||||
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
||||||
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
||||||
#include "ballistica/scene_v1/support/client_session.h"
|
#include "ballistica/scene_v1/support/client_session.h"
|
||||||
@ -34,16 +34,14 @@ void RollSoundMaterialAction::Apply(MaterialContext* context,
|
|||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
|
|
||||||
// For now lets avoid this in low-quality graphics mode
|
// Avoid this if we're cutting corners.
|
||||||
// (should we make a low-quality sound mode?)
|
if (g_base->audio->UseLowQualityAudio()) {
|
||||||
if (g_base->graphics
|
|
||||||
&& g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's limit the amount of skid-sounds we spawn, otherwise we'll
|
// Let's limit the amount of skid-sounds we spawn, otherwise we'll
|
||||||
// start using up all our sound resources on skids when things get messy
|
// start using up all our sound resources on skids when things get messy
|
||||||
if (context->dynamics->getRollSoundCount() < 2) {
|
if (context->dynamics->roll_sound_count() < 2) {
|
||||||
context->roll_sounds.emplace_back(context, sound.Get(), target_impulse,
|
context->roll_sounds.emplace_back(context, sound.Get(), target_impulse,
|
||||||
volume);
|
volume);
|
||||||
context->complex_sound = true;
|
context->complex_sound = true;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ballistica/scene_v1/dynamics/material/skid_sound_material_action.h"
|
#include "ballistica/scene_v1/dynamics/material/skid_sound_material_action.h"
|
||||||
|
|
||||||
#include "ballistica/base/graphics/graphics_server.h"
|
#include "ballistica/base/audio/audio.h"
|
||||||
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
#include "ballistica/scene_v1/dynamics/dynamics.h"
|
||||||
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
#include "ballistica/scene_v1/dynamics/material/material_context.h"
|
||||||
#include "ballistica/scene_v1/support/client_session.h"
|
#include "ballistica/scene_v1/support/client_session.h"
|
||||||
@ -34,10 +34,8 @@ void SkidSoundMaterialAction::Apply(MaterialContext* context,
|
|||||||
assert(context->dynamics.Exists());
|
assert(context->dynamics.Exists());
|
||||||
assert(context->dynamics->in_process());
|
assert(context->dynamics->in_process());
|
||||||
|
|
||||||
// For now lets avoid this in low-quality graphics mode
|
// Avoid this if we're cutting corners.
|
||||||
// (should we make a low-quality sound mode?).
|
if (g_base->audio->UseLowQualityAudio()) {
|
||||||
if (g_base->graphics_server
|
|
||||||
&& g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -65,23 +65,23 @@ RigidBody::RigidBody(int id_in, Part* part_in, Type type_in, Shape shape_in,
|
|||||||
case Shape::kSphere: {
|
case Shape::kSphere: {
|
||||||
dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.3f;
|
dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.3f;
|
||||||
geoms_.resize(1);
|
geoms_.resize(1);
|
||||||
geoms_[0] = dCreateSphere(dynamics_->space(), dimensions_[0]);
|
geoms_[0] = dCreateSphere(dynamics_->ode_space(), dimensions_[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Shape::kBox: {
|
case Shape::kBox: {
|
||||||
dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.6f;
|
dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.6f;
|
||||||
geoms_.resize(1);
|
geoms_.resize(1);
|
||||||
geoms_[0] = dCreateBox(dynamics_->space(), dimensions_[0], dimensions_[1],
|
geoms_[0] = dCreateBox(dynamics_->ode_space(), dimensions_[0],
|
||||||
dimensions_[2]);
|
dimensions_[1], dimensions_[2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Shape::kCapsule: {
|
case Shape::kCapsule: {
|
||||||
dimensions_[0] = dimensions_[1] = 0.3f;
|
dimensions_[0] = dimensions_[1] = 0.3f;
|
||||||
geoms_.resize(1);
|
geoms_.resize(1);
|
||||||
geoms_[0] =
|
geoms_[0] = dCreateCCylinder(dynamics_->ode_space(), dimensions_[0],
|
||||||
dCreateCCylinder(dynamics_->space(), dimensions_[0], dimensions_[1]);
|
dimensions_[1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,14 +98,15 @@ RigidBody::RigidBody(int id_in, Part* part_in, Type type_in, Shape shape_in,
|
|||||||
Vector3f p =
|
Vector3f p =
|
||||||
Matrix44fRotate(Vector3f(0, 1, 0), static_cast<float>(i) * inc)
|
Matrix44fRotate(Vector3f(0, 1, 0), static_cast<float>(i) * inc)
|
||||||
* Vector3f(offset, 0, 0);
|
* Vector3f(offset, 0, 0);
|
||||||
geoms_[i * 2] = dCreateGeomTransform(dynamics_->space());
|
geoms_[i * 2] = dCreateGeomTransform(dynamics_->ode_space());
|
||||||
geoms_[i * 2 + 1] = dCreateSphere(nullptr, sub_rad);
|
geoms_[i * 2 + 1] = dCreateSphere(nullptr, sub_rad);
|
||||||
dGeomTransformSetGeom(geoms_[i * 2], geoms_[i * 2 + 1]);
|
dGeomTransformSetGeom(geoms_[i * 2], geoms_[i * 2 + 1]);
|
||||||
dGeomSetPosition(geoms_[i * 2 + 1], p.v[0], p.v[1], p.v[2]);
|
dGeomSetPosition(geoms_[i * 2 + 1], p.v[0], p.v[1], p.v[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// One last center sphere to keep stuff from getting stuck in our middle.
|
// One last center sphere to keep stuff from getting stuck in our middle.
|
||||||
geoms_[geoms_.size() - 1] = dCreateSphere(dynamics_->space(), sub_rad);
|
geoms_[geoms_.size() - 1] =
|
||||||
|
dCreateSphere(dynamics_->ode_space(), sub_rad);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,9 +129,6 @@ FlagNode::FlagNode(Scene* scene) : Node(scene, node_type), part_(this) {
|
|||||||
|
|
||||||
mesh_.SetIndexData(indices);
|
mesh_.SetIndexData(indices);
|
||||||
mesh_.SetStaticData(v_static);
|
mesh_.SetStaticData(v_static);
|
||||||
|
|
||||||
// Create our shadow set.
|
|
||||||
UpdateForGraphicsQuality(g_base->graphics_server->quality());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FlagNode::getPosition() const -> std::vector<float> {
|
auto FlagNode::getPosition() const -> std::vector<float> {
|
||||||
@ -257,6 +254,11 @@ void FlagNode::HandleMessage(const char* data_in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlagNode::Draw(base::FrameDef* frame_def) {
|
void FlagNode::Draw(base::FrameDef* frame_def) {
|
||||||
|
if (graphics_quality_ != frame_def->quality()) {
|
||||||
|
graphics_quality_ = frame_def->quality();
|
||||||
|
UpdateForGraphicsQuality(graphics_quality_);
|
||||||
|
}
|
||||||
|
|
||||||
// Flag cloth.
|
// Flag cloth.
|
||||||
{
|
{
|
||||||
// Update the dynamic portion of our mesh data.
|
// Update the dynamic portion of our mesh data.
|
||||||
@ -311,45 +313,60 @@ void FlagNode::Draw(base::FrameDef* frame_def) {
|
|||||||
|
|
||||||
FullShadowSet* full_shadows = full_shadow_set_.Get();
|
FullShadowSet* full_shadows = full_shadow_set_.Get();
|
||||||
|
|
||||||
if (full_shadows) {
|
// Update our shadow objects.
|
||||||
// Pole bottom.
|
if (!g_core->HeadlessMode()) {
|
||||||
{
|
dBodyID b = body_->body();
|
||||||
full_shadows->shadow_pole_bottom_.GetValues(&s_scale, &s_density);
|
assert(b);
|
||||||
const Vector3f& p(full_shadows->shadow_pole_bottom_.GetPosition());
|
dVector3 p;
|
||||||
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
if (FullShadowSet* full_shadows = full_shadow_set_.Get()) {
|
||||||
s_density * 0.25f);
|
full_shadows->shadow_flag_.SetPosition(
|
||||||
}
|
flag_points_[kFlagSizeX * (kFlagSizeY / 2) + (kFlagSizeX / 2)]);
|
||||||
|
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.4f, p);
|
||||||
|
full_shadows->shadow_pole_bottom_.SetPosition(Vector3f(p));
|
||||||
|
full_shadows->shadow_pole_middle_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(b)));
|
||||||
|
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * 0.4f, p);
|
||||||
|
full_shadows->shadow_pole_top_.SetPosition(Vector3f(p));
|
||||||
|
// Pole bottom.
|
||||||
|
{
|
||||||
|
full_shadows->shadow_pole_bottom_.GetValues(&s_scale, &s_density);
|
||||||
|
const Vector3f& p(full_shadows->shadow_pole_bottom_.GetPosition());
|
||||||
|
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
||||||
|
s_density * 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
// Pole middle.
|
// Pole middle.
|
||||||
{
|
{
|
||||||
full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density);
|
full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density);
|
||||||
const Vector3f& p(full_shadows->shadow_pole_middle_.GetPosition());
|
const Vector3f& p(full_shadows->shadow_pole_middle_.GetPosition());
|
||||||
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
||||||
s_density * 0.25f);
|
s_density * 0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pole top.
|
// Pole top.
|
||||||
{
|
{
|
||||||
full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density);
|
full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density);
|
||||||
const Vector3f& p(full_shadows->shadow_pole_top_.GetPosition());
|
const Vector3f& p(full_shadows->shadow_pole_top_.GetPosition());
|
||||||
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0,
|
||||||
s_density * 0.25f);
|
s_density * 0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag center.
|
// Flag center.
|
||||||
{
|
{
|
||||||
full_shadows->shadow_flag_.GetValues(&s_scale, &s_density);
|
full_shadows->shadow_flag_.GetValues(&s_scale, &s_density);
|
||||||
const Vector3f& p(full_shadows->shadow_flag_.GetPosition());
|
const Vector3f& p(full_shadows->shadow_flag_.GetPosition());
|
||||||
|
g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0,
|
||||||
|
s_density * 0.3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (SimpleShadowSet* simple_shadows = simple_shadow_set_.Get()) {
|
||||||
|
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.3f, p);
|
||||||
|
simple_shadows->shadow_.SetPosition(Vector3f(p));
|
||||||
|
simple_shadows->shadow_.GetValues(&s_scale, &s_density);
|
||||||
|
const Vector3f& p(simple_shadows->shadow_.GetPosition());
|
||||||
g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0,
|
g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0,
|
||||||
s_density * 0.3f);
|
s_density * 0.5f);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SimpleShadowSet* simple_shadows = simple_shadow_set_.Get();
|
|
||||||
assert(simple_shadows);
|
|
||||||
simple_shadows->shadow_.GetValues(&s_scale, &s_density);
|
|
||||||
const Vector3f& p(simple_shadows->shadow_.GetPosition());
|
|
||||||
g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0,
|
|
||||||
s_density * 0.5f);
|
|
||||||
}
|
}
|
||||||
c.Submit();
|
c.Submit();
|
||||||
}
|
}
|
||||||
@ -398,30 +415,6 @@ void FlagNode::Step() {
|
|||||||
// FIXME: This should probably happen for RBDs automatically?
|
// FIXME: This should probably happen for RBDs automatically?
|
||||||
body_->UpdateBlending();
|
body_->UpdateBlending();
|
||||||
|
|
||||||
// Update our shadow objects.
|
|
||||||
dBodyID b = body_->body();
|
|
||||||
assert(b);
|
|
||||||
|
|
||||||
if (!g_core->HeadlessMode()) {
|
|
||||||
dVector3 p;
|
|
||||||
FullShadowSet* full_shadows = full_shadow_set_.Get();
|
|
||||||
if (full_shadows) {
|
|
||||||
full_shadows->shadow_flag_.SetPosition(
|
|
||||||
flag_points_[kFlagSizeX * (kFlagSizeY / 2) + (kFlagSizeX / 2)]);
|
|
||||||
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.4f, p);
|
|
||||||
full_shadows->shadow_pole_bottom_.SetPosition(Vector3f(p));
|
|
||||||
full_shadows->shadow_pole_middle_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(b)));
|
|
||||||
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * 0.4f, p);
|
|
||||||
full_shadows->shadow_pole_top_.SetPosition(Vector3f(p));
|
|
||||||
} else {
|
|
||||||
SimpleShadowSet* simple_shadows = simple_shadow_set_.Get();
|
|
||||||
assert(simple_shadows);
|
|
||||||
dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.3f, p);
|
|
||||||
simple_shadows->shadow_.SetPosition(Vector3f(p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dBodyIsEnabled(body_->body())) {
|
if (dBodyIsEnabled(body_->body())) {
|
||||||
// Try to keep upright by pushing the top of the
|
// Try to keep upright by pushing the top of the
|
||||||
// flag to be above the bottom.
|
// flag to be above the bottom.
|
||||||
@ -675,10 +668,6 @@ void FlagNode::GetRigidBodyPickupLocations(int id, float* obj, float* character,
|
|||||||
hand1[2] = -0.05f;
|
hand1[2] = -0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlagNode::OnGraphicsQualityChanged(base::GraphicsQuality q) {
|
|
||||||
UpdateForGraphicsQuality(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlagNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) {
|
void FlagNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) {
|
||||||
if (!g_core->HeadlessMode()) {
|
if (!g_core->HeadlessMode()) {
|
||||||
if (quality >= base::GraphicsQuality::kMedium) {
|
if (quality >= base::GraphicsQuality::kMedium) {
|
||||||
|
|||||||
@ -44,10 +44,13 @@ class FlagNode : public Node {
|
|||||||
void UpdateDimensions();
|
void UpdateDimensions();
|
||||||
void ResetFlagMesh();
|
void ResetFlagMesh();
|
||||||
void UpdateFlagMesh();
|
void UpdateFlagMesh();
|
||||||
void OnGraphicsQualityChanged(base::GraphicsQuality q) override;
|
|
||||||
void UpdateForGraphicsQuality(base::GraphicsQuality q);
|
void UpdateForGraphicsQuality(base::GraphicsQuality q);
|
||||||
void UpdateSpringPoint(int p1, int p2, float rest_length);
|
void UpdateSpringPoint(int p1, int p2, float rest_length);
|
||||||
base::AreaOfInterest* area_of_interest_ = nullptr;
|
|
||||||
|
base::GraphicsQuality graphics_quality_{};
|
||||||
|
bool light_weight_ : 1 {};
|
||||||
|
bool have_flag_impulse_ : 1 {};
|
||||||
|
base::AreaOfInterest* area_of_interest_{};
|
||||||
Part part_;
|
Part part_;
|
||||||
std::vector<float> color_ = {1.0f, 1.0f, 1.0f};
|
std::vector<float> color_ = {1.0f, 1.0f, 1.0f};
|
||||||
Object::Ref<RigidBody> body_;
|
Object::Ref<RigidBody> body_;
|
||||||
@ -56,15 +59,13 @@ class FlagNode : public Node {
|
|||||||
Object::Ref<FullShadowSet> full_shadow_set_;
|
Object::Ref<FullShadowSet> full_shadow_set_;
|
||||||
Object::Ref<SimpleShadowSet> simple_shadow_set_;
|
Object::Ref<SimpleShadowSet> simple_shadow_set_;
|
||||||
int wind_rand_{};
|
int wind_rand_{};
|
||||||
|
int footing_{};
|
||||||
float wind_rand_x_{};
|
float wind_rand_x_{};
|
||||||
float wind_rand_y_{};
|
float wind_rand_y_{};
|
||||||
float wind_rand_z_{};
|
float wind_rand_z_{};
|
||||||
float flag_impulse_add_x_{};
|
float flag_impulse_add_x_{};
|
||||||
float flag_impulse_add_y_{};
|
float flag_impulse_add_y_{};
|
||||||
float flag_impulse_add_z_{};
|
float flag_impulse_add_z_{};
|
||||||
bool have_flag_impulse_{};
|
|
||||||
int footing_{};
|
|
||||||
bool light_weight_{};
|
|
||||||
Vector3f flag_points_[25]{};
|
Vector3f flag_points_[25]{};
|
||||||
Vector3f flag_normals_[25]{};
|
Vector3f flag_normals_[25]{};
|
||||||
Vector3f flag_velocities_[25]{};
|
Vector3f flag_velocities_[25]{};
|
||||||
|
|||||||
@ -40,7 +40,6 @@ class Node : public Object {
|
|||||||
|
|
||||||
/// Called when the language changes.
|
/// Called when the language changes.
|
||||||
virtual void OnLanguageChange() {}
|
virtual void OnLanguageChange() {}
|
||||||
virtual void OnGraphicsQualityChanged(base::GraphicsQuality q) {}
|
|
||||||
|
|
||||||
/// The node can rule out collisions between particular bodies using this.
|
/// The node can rule out collisions between particular bodies using this.
|
||||||
virtual auto PreFilterCollision(RigidBody* b1, RigidBody* r2) -> bool {
|
virtual auto PreFilterCollision(RigidBody* b1, RigidBody* r2) -> bool {
|
||||||
|
|||||||
@ -576,7 +576,7 @@ auto PropNode::CollideCallback(dContact* c, int count,
|
|||||||
dBodyGetMass(b2, &m);
|
dBodyGetMass(b2, &m);
|
||||||
dJointID j =
|
dJointID j =
|
||||||
dJointCreateFixed(scene()->dynamics()->ode_world(),
|
dJointCreateFixed(scene()->dynamics()->ode_world(),
|
||||||
scene()->dynamics()->getContactGroup());
|
scene()->dynamics()->ode_contact_group());
|
||||||
dJointAttach(j, b1, b2);
|
dJointAttach(j, b1, b2);
|
||||||
dJointSetFixed(j);
|
dJointSetFixed(j);
|
||||||
dJointSetFixedSpringMode(j, 1, 1, false);
|
dJointSetFixedSpringMode(j, 1, 1, false);
|
||||||
|
|||||||
@ -260,7 +260,7 @@ void ShieldNode::Draw(base::FrameDef* frame_def) {
|
|||||||
c.Submit();
|
c.Submit();
|
||||||
|
|
||||||
// Nifty intersection effects in fancy graphics mode.
|
// Nifty intersection effects in fancy graphics mode.
|
||||||
if (frame_def->has_depth_texture()) {
|
if (frame_def->HasDepthTexture()) {
|
||||||
base::ShieldComponent c2(frame_def->overlay_3d_pass());
|
base::ShieldComponent c2(frame_def->overlay_3d_pass());
|
||||||
{
|
{
|
||||||
auto xf = c2.ScopedTransform();
|
auto xf = c2.ScopedTransform();
|
||||||
@ -273,7 +273,7 @@ void ShieldNode::Draw(base::FrameDef* frame_def) {
|
|||||||
}
|
}
|
||||||
c2.Submit();
|
c2.Submit();
|
||||||
}
|
}
|
||||||
if (frame_def->has_depth_texture()) {
|
if (frame_def->HasDepthTexture()) {
|
||||||
base::PostProcessComponent c2(frame_def->blit_pass());
|
base::PostProcessComponent c2(frame_def->blit_pass());
|
||||||
c2.SetNormalDistort(distort);
|
c2.SetNormalDistort(distort);
|
||||||
{
|
{
|
||||||
|
|||||||
@ -916,9 +916,6 @@ SpazNode::SpazNode(Scene* scene)
|
|||||||
// Give joints initial vals.
|
// Give joints initial vals.
|
||||||
UpdateJoints();
|
UpdateJoints();
|
||||||
|
|
||||||
// FIXME: should do this on draw.
|
|
||||||
UpdateForGraphicsQuality(g_base->graphics_server->quality());
|
|
||||||
|
|
||||||
// We want to have an area of interest by default.
|
// We want to have an area of interest by default.
|
||||||
SetIsAreaOfInterest(true);
|
SetIsAreaOfInterest(true);
|
||||||
|
|
||||||
@ -2079,40 +2076,6 @@ void SpazNode::Step() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update shadows.
|
|
||||||
#if !BA_HEADLESS_BUILD
|
|
||||||
FullShadowSet* full_shadows = full_shadow_set_.Get();
|
|
||||||
if (full_shadows) {
|
|
||||||
full_shadows->torso_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(body_torso_->body())));
|
|
||||||
full_shadows->head_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(body_head_->body())));
|
|
||||||
full_shadows->pelvis_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(body_pelvis_->body())));
|
|
||||||
full_shadows->lower_left_leg_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(lower_left_leg_body_->body())));
|
|
||||||
full_shadows->lower_right_leg_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(lower_right_leg_body_->body())));
|
|
||||||
full_shadows->upper_left_leg_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(upper_left_leg_body_->body())));
|
|
||||||
full_shadows->upper_right_leg_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(upper_right_leg_body_->body())));
|
|
||||||
full_shadows->lower_right_arm_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(lower_right_arm_body_->body())));
|
|
||||||
full_shadows->upper_right_arm_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(upper_right_arm_body_->body())));
|
|
||||||
full_shadows->lower_left_arm_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(lower_left_arm_body_->body())));
|
|
||||||
full_shadows->upper_left_arm_shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(upper_left_arm_body_->body())));
|
|
||||||
} else {
|
|
||||||
SimpleShadowSet* simple_shadows = simple_shadow_set_.Get();
|
|
||||||
assert(simple_shadows);
|
|
||||||
simple_shadows->shadow_.SetPosition(
|
|
||||||
Vector3f(dBodyGetPosition(body_pelvis_->body())));
|
|
||||||
}
|
|
||||||
#endif // !BA_HEADLESS_BUILD
|
|
||||||
|
|
||||||
// Update wings if we've got 'em.
|
// Update wings if we've got 'em.
|
||||||
if (wings_) {
|
if (wings_) {
|
||||||
float maxDist = 0.8f;
|
float maxDist = 0.8f;
|
||||||
@ -4547,6 +4510,11 @@ static void DrawRadialMeter(base::MeshIndexedSimpleFull* m,
|
|||||||
void SpazNode::Draw(base::FrameDef* frame_def) {
|
void SpazNode::Draw(base::FrameDef* frame_def) {
|
||||||
#if !BA_HEADLESS_BUILD
|
#if !BA_HEADLESS_BUILD
|
||||||
|
|
||||||
|
if (graphics_quality_ != frame_def->quality()) {
|
||||||
|
graphics_quality_ = frame_def->quality();
|
||||||
|
UpdateForGraphicsQuality(graphics_quality_);
|
||||||
|
}
|
||||||
|
|
||||||
#if BA_OSTYPE_MACOS
|
#if BA_OSTYPE_MACOS
|
||||||
if (g_base->graphics_server->renderer()->debug_draw_mode()) {
|
if (g_base->graphics_server->renderer()->debug_draw_mode()) {
|
||||||
base::SimpleComponent c(frame_def->overlay_3d_pass());
|
base::SimpleComponent c(frame_def->overlay_3d_pass());
|
||||||
@ -5356,49 +5324,68 @@ void SpazNode::Draw(base::FrameDef* frame_def) {
|
|||||||
sc[2] = weight * freeze_color[2] + (1.0f - weight) * sc[2];
|
sc[2] = weight * freeze_color[2] + (1.0f - weight) * sc[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
FullShadowSet* full_shadows = full_shadow_set_.Get();
|
// Update and draw shadows.
|
||||||
if (full_shadows) {
|
if (!g_core->HeadlessMode()) {
|
||||||
DrawBrightSpot(full_shadows->lower_left_leg_shadow_, 0.3f * death_scale,
|
if (FullShadowSet* full_shadows = full_shadow_set_.Get()) {
|
||||||
death_fade * (frozen_ ? 0.3f : 0.2f), sc);
|
full_shadows->torso_shadow_.SetPosition(
|
||||||
DrawBrightSpot(full_shadows->lower_right_leg_shadow_, 0.3f * death_scale,
|
Vector3f(dBodyGetPosition(body_torso_->body())));
|
||||||
death_fade * (frozen_ ? 0.3f : 0.2f), sc);
|
full_shadows->head_shadow_.SetPosition(
|
||||||
DrawBrightSpot(full_shadows->head_shadow_, 0.45f * death_scale,
|
Vector3f(dBodyGetPosition(body_head_->body())));
|
||||||
death_fade * (frozen_ ? 0.8f : 0.14f), sc);
|
full_shadows->pelvis_shadow_.SetPosition(
|
||||||
}
|
Vector3f(dBodyGetPosition(body_pelvis_->body())));
|
||||||
|
full_shadows->lower_left_leg_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(lower_left_leg_body_->body())));
|
||||||
|
full_shadows->lower_right_leg_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(lower_right_leg_body_->body())));
|
||||||
|
full_shadows->upper_left_leg_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(upper_left_leg_body_->body())));
|
||||||
|
full_shadows->upper_right_leg_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(upper_right_leg_body_->body())));
|
||||||
|
full_shadows->lower_right_arm_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(lower_right_arm_body_->body())));
|
||||||
|
full_shadows->upper_right_arm_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(upper_right_arm_body_->body())));
|
||||||
|
full_shadows->lower_left_arm_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(lower_left_arm_body_->body())));
|
||||||
|
full_shadows->upper_left_arm_shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(upper_left_arm_body_->body())));
|
||||||
|
|
||||||
if (full_shadows) {
|
DrawBrightSpot(full_shadows->lower_left_leg_shadow_, 0.3f * death_scale,
|
||||||
DrawShadow(full_shadows->torso_shadow_, 0.19f * death_scale, 0.9f, sc);
|
death_fade * (frozen_ ? 0.3f : 0.2f), sc);
|
||||||
DrawShadow(full_shadows->head_shadow_, 0.15f * death_scale, 0.7f, sc);
|
DrawBrightSpot(full_shadows->lower_right_leg_shadow_,
|
||||||
DrawShadow(full_shadows->pelvis_shadow_, 0.15f * death_scale, 0.7f, sc);
|
0.3f * death_scale, death_fade * (frozen_ ? 0.3f : 0.2f),
|
||||||
DrawShadow(full_shadows->lower_left_leg_shadow_, 0.08f * death_scale,
|
sc);
|
||||||
1.0f, sc);
|
DrawBrightSpot(full_shadows->head_shadow_, 0.45f * death_scale,
|
||||||
DrawShadow(full_shadows->lower_right_leg_shadow_, 0.08f * death_scale,
|
death_fade * (frozen_ ? 0.8f : 0.14f), sc);
|
||||||
1.0f, sc);
|
DrawShadow(full_shadows->torso_shadow_, 0.19f * death_scale, 0.9f, sc);
|
||||||
DrawShadow(full_shadows->upper_left_leg_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->head_shadow_, 0.15f * death_scale, 0.7f, sc);
|
||||||
1.0f, sc);
|
DrawShadow(full_shadows->pelvis_shadow_, 0.15f * death_scale, 0.7f, sc);
|
||||||
DrawShadow(full_shadows->upper_right_leg_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->lower_left_leg_shadow_, 0.08f * death_scale,
|
||||||
1.0f, sc);
|
1.0f, sc);
|
||||||
DrawShadow(full_shadows->upper_left_arm_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->lower_right_leg_shadow_, 0.08f * death_scale,
|
||||||
0.5f, sc);
|
1.0f, sc);
|
||||||
DrawShadow(full_shadows->lower_left_arm_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->upper_left_leg_shadow_, 0.08f * death_scale,
|
||||||
0.3f, sc);
|
1.0f, sc);
|
||||||
DrawShadow(full_shadows->lower_right_arm_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->upper_right_leg_shadow_, 0.08f * death_scale,
|
||||||
0.3f, sc);
|
1.0f, sc);
|
||||||
DrawShadow(full_shadows->upper_right_arm_shadow_, 0.08f * death_scale,
|
DrawShadow(full_shadows->upper_left_arm_shadow_, 0.08f * death_scale,
|
||||||
0.5f, sc);
|
0.5f, sc);
|
||||||
} else {
|
DrawShadow(full_shadows->lower_left_arm_shadow_, 0.08f * death_scale,
|
||||||
SimpleShadowSet* simple_shadows = simple_shadow_set_.Get();
|
0.3f, sc);
|
||||||
assert(simple_shadows);
|
DrawShadow(full_shadows->lower_right_arm_shadow_, 0.08f * death_scale,
|
||||||
DrawShadow(simple_shadows->shadow_, 0.2f * death_scale, 2.0f, sc);
|
0.3f, sc);
|
||||||
|
DrawShadow(full_shadows->upper_right_arm_shadow_, 0.08f * death_scale,
|
||||||
|
0.5f, sc);
|
||||||
|
} else if (SimpleShadowSet* simple_shadows = simple_shadow_set_.Get()) {
|
||||||
|
simple_shadows->shadow_.SetPosition(
|
||||||
|
Vector3f(dBodyGetPosition(body_pelvis_->body())));
|
||||||
|
DrawShadow(simple_shadows->shadow_, 0.2f * death_scale, 2.0f, sc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !BA_HEADLESS_BUILD
|
#endif // !BA_HEADLESS_BUILD
|
||||||
} // NOLINT (yes i know this is too big)
|
} // NOLINT (yes i know this is too big)
|
||||||
|
|
||||||
void SpazNode::OnGraphicsQualityChanged(base::GraphicsQuality q) {
|
|
||||||
UpdateForGraphicsQuality(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpazNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) {
|
void SpazNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) {
|
||||||
#if !BA_HEADLESS_BUILD
|
#if !BA_HEADLESS_BUILD
|
||||||
if (quality >= base::GraphicsQuality::kMedium) {
|
if (quality >= base::GraphicsQuality::kMedium) {
|
||||||
|
|||||||
@ -277,7 +277,6 @@ class SpazNode : public Node {
|
|||||||
|
|
||||||
// Reset to a standing, non-moving state at the given point.
|
// Reset to a standing, non-moving state at the given point.
|
||||||
void Stand(float x, float y, float z, float angle);
|
void Stand(float x, float y, float z, float angle);
|
||||||
void OnGraphicsQualityChanged(base::GraphicsQuality q) override;
|
|
||||||
void UpdateForGraphicsQuality(base::GraphicsQuality q);
|
void UpdateForGraphicsQuality(base::GraphicsQuality q);
|
||||||
void UpdateAreaOfInterest();
|
void UpdateAreaOfInterest();
|
||||||
auto CollideCallback(dContact* c, int count, RigidBody* colliding_body,
|
auto CollideCallback(dContact* c, int count, RigidBody* colliding_body,
|
||||||
@ -515,6 +514,7 @@ class SpazNode : public Node {
|
|||||||
bool has_eyelids_{true};
|
bool has_eyelids_{true};
|
||||||
bool running_{};
|
bool running_{};
|
||||||
bool billboard_cross_out_{};
|
bool billboard_cross_out_{};
|
||||||
|
base::GraphicsQuality graphics_quality_{};
|
||||||
Object::Ref<RigidBody> hair_front_right_body_;
|
Object::Ref<RigidBody> hair_front_right_body_;
|
||||||
JointFixedEF* hair_front_right_joint_{};
|
JointFixedEF* hair_front_right_joint_{};
|
||||||
Object::Ref<RigidBody> hair_front_left_body_;
|
Object::Ref<RigidBody> hair_front_left_body_;
|
||||||
|
|||||||
@ -483,9 +483,6 @@ void HostActivity::PruneSessionBaseTimers() {
|
|||||||
void HostActivity::OnScreenSizeChange() { scene()->OnScreenSizeChange(); }
|
void HostActivity::OnScreenSizeChange() { scene()->OnScreenSizeChange(); }
|
||||||
void HostActivity::LanguageChanged() { scene()->LanguageChanged(); }
|
void HostActivity::LanguageChanged() { scene()->LanguageChanged(); }
|
||||||
void HostActivity::DebugSpeedMultChanged() { UpdateStepTimerLength(); }
|
void HostActivity::DebugSpeedMultChanged() { UpdateStepTimerLength(); }
|
||||||
void HostActivity::GraphicsQualityChanged(base::GraphicsQuality q) {
|
|
||||||
scene()->GraphicsQualityChanged(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HostActivity::Draw(base::FrameDef* frame_def) {
|
void HostActivity::Draw(base::FrameDef* frame_def) {
|
||||||
if (!started_) {
|
if (!started_) {
|
||||||
|
|||||||
@ -57,7 +57,6 @@ class HostActivity : public SceneV1Context {
|
|||||||
void OnScreenSizeChange();
|
void OnScreenSizeChange();
|
||||||
void LanguageChanged();
|
void LanguageChanged();
|
||||||
void DebugSpeedMultChanged();
|
void DebugSpeedMultChanged();
|
||||||
void GraphicsQualityChanged(base::GraphicsQuality q);
|
|
||||||
|
|
||||||
// Used to register python calls created in this context so we can make sure
|
// Used to register python calls created in this context so we can make sure
|
||||||
// they got properly cleaned up.
|
// they got properly cleaned up.
|
||||||
|
|||||||
@ -154,16 +154,6 @@ void HostSession::LanguageChanged() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostSession::GraphicsQualityChanged(base::GraphicsQuality q) {
|
|
||||||
// Let our internal scene know.
|
|
||||||
scene()->GraphicsQualityChanged(q);
|
|
||||||
|
|
||||||
// Let all our activities know.
|
|
||||||
for (auto&& i : host_activities_) {
|
|
||||||
i->GraphicsQualityChanged(q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto HostSession::DoesFillScreen() const -> bool {
|
auto HostSession::DoesFillScreen() const -> bool {
|
||||||
// FIXME not necessarily the case.
|
// FIXME not necessarily the case.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -70,7 +70,6 @@ class HostSession : public Session {
|
|||||||
void Draw(base::FrameDef* f) override;
|
void Draw(base::FrameDef* f) override;
|
||||||
void OnScreenSizeChange() override;
|
void OnScreenSizeChange() override;
|
||||||
void LanguageChanged() override;
|
void LanguageChanged() override;
|
||||||
void GraphicsQualityChanged(base::GraphicsQuality q) override;
|
|
||||||
void DebugSpeedMultChanged() override;
|
void DebugSpeedMultChanged() override;
|
||||||
auto GetHostSession() -> HostSession* override;
|
auto GetHostSession() -> HostSession* override;
|
||||||
auto GetMutableScene() -> Scene* override;
|
auto GetMutableScene() -> Scene* override;
|
||||||
|
|||||||
@ -166,7 +166,7 @@ void Scene::Step() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lastly step our sim.
|
// Lastly step our sim.
|
||||||
dynamics_->process();
|
dynamics_->Process();
|
||||||
|
|
||||||
time_ += kGameStepMilliseconds;
|
time_ += kGameStepMilliseconds;
|
||||||
stepnum_++;
|
stepnum_++;
|
||||||
@ -227,13 +227,6 @@ void Scene::DeleteNode(Node* node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::GraphicsQualityChanged(base::GraphicsQuality q) {
|
|
||||||
assert(g_base->InLogicThread());
|
|
||||||
for (auto&& i : nodes_) {
|
|
||||||
i->OnGraphicsQualityChanged(q);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scene::OnScreenSizeChange() {
|
void Scene::OnScreenSizeChange() {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
for (auto&& i : nodes_) {
|
for (auto&& i : nodes_) {
|
||||||
|
|||||||
@ -43,7 +43,6 @@ class Scene : public Object {
|
|||||||
void SetMapBounds(float x, float y, float z, float X, float Y, float Z);
|
void SetMapBounds(float x, float y, float z, float X, float Y, float Z);
|
||||||
void OnScreenSizeChange();
|
void OnScreenSizeChange();
|
||||||
void LanguageChanged();
|
void LanguageChanged();
|
||||||
void GraphicsQualityChanged(base::GraphicsQuality q);
|
|
||||||
auto out_of_bounds_nodes() -> const std::vector<Object::WeakRef<Node> >& {
|
auto out_of_bounds_nodes() -> const std::vector<Object::WeakRef<Node> >& {
|
||||||
return out_of_bounds_nodes_;
|
return out_of_bounds_nodes_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1312,15 +1312,6 @@ void SceneV1AppMode::SetPublicPartyStatsURL(const std::string& url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneV1AppMode::GraphicsQualityChanged(base::GraphicsQuality quality) {
|
|
||||||
for (auto&& i : sessions_) {
|
|
||||||
if (!i.Exists()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
i->GraphicsQualityChanged(quality);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneV1AppMode::SetPublicPartyPlayerCount(int count) {
|
void SceneV1AppMode::SetPublicPartyPlayerCount(int count) {
|
||||||
assert(g_base->InLogicThread());
|
assert(g_base->InLogicThread());
|
||||||
if (count == public_party_player_count_) {
|
if (count == public_party_player_count_) {
|
||||||
|
|||||||
@ -172,7 +172,6 @@ class SceneV1AppMode : public base::AppMode {
|
|||||||
sockaddr_storage* from) override;
|
sockaddr_storage* from) override;
|
||||||
void DrawWorld(base::FrameDef* frame_def) override;
|
void DrawWorld(base::FrameDef* frame_def) override;
|
||||||
auto DoesWorldFillScreen() -> bool override;
|
auto DoesWorldFillScreen() -> bool override;
|
||||||
void GraphicsQualityChanged(base::GraphicsQuality quality) override;
|
|
||||||
void RunMainMenu();
|
void RunMainMenu();
|
||||||
|
|
||||||
auto dynamics_sync_time() const { return dynamics_sync_time_; }
|
auto dynamics_sync_time() const { return dynamics_sync_time_; }
|
||||||
|
|||||||
@ -33,8 +33,6 @@ void Session::OnScreenSizeChange() {}
|
|||||||
|
|
||||||
void Session::LanguageChanged() {}
|
void Session::LanguageChanged() {}
|
||||||
|
|
||||||
void Session::GraphicsQualityChanged(base::GraphicsQuality q) {}
|
|
||||||
|
|
||||||
void Session::DebugSpeedMultChanged() {}
|
void Session::DebugSpeedMultChanged() {}
|
||||||
|
|
||||||
void Session::DumpFullState(SessionStream* out) {
|
void Session::DumpFullState(SessionStream* out) {
|
||||||
|
|||||||
@ -34,7 +34,6 @@ class Session : public SceneV1Context {
|
|||||||
virtual auto GetForegroundContext() -> base::ContextRef;
|
virtual auto GetForegroundContext() -> base::ContextRef;
|
||||||
virtual void OnScreenSizeChange();
|
virtual void OnScreenSizeChange();
|
||||||
virtual void LanguageChanged();
|
virtual void LanguageChanged();
|
||||||
virtual void GraphicsQualityChanged(base::GraphicsQuality q);
|
|
||||||
virtual void DebugSpeedMultChanged();
|
virtual void DebugSpeedMultChanged();
|
||||||
auto benchmark_type() const -> base::BenchmarkType { return benchmark_type_; }
|
auto benchmark_type() const -> base::BenchmarkType { return benchmark_type_; }
|
||||||
void set_benchmark_type(base::BenchmarkType val) { benchmark_type_ = val; }
|
void set_benchmark_type(base::BenchmarkType val) { benchmark_type_ = val; }
|
||||||
|
|||||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
|||||||
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 kEngineBuildNumber = 21479;
|
const int kEngineBuildNumber = 21486;
|
||||||
const char* kEngineVersion = "1.7.28";
|
const char* kEngineVersion = "1.7.28";
|
||||||
const int kEngineApiVersion = 8;
|
const int kEngineApiVersion = 8;
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,7 @@ void FatalError::ReportFatalError(const std::string& message,
|
|||||||
// momentarily, and also go to platform-specific logging and good ol'
|
// momentarily, and also go to platform-specific logging and good ol'
|
||||||
// stderr.
|
// stderr.
|
||||||
Logging::V1CloudLog(logmsg);
|
Logging::V1CloudLog(logmsg);
|
||||||
Logging::DisplayLog("root", LogLevel::kCritical, logmsg);
|
Logging::EmitLog("root", LogLevel::kCritical, logmsg);
|
||||||
fprintf(stderr, "%s\n", logmsg.c_str());
|
fprintf(stderr, "%s\n", logmsg.c_str());
|
||||||
|
|
||||||
std::string prefix = "FATAL-ERROR-LOG:";
|
std::string prefix = "FATAL-ERROR-LOG:";
|
||||||
@ -175,10 +175,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) {
|
||||||
Logging::DisplayLog("root", LogLevel::kCritical, "Calling exit(1)...");
|
Logging::EmitLog("root", LogLevel::kCritical, "Calling exit(1)...");
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
Logging::DisplayLog("root", LogLevel::kCritical, "Calling abort()...");
|
Logging::EmitLog("root", LogLevel::kCritical, "Calling abort()...");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,16 +20,16 @@ void Logging::Log(LogLevel level, const std::string& msg) {
|
|||||||
g_core->python->LoggingCall(level, msg);
|
g_core->python->LoggingCall(level, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logging::DisplayLog(const std::string& name, LogLevel level,
|
void Logging::EmitLog(const std::string& name, LogLevel level,
|
||||||
const std::string& msg) {
|
const std::string& msg) {
|
||||||
// Print to the in-app console (with a newline added).
|
// Print to the dev console.
|
||||||
if (g_base_soft) {
|
if (g_base_soft) {
|
||||||
g_base_soft->PushDevConsolePrintCall(msg + "\n");
|
g_base_soft->PushDevConsolePrintCall(msg + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ship to platform-specific display mechanisms (android log, etc).
|
// Ship to platform-specific display mechanisms (android log, etc).
|
||||||
if (g_core) {
|
if (g_core) {
|
||||||
g_core->platform->DisplayLog(name, level, msg);
|
g_core->platform->EmitPlatformLog(name, level, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,12 +29,11 @@ class Logging {
|
|||||||
/// babase is imported may not be visible in the app for that same reason.
|
/// babase is imported may not be visible in the app for that same reason.
|
||||||
static void Log(LogLevel level, const std::string& msg);
|
static void Log(LogLevel level, const std::string& msg);
|
||||||
|
|
||||||
/// Immediately display a log message in the in-app console,
|
/// Send a log message to the in-app console, platform-specific logs, etc.
|
||||||
/// platform-specific logs, etc. This generally should not be called
|
/// This generally should not be called directly but instead wired up to
|
||||||
/// directly but instead wired up to display messages coming from the
|
/// log messages coming through the Python logging system.
|
||||||
/// Python logging system.
|
static void EmitLog(const std::string& name, LogLevel level,
|
||||||
static void DisplayLog(const std::string& name, LogLevel level,
|
const std::string& msg);
|
||||||
const std::string& msg);
|
|
||||||
|
|
||||||
/// Write a message to the v1 cloud log. This is considered legacy and
|
/// Write a message to the v1 cloud log. This is considered legacy and
|
||||||
/// will be phased out eventually.
|
/// will be phased out eventually.
|
||||||
|
|||||||
@ -20,7 +20,6 @@ using core::g_core;
|
|||||||
Object::Object() {
|
Object::Object() {
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
// Mark when we were born.
|
// Mark when we were born.
|
||||||
// NOTE: Using core's internal globals here; don't do this normally.
|
|
||||||
assert(g_core);
|
assert(g_core);
|
||||||
object_birth_time_ = g_core->GetAppTimeMillisecs();
|
object_birth_time_ = g_core->GetAppTimeMillisecs();
|
||||||
|
|
||||||
@ -41,7 +40,6 @@ Object::Object() {
|
|||||||
Object::~Object() {
|
Object::~Object() {
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
{
|
{
|
||||||
// NOTE: using core's internal globals here; don't do this normally!
|
|
||||||
assert(g_core);
|
assert(g_core);
|
||||||
// Pull ourself from the global obj list.
|
// Pull ourself from the global obj list.
|
||||||
std::scoped_lock lock(g_core->object_list_mutex);
|
std::scoped_lock lock(g_core->object_list_mutex);
|
||||||
@ -70,6 +68,7 @@ Object::~Object() {
|
|||||||
#endif // BA_DEBUG_BUILD
|
#endif // BA_DEBUG_BUILD
|
||||||
|
|
||||||
// Invalidate all our weak refs.
|
// Invalidate all our weak refs.
|
||||||
|
//
|
||||||
// We could call Release() on each but we'd have to deactivate the
|
// We could call Release() on each but we'd have to deactivate the
|
||||||
// thread-check since virtual functions won't work as expected in a
|
// thread-check since virtual functions won't work as expected in a
|
||||||
// destructor. Also we can take a few shortcuts here since we know
|
// destructor. Also we can take a few shortcuts here since we know
|
||||||
@ -85,7 +84,6 @@ Object::~Object() {
|
|||||||
|
|
||||||
auto Object::GetObjectTypeName() const -> std::string {
|
auto Object::GetObjectTypeName() const -> std::string {
|
||||||
// Default implementation just returns type name.
|
// Default implementation just returns type name.
|
||||||
// Note: using core's globals directly; don't normally do this!
|
|
||||||
if (g_core) {
|
if (g_core) {
|
||||||
return g_core->platform->DemangleCXXSymbol(typeid(*this).name());
|
return g_core->platform->DemangleCXXSymbol(typeid(*this).name());
|
||||||
}
|
}
|
||||||
@ -112,7 +110,6 @@ auto Object::GetThreadOwnership() const -> Object::ThreadOwnership {
|
|||||||
|
|
||||||
void Object::LsObjects() {
|
void Object::LsObjects() {
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
// Note: using core's internal globals here; don't normally do this.
|
|
||||||
assert(g_core);
|
assert(g_core);
|
||||||
std::string s;
|
std::string s;
|
||||||
{
|
{
|
||||||
@ -192,12 +189,12 @@ void Object::ObjectUpdateForAcquire() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::ObjectThreadCheck() {
|
void Object::ObjectThreadCheck() const {
|
||||||
if (!thread_checks_enabled_) {
|
if (!thread_checks_enabled_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadOwnership thread_ownership = GetThreadOwnership();
|
auto thread_ownership = GetThreadOwnership();
|
||||||
|
|
||||||
// Special case; graphics context (not simply a thread so have to handle
|
// Special case; graphics context (not simply a thread so have to handle
|
||||||
// specially).
|
// specially).
|
||||||
|
|||||||
@ -12,23 +12,26 @@
|
|||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
/// Objects supporting strong and weak referencing and thread enforcement.
|
/// Objects supporting strong and weak referencing and thread enforcement.
|
||||||
/// A rule or two for for Objects:
|
|
||||||
/// Don't throw exceptions out of object destructors;
|
|
||||||
/// This will break references to that object and lead to crashes if/when they
|
|
||||||
/// are used.
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
protected:
|
||||||
|
/// Our base constructor is marked protected because we *require* Objects
|
||||||
|
/// to be dynamically allocated. This allows us extra measures of control
|
||||||
|
/// over their construction and destruction, and it does not seem that
|
||||||
|
/// there is a pressing use case for a statically allocated Object that
|
||||||
|
/// would justify diluting that control.
|
||||||
Object();
|
Object();
|
||||||
|
|
||||||
|
public:
|
||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
|
|
||||||
// Object classes can provide descriptive names for themselves;
|
// Object classes can provide descriptive names for themselves; these are
|
||||||
// these are used for debugging and other purposes.
|
// used for debugging and other purposes. The default is to use the C++
|
||||||
// The default is to use the C++ symbol name, demangling it when possible.
|
// symbol name, demangling it when possible. IMPORTANT: Do not rely on
|
||||||
// IMPORTANT: Do not rely on this being consistent across builds/platforms.
|
// this being consistent across builds/platforms.
|
||||||
virtual auto GetObjectTypeName() const -> std::string;
|
virtual auto GetObjectTypeName() const -> std::string;
|
||||||
|
|
||||||
// Provide a brief description of this particular object; by default returns
|
// Provide a brief description of this particular object; by default
|
||||||
// type-name plus address.
|
// returns type-name plus address.
|
||||||
virtual auto GetObjectDescription() const -> std::string;
|
virtual auto GetObjectDescription() const -> std::string;
|
||||||
|
|
||||||
enum class ThreadOwnership {
|
enum class ThreadOwnership {
|
||||||
@ -42,25 +45,26 @@ class Object {
|
|||||||
|
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
|
|
||||||
/// This is called when adding or removing a reference to an Object;
|
/// This is called when adding or removing a reference to an Object; it
|
||||||
/// it can perform sanity-tests to make sure references are not being
|
/// can perform sanity-tests to make sure references are not being added
|
||||||
/// added at incorrect times or from incorrect threads.
|
/// at incorrect times or from incorrect threads. The default
|
||||||
/// The default implementation uses the per-object
|
/// implementation uses the per-object ThreadOwnership/EventLoopID values
|
||||||
/// ThreadOwnership/EventLoopID values accessible below. NOTE: this
|
/// accessible below.
|
||||||
/// check runs only in the debug build so don't add any logical side-effects!
|
///
|
||||||
virtual void ObjectThreadCheck();
|
/// NOTE: This check runs *only* in the debug build so don't include any
|
||||||
|
/// logical side-effects in these checks!
|
||||||
|
void ObjectThreadCheck() const;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Called by the default ObjectThreadCheck() to determine ThreadOwnership
|
/// Called by the default ObjectThreadCheck() to determine ownership for
|
||||||
/// for an Object. The default uses the object's individual value
|
/// an Object. By default, an object is owned by a specific thread,
|
||||||
/// (which defaults to ThreadOwnership::kClassDefault and can be set via
|
/// defaulting to the logic thread.
|
||||||
/// SetThreadOwnership())
|
|
||||||
virtual auto GetThreadOwnership() const -> ThreadOwnership;
|
virtual auto GetThreadOwnership() const -> ThreadOwnership;
|
||||||
|
|
||||||
/// Return the exact thread to check for with ThreadOwnership::kClassDefault
|
/// Return the exact thread to check for with
|
||||||
/// (in the default ObjectThreadCheck implementation at least).
|
/// ThreadOwnership::kClassDefault (in the default ObjectThreadCheck
|
||||||
/// Default returns EventLoopID::kLogic
|
/// implementation at least). Default returns EventLoopID::kLogic
|
||||||
virtual auto GetDefaultOwnerThread() const -> EventLoopID;
|
virtual auto GetDefaultOwnerThread() const -> EventLoopID;
|
||||||
|
|
||||||
/// Set thread ownership for an individual object.
|
/// Set thread ownership for an individual object.
|
||||||
@ -73,12 +77,12 @@ class Object {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the provided obj ptr is not null, is ref-counted, and has at
|
// Return true if the provided obj ptr is not null, is ref-counted, and
|
||||||
// least 1 strong ref. This is generally a good thing for calls accepting
|
// has at least 1 strong ref. This is generally a good thing for calls
|
||||||
// object ptrs to check. It is considered bad practice to perform operations
|
// accepting object ptrs to check. It is considered bad practice to
|
||||||
// with not-yet-reffed objects. Note that in some cases this may return
|
// perform operations with not-yet-reffed objects. Note that in some cases
|
||||||
// false positives, so only use this as a sanity check and only take action
|
// this may return false positives, so only use this as a sanity check and
|
||||||
// for a negative result.
|
// only take action for a negative result.
|
||||||
static auto IsValidManagedObject(Object* obj) -> bool {
|
static auto IsValidManagedObject(Object* obj) -> bool {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return false;
|
return false;
|
||||||
@ -91,11 +95,11 @@ class Object {
|
|||||||
return (obj->object_strong_ref_count_ > 0);
|
return (obj->object_strong_ref_count_ > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the object seems to be valid and was allocated as unmanaged.
|
// Return true if the object seems to be valid and was allocated as
|
||||||
// Code that plans to explicitly delete raw passed pointers can check this
|
// unmanaged. Code that plans to explicitly delete raw passed pointers can
|
||||||
// for peace of mind. Note that for some build types this will return false
|
// check this for peace of mind. Note that for some build types this will
|
||||||
// positives, so only use this as a sanity check and only take action for
|
// return false positives, so only use this as a sanity check and only
|
||||||
// negative results.
|
// take action for negative results.
|
||||||
static auto IsValidUnmanagedObject(Object* obj) -> bool {
|
static auto IsValidUnmanagedObject(Object* obj) -> bool {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return false;
|
return false;
|
||||||
@ -108,12 +112,53 @@ class Object {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// We don't store specifics in release builds; assume everything is peachy.
|
// We don't store specifics in release builds; assume everything is
|
||||||
|
// peachy.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto object_strong_ref_count() const -> int {
|
auto object_strong_ref_count() const -> int {
|
||||||
return object_strong_ref_count_;
|
return object_strong_ref_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Increment the strong reference count for an Object. In most cases you
|
||||||
|
/// should let Ref objects handle this for you and not call this directly.
|
||||||
|
void ObjectIncrementStrongRefCount() {
|
||||||
|
#if BA_DEBUG_BUILD
|
||||||
|
ObjectUpdateForAcquire();
|
||||||
|
ObjectThreadCheck();
|
||||||
|
|
||||||
|
// Obvs shouldn't be referencing dead stuff.
|
||||||
|
assert(!object_is_dead_);
|
||||||
|
|
||||||
|
// Complain if trying ot create a ref to a non-ref-counted obj.
|
||||||
|
if (!object_is_ref_counted_) {
|
||||||
|
FatalError("Attempting to create a strong-ref to non-refcounted obj: "
|
||||||
|
+ GetObjectDescription());
|
||||||
|
}
|
||||||
|
object_has_been_strong_reffed_ = true;
|
||||||
|
#endif // BA_DEBUG_BUILD
|
||||||
|
|
||||||
|
object_strong_ref_count_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrement the strong reference count for the Object, deleting it if it
|
||||||
|
/// hits zero. In most cases you should let Ref objects handle this for
|
||||||
|
/// you and not call this directly.
|
||||||
|
void ObjectDecrementStrongRefCount() {
|
||||||
|
#if BA_DEBUG_BUILD
|
||||||
|
ObjectThreadCheck();
|
||||||
|
#endif
|
||||||
|
assert(object_strong_ref_count_ > 0);
|
||||||
|
object_strong_ref_count_--;
|
||||||
|
if (object_strong_ref_count_ == 0) {
|
||||||
|
#if BA_DEBUG_BUILD
|
||||||
|
object_is_dead_ = true;
|
||||||
|
#endif
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T = Object>
|
template <typename T = Object>
|
||||||
class Ref;
|
class Ref;
|
||||||
template <typename T = Object>
|
template <typename T = Object>
|
||||||
@ -193,9 +238,8 @@ class Object {
|
|||||||
PyExcType::kReference);
|
PyExcType::kReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes, reinterpret_cast is evil, but we make sure
|
// Yes, reinterpret_cast is evil, but we make sure we only operate on
|
||||||
// we only operate on cases where this is valid
|
// cases where this is valid (see Acquire()).
|
||||||
// (see Acquire()).
|
|
||||||
return *reinterpret_cast<T*>(obj_);
|
return *reinterpret_cast<T*>(obj_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +251,8 @@ class Object {
|
|||||||
PyExcType::kReference);
|
PyExcType::kReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes, reinterpret_cast is evil, but we make sure we only operate
|
// Yes, reinterpret_cast is evil, but we make sure we only operate on
|
||||||
// on cases where this is valid (see Acquire()).
|
// cases where this is valid (see Acquire()).
|
||||||
return reinterpret_cast<T*>(obj_);
|
return reinterpret_cast<T*>(obj_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,8 +307,8 @@ class Object {
|
|||||||
auto operator=(U* ptr) -> WeakRef<T>& {
|
auto operator=(U* ptr) -> WeakRef<T>& {
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
// Go through our template type instead of assigning directly
|
// Go through our template type instead of assigning directly to our
|
||||||
// to our Object* so we catch invalid assigns at compile-time.
|
// Object* so we catch invalid assigns at compile-time.
|
||||||
T* tmp = ptr;
|
T* tmp = ptr;
|
||||||
if (tmp) Acquire(tmp);
|
if (tmp) Acquire(tmp);
|
||||||
|
|
||||||
@ -295,13 +339,13 @@ class Object {
|
|||||||
// Default constructor.
|
// Default constructor.
|
||||||
WeakRef() = default;
|
WeakRef() = default;
|
||||||
|
|
||||||
/// Copy constructor. Note that, by making this explicit, we require code
|
/// Copy constructor. Note that, by making this explicit, we require
|
||||||
/// to be a bit more verbose. For example, we can't just do 'return
|
/// code to be a bit more verbose. For example, we can't just do 'return
|
||||||
/// some_ref;' from a function and instead have to do 'return
|
/// some_ref;' from a function that returns a WeakRef and instead have
|
||||||
/// Object::WeakRef<SomeType>(some_ref)'. However I feel this extra
|
/// to do 'return Object::WeakRef<SomeType>(some_ref)'. However I feel
|
||||||
/// verbosity is good; we're tossing around a mix of pointers and
|
/// this extra verbosity is good; we're tossing around a mix of pointers
|
||||||
/// strong-refs and weak-refs so it's good to be aware exactly where refs
|
/// and strong-refs and weak-refs so it's good to be aware exactly where
|
||||||
/// are being added/etc.
|
/// refs are being added/etc.
|
||||||
explicit WeakRef(const WeakRef<T>& ref) { *this = ref.Get(); }
|
explicit WeakRef(const WeakRef<T>& ref) { *this = ref.Get(); }
|
||||||
|
|
||||||
/// Create from a pointer of any compatible type.
|
/// Create from a pointer of any compatible type.
|
||||||
@ -469,13 +513,13 @@ class Object {
|
|||||||
/// Default constructor.
|
/// Default constructor.
|
||||||
Ref() = default;
|
Ref() = default;
|
||||||
|
|
||||||
/// Copy constructor. Note that, by making this explicit, we require code
|
/// Copy constructor. Note that, by making this explicit, we require
|
||||||
/// to be a bit more verbose. For example, we can't just do 'return
|
/// code to be a bit more verbose. For example, we can't just do 'return
|
||||||
/// some_ref;' from a function and instead have to do 'return
|
/// some_ref;' from a function that returns a Ref and instead have to do
|
||||||
/// Object::Ref<SomeType>(some_ref)'. However I feel this extra verbosity
|
/// 'return Object::Ref<SomeType>(some_ref)'. However I feel this extra
|
||||||
/// is good; we're tossing around a mix of pointers and strong-refs and
|
/// verbosity is good; we're tossing around a mix of pointers and
|
||||||
/// weak-refs so it's good to be aware exactly where refs are being
|
/// strong-refs and weak-refs so it's good to be aware exactly where
|
||||||
/// added/etc.
|
/// refs are being added/etc.
|
||||||
explicit Ref(const Ref<T>& ref) { *this = ref.Get(); }
|
explicit Ref(const Ref<T>& ref) { *this = ref.Get(); }
|
||||||
|
|
||||||
/// Create from a compatible pointer.
|
/// Create from a compatible pointer.
|
||||||
@ -505,42 +549,16 @@ class Object {
|
|||||||
PyExcType::kReference);
|
PyExcType::kReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BA_DEBUG_BUILD
|
obj->ObjectIncrementStrongRefCount();
|
||||||
obj->ObjectUpdateForAcquire();
|
|
||||||
obj->ObjectThreadCheck();
|
|
||||||
|
|
||||||
// Obvs shouldn't be referencing dead stuff.
|
|
||||||
assert(!obj->object_is_dead_);
|
|
||||||
|
|
||||||
// Complain if trying ot create a ref to a non-ref-counted obj.
|
|
||||||
if (!obj->object_is_ref_counted_) {
|
|
||||||
FatalError("Attempting to create a strong-ref to non-refcounted obj: "
|
|
||||||
+ obj->GetObjectDescription());
|
|
||||||
}
|
|
||||||
obj->object_has_been_strong_reffed_ = true;
|
|
||||||
#endif // BA_DEBUG_BUILD
|
|
||||||
|
|
||||||
obj->object_strong_ref_count_++;
|
|
||||||
obj_ = obj;
|
obj_ = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release() {
|
void Release() {
|
||||||
if (obj_ != nullptr) {
|
if (obj_ != nullptr) {
|
||||||
#if BA_DEBUG_BUILD
|
auto* obj = obj_;
|
||||||
obj_->ObjectThreadCheck();
|
// Invalidate ref *before* to avoid potential recursive-release.
|
||||||
#endif
|
|
||||||
assert(obj_->object_strong_ref_count_ > 0);
|
|
||||||
obj_->object_strong_ref_count_--;
|
|
||||||
T* tmp = obj_;
|
|
||||||
|
|
||||||
// Invalidate ref *before* delete to avoid potential double-release.
|
|
||||||
obj_ = nullptr;
|
obj_ = nullptr;
|
||||||
if (tmp->object_strong_ref_count_ == 0) {
|
obj->ObjectDecrementStrongRefCount();
|
||||||
#if BA_DEBUG_BUILD
|
|
||||||
tmp->object_is_dead_ = true;
|
|
||||||
#endif
|
|
||||||
delete tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T* obj_{};
|
T* obj_{};
|
||||||
@ -549,10 +567,10 @@ class Object {
|
|||||||
/// Object::New<Type>(): The preferred way to create ref-counted Objects.
|
/// Object::New<Type>(): The preferred way to create ref-counted Objects.
|
||||||
/// Allocates a new Object with the provided args and returns a strong
|
/// Allocates a new Object with the provided args and returns a strong
|
||||||
/// reference to it.
|
/// reference to it.
|
||||||
/// Generally you pass a single type to be instantiated and returned,
|
///
|
||||||
/// but you can optionally specify the two separately.
|
/// Generally you pass a single type to be instantiated and returned, but
|
||||||
/// (for instance you may want to create a Button but return
|
/// you can optionally specify the two separately. For example, you may
|
||||||
/// a Ref to a Widget)
|
/// want to create a Button but return a Ref to a Widget.
|
||||||
template <typename TRETURN, typename TALLOC = TRETURN, typename... ARGS>
|
template <typename TRETURN, typename TALLOC = TRETURN, typename... ARGS>
|
||||||
[[nodiscard]] static auto New(ARGS&&... args) -> Object::Ref<TRETURN> {
|
[[nodiscard]] static auto New(ARGS&&... args) -> Object::Ref<TRETURN> {
|
||||||
auto* ptr = new TALLOC(std::forward<ARGS>(args)...);
|
auto* ptr = new TALLOC(std::forward<ARGS>(args)...);
|
||||||
@ -642,17 +660,19 @@ class Object {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
// Making operator new private here to help ensure all of our dynamic
|
// Making operator new private here purely to help enforce all of our
|
||||||
// allocation/deallocation goes through our special functions (New(),
|
// dynamic allocation/deallocation going through our special functions
|
||||||
// NewDeferred(), etc.). However, sticking with original new for release
|
// (New(), NewDeferred(), etc.). However, sticking with original new for
|
||||||
// builds since it may handle corner cases that this does not.
|
// release builds since we don't actually intend to muck with its runtime
|
||||||
|
// behavior and the default might be somehow smarter than ours here.
|
||||||
auto operator new(size_t size) -> void* { return new char[size]; }
|
auto operator new(size_t size) -> void* { return new char[size]; }
|
||||||
void ObjectUpdateForAcquire();
|
void ObjectUpdateForAcquire();
|
||||||
bool object_has_been_strong_reffed_{};
|
|
||||||
bool object_is_ref_counted_{};
|
bool object_has_been_strong_reffed_ : 1 {};
|
||||||
bool object_is_pending_deferred_{};
|
bool object_is_ref_counted_ : 1 {};
|
||||||
bool object_is_unmanaged_{};
|
bool object_is_pending_deferred_ : 1 {};
|
||||||
bool object_is_dead_{};
|
bool object_is_unmanaged_ : 1 {};
|
||||||
|
bool object_is_dead_ : 1 {};
|
||||||
Object* object_next_{};
|
Object* object_next_{};
|
||||||
Object* object_prev_{};
|
Object* object_prev_{};
|
||||||
ThreadOwnership thread_ownership_{ThreadOwnership::kClassDefault};
|
ThreadOwnership thread_ownership_{ThreadOwnership::kClassDefault};
|
||||||
@ -661,8 +681,8 @@ class Object {
|
|||||||
millisecs_t object_birth_time_{};
|
millisecs_t object_birth_time_{};
|
||||||
bool object_printed_warning_{};
|
bool object_printed_warning_{};
|
||||||
#endif
|
#endif
|
||||||
int object_strong_ref_count_{};
|
|
||||||
WeakRefBase* object_weak_refs_{};
|
WeakRefBase* object_weak_refs_{};
|
||||||
|
int object_strong_ref_count_{};
|
||||||
BA_DISALLOW_CLASS_COPIES(Object);
|
BA_DISALLOW_CLASS_COPIES(Object);
|
||||||
}; // Object
|
}; // Object
|
||||||
|
|
||||||
|
|||||||
26
src/ballistica/shared/generic/snapshot.h
Normal file
26
src/ballistica/shared/generic/snapshot.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
#ifndef BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_
|
||||||
|
#define BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_
|
||||||
|
|
||||||
|
#include "ballistica/shared/foundation/object.h"
|
||||||
|
|
||||||
|
namespace ballistica {
|
||||||
|
|
||||||
|
/// Wraps a const instance of some type in a logic-thread-owned Object. To
|
||||||
|
/// use this, allocate some object using new(), fill it out, and pass it to
|
||||||
|
/// this which will take ownership and expose it as a const.
|
||||||
|
template <typename T>
|
||||||
|
class Snapshot : public Object {
|
||||||
|
public:
|
||||||
|
explicit Snapshot(T* data) : data_{data} { assert(data); }
|
||||||
|
~Snapshot() { delete data_; }
|
||||||
|
auto* Get() const { return data_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T* data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ballistica
|
||||||
|
|
||||||
|
#endif // BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_
|
||||||
@ -307,7 +307,7 @@ int establish_connection_(const struct Context_* ctx) {
|
|||||||
retry_attempt + 1);
|
retry_attempt + 1);
|
||||||
}
|
}
|
||||||
} else if (errno == ECONNREFUSED) {
|
} else if (errno == ECONNREFUSED) {
|
||||||
// Am seeing this very rarely on random one-off commands. I'm
|
// Am seeing these very rarely on random one-off commands. I'm
|
||||||
// guessing there's some race condition at the OS level where the
|
// guessing there's some race condition at the OS level where the
|
||||||
// port-file write goes through before the socket is actually truly
|
// port-file write goes through before the socket is actually truly
|
||||||
// accepting connections. A retry should succeed.
|
// accepting connections. A retry should succeed.
|
||||||
@ -318,6 +318,15 @@ int establish_connection_(const struct Context_* ctx) {
|
|||||||
ctx->instance_prefix, ctx->instance_num, ctx->pid,
|
ctx->instance_prefix, ctx->instance_num, ctx->pid,
|
||||||
retry_attempt + 1);
|
retry_attempt + 1);
|
||||||
}
|
}
|
||||||
|
} else if (errno == EINVAL) {
|
||||||
|
// Saw this randomly once on Mac. Not sure what could have led to it.
|
||||||
|
if (ctx->verbose) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"pcommandbatch client %s_%d (pid %d): got EINVAL"
|
||||||
|
" on connect attempt %d.\n",
|
||||||
|
ctx->instance_prefix, ctx->instance_num, ctx->pid,
|
||||||
|
retry_attempt + 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Currently not retrying on other errors.
|
// Currently not retrying on other errors.
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|||||||
@ -983,8 +983,8 @@ class XCodeBuild:
|
|||||||
# on to clarify in that case (unless requested not to).
|
# on to clarify in that case (unless requested not to).
|
||||||
assert self._section is not None
|
assert self._section is not None
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
f'{Clr.YLW}Unexpected {self._section.value}'
|
f'{Clr.YLW}Unfiltered Output (Section {self._section.value}):'
|
||||||
f' Output:{Clr.RST} {line}'
|
f'{Clr.RST} {line}'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(line)
|
sys.stdout.write(line)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user