From a2ea720bb900f70291609661329cb1de938e5665 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 5 Oct 2023 11:56:14 -0700 Subject: [PATCH] Cleaned up the ballistica::Object class and its reference types to try and minimize ambiguity --- .efrocachemap | 90 ++--- CHANGELOG.md | 5 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/assets/assets.cc | 12 +- .../base/graphics/text/text_graphics.cc | 2 +- src/ballistica/base/input/input.cc | 2 +- src/ballistica/scene_v1/assets/scene_asset.h | 2 +- src/ballistica/scene_v1/node/flag_node.h | 2 +- .../python_class_scene_collision_mesh.cc | 3 +- .../class/python_class_scene_data_asset.cc | 2 +- .../python/class/python_class_scene_mesh.cc | 2 +- .../python/class/python_class_scene_sound.cc | 2 +- .../class/python_class_scene_texture.cc | 2 +- .../scene_v1/support/host_activity.cc | 2 +- .../scene_v1/support/host_session.cc | 2 +- src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/shared/foundation/object.h | 325 +++++++++--------- src/ballistica/shared/foundation/types.h | 1 + src/ballistica/shared/python/python.cc | 3 + .../ui_v1/widget/container_widget.cc | 2 +- 20 files changed, 245 insertions(+), 220 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 4a14d1db..168912e9 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -1,5 +1,5 @@ { - "ballisticakit-windows/Generic/BallisticaKit.ico": "0611a2b624f01b5e6939f2dd810add5b", + "ballisticakit-windows/Generic/BallisticaKit.ico": "be1b956dcd7f7a261b1afe5bce2a0336", "build/assets/ba_data/audio/achievement.ogg": "079a366ce183b25a63550ef7072af605", "build/assets/ba_data/audio/actionHero1.ogg": "f0f986f268f036a5ac2f940e07f2f27e", "build/assets/ba_data/audio/actionHero2.ogg": "204a6735dc655f0975cf8308b585f2fd", @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "00df85426f2fd425284d788ad2001163", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "ec7fd15e05dc966ed5fe2dc53082b8dc", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5a07480211a13748414bccdb33ab50e0", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "cee4f0b1f606e2cd4e0084821803bbda", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ec670868f9b49d8b300e7c096d45fccd", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "55e11d3f9f2dafbe4a785ad8d53a5191", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "66a165dce9b2576796b61a0190ee2360", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "0973f550afc8dc1a966f0cf34119bdee", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "be55036d49b2aac4f7fb34acda7ae46a", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0b5b2fcbe365f1465d1eaf6663efddef", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "198ab1ae413439560c94e7e70dccb8e1", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "832d429448bf666876ecc2dfbdce6ac1", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "42a60e06d573fd770bf085d1de1e8426", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "4b3b7f626517f5b83973e23728182fa0", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b7b82fe0bef26f414f952038982ba94c", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "99156961b81f9849e7055f5e73449735", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "93ae112921fa541badb6844eb913b825", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "08a27186747d3a1fe854014243d39550", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "10ec7da590f68e1cc1a6f9b9ed4abf25", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c76a8d161dae2b3ec3ae2898803e6387", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "76d9f578bc7395af5ddef379a85e6354", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "48dd3167591df4494852c6c3e9047f1b", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "76d9f578bc7395af5ddef379a85e6354", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "48dd3167591df4494852c6c3e9047f1b", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "4a757f9ede607532cd5c8c2589f05bb4", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "9a9e18d3856e343c3ca6ac136a64235a", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "4a757f9ede607532cd5c8c2589f05bb4", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "9a9e18d3856e343c3ca6ac136a64235a", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "da8bef9f3989024b8f45b7c27d41ce06", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f2f9159cd08054e71ed87db479b18d21", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "da8bef9f3989024b8f45b7c27d41ce06", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f2f9159cd08054e71ed87db479b18d21", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "dfb64c08a34939df60bae54579cc662c", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0c0e93911fda8343f06b76a84b2331a3", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "5414ebd032c5b437f0b6a6ea952667d0", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0c0e93911fda8343f06b76a84b2331a3", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c376e54bfa43c7411464c86b7ebbe7d2", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "92509f7dbfdd5628f71a9f5e0453c1de", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "187084265adac8497ebd6f43b82c6a9f", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "bf66ac68f2d9deea5f310e3e8a40e4da", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c570f55f73054b411dbaca428062c3d7", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "0fa9d0afbbe2fb2de1a19a6be66d04d2", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c08bdaebba8bbbe2a92a6c17b11a8ccc", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "17809e9b9a2e62cb49d952ac41d79a13", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6cdefa5cd565abee912694fb28d828d3", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "c51444bf5d10839e45a347c3200a6055", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0ab2bbf81b5a23d9cd0df2c8c71d1df8", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "767696047eb3faa9dcab8edcef4e776b", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "18ef5fd23969bbd009bb1360a161fca4", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "680935c4c7d3cfe1d74afdb5376c55a2", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "7fd4da4a5ef6ed013fad3e5ab360cbae", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "65fa11a84646d483601ee37a0c1ba653", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "530214ddb822998dfdb61107dded1802", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "52924ddffd34be9cb9b78ef4757a7f45", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a9b3849992aa832e2265f626e46773f4", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e56702bd5e1fd7e5c613ea6dd4b8801a", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "c96db4026b4ff8d7b2f6fd189778db50", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "de5638c952f8d71b26235f30bc957f2c", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "17d898335005122c303ea1811dd06c77", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0941c6dfb7b7a5ebfc0e4e8f93cb3fb7", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "cdcdb3a9fc357e025ce2ed6d864a0e80", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d68b729ed88d9eef64bc1a40cc34b67f", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "fa3cd09737f23271f66ca7d7bb1e629a", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "4ea0a028f40afc4456135f34a95d652b", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "dd14e0abacf5a27d9823b0a41127e3e3", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bd994ca8a1896ada5c582be155db5c36", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "dd14e0abacf5a27d9823b0a41127e3e3", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "bd994ca8a1896ada5c582be155db5c36", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d855693f8342c4080ce0f452784e5cf9", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "eeaf4e383752fdcdaaae1cb863208870", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d855693f8342c4080ce0f452784e5cf9", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "eeaf4e383752fdcdaaae1cb863208870", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "ba391e47cc87b609ea794cdf9e693163", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "84e913835ae280a59045bed189c920b0", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "ba391e47cc87b609ea794cdf9e693163", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "84e913835ae280a59045bed189c920b0", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8f147ca53e6e261becb37d7ff5490b59", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "7d386ab4fc78cc7598188df82bf4f04a", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "5627e6b08b61024650420b849d41721b", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "7d386ab4fc78cc7598188df82bf4f04a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "36dc4b524796e12a1bda3dd96cc5a102", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "6e97a4ada89c867ea6795b792a37091a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "1aeee25b763b80b7f291e5adfd025557", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6903271f88d2a904fb0394e99098f746", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c2888b185b9ac3ddae1db665839765b5", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e7a19af8da2c3910080d411a11429723", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "9093de58a5aa33b8061057ac500a3f6d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "93dcf1b0a3d140c51eb550e6d95128d1", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318", "src/ballistica/base/mgen/pyembed/binding_base.inc": "9f71f171464dc004dbaab87e9bb4b03b", diff --git a/CHANGELOG.md b/CHANGELOG.md index 614ec1ad..79129316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21418, api 8, 2023-10-05) +### 1.7.28 (build 21421, api 8, 2023-10-05) - 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 @@ -101,6 +101,9 @@ - Now that all our compilers support it, updating from the C++17 standard to C++20. This will allow a few useful things such as being able to pack 8 bools into 1 byte. +- Created a custom icon for BallisticaKit (previously it was just the BombSquad + icon with an ugly 'C' on it). BombSquad itself will still have the BombSquad + icon. ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 71ed5bcf..b6be797c 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21418 +TARGET_BALLISTICA_BUILD = 21421 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/assets/assets.cc b/src/ballistica/base/assets/assets.cc index db0b5bde..4a1f1bc6 100644 --- a/src/ballistica/base/assets/assets.cc +++ b/src/ballistica/base/assets/assets.cc @@ -473,7 +473,7 @@ auto Assets::GetAsset(const std::string& file_name, MarkAssetForLoad(d.Get()); } d->set_last_used_time(g_core->GetAppTimeMillisecs()); - return d; + return Object::Ref(d); } } @@ -485,7 +485,7 @@ auto Assets::GetTexture(TextPacker* packer) -> Object::Ref { if (i != text_textures_.end()) { return Object::Ref(i->second.Get()); } else { - auto d(Object::New(packer)); + auto d{Object::New(packer)}; text_textures_[hash] = d; { Asset::LockGuard lock(d.Get()); @@ -493,7 +493,7 @@ auto Assets::GetTexture(TextPacker* packer) -> Object::Ref { MarkAssetForLoad(d.Get()); } d->set_last_used_time(g_core->GetAppTimeMillisecs()); - return d; + return Object::Ref(d); } } @@ -513,7 +513,7 @@ auto Assets::GetQRCodeTexture(const std::string& url) MarkAssetForLoad(d.Get()); } d->set_last_used_time(g_core->GetAppTimeMillisecs()); - return d; + return Object::Ref(d); } } @@ -536,7 +536,7 @@ auto Assets::GetCubeMapTexture(const std::string& file_name) MarkAssetForLoad(d.Get()); } d->set_last_used_time(g_core->GetAppTimeMillisecs()); - return d; + return Object::Ref(d); } } @@ -592,7 +592,7 @@ auto Assets::GetTexture(const std::string& file_name) MarkAssetForLoad(d.Get()); } d->set_last_used_time(g_core->GetAppTimeMillisecs()); - return d; + return Object::Ref(d); } } diff --git a/src/ballistica/base/graphics/text/text_graphics.cc b/src/ballistica/base/graphics/text/text_graphics.cc index f9e5a8d5..5a5cd8de 100644 --- a/src/ballistica/base/graphics/text/text_graphics.cc +++ b/src/ballistica/base/graphics/text/text_graphics.cc @@ -1002,7 +1002,7 @@ void TextGraphics::GetOSTextSpanBoundsAndWidth(const std::string& s, Rect* r, // so let's use a cache of recent results. auto i = text_span_bounds_cache_map_.find(s); if (i != text_span_bounds_cache_map_.end()) { - Object::Ref entry = i->second; + auto entry = Object::Ref(i->second); *r = entry->r; *width = entry->width; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 667773fb..0fde2709 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -369,7 +369,7 @@ void Input::RemoveInputDevice(InputDevice* input, bool standard_message) { if (input_device.Exists() && (input_device.Get() == input)) { // Pull it off the list before killing it (in case it tries to trigger // another kill itself). - Object::Ref device = input_device; + auto device = Object::Ref(input_device); // Ok we cleared its slot in our vector; now we just have // the local variable 'device' keeping it alive. diff --git a/src/ballistica/scene_v1/assets/scene_asset.h b/src/ballistica/scene_v1/assets/scene_asset.h index a9d46fc9..f7eb416d 100644 --- a/src/ballistica/scene_v1/assets/scene_asset.h +++ b/src/ballistica/scene_v1/assets/scene_asset.h @@ -30,7 +30,7 @@ static auto GetAsset(std::unordered_map >* list, // strong-ref to it. auto t(Object::New(name, scene)); (*list)[name] = t; - return t; + return Object::Ref(t); } } diff --git a/src/ballistica/scene_v1/node/flag_node.h b/src/ballistica/scene_v1/node/flag_node.h index ad2caff5..717338cb 100644 --- a/src/ballistica/scene_v1/node/flag_node.h +++ b/src/ballistica/scene_v1/node/flag_node.h @@ -50,7 +50,7 @@ class FlagNode : public Node { base::AreaOfInterest* area_of_interest_ = nullptr; Part part_; std::vector color_ = {1.0f, 1.0f, 1.0f}; - Object::Ref body_{nullptr}; + Object::Ref body_; Object::Ref color_texture_; base::MeshIndexedObjectSplit mesh_; Object::Ref full_shadow_set_; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.cc b/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.cc index 7453bedb..55ccc889 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.cc @@ -12,7 +12,8 @@ namespace ballistica::scene_v1 { auto PythonClassSceneCollisionMesh::tp_repr(PythonClassSceneCollisionMesh* self) -> PyObject* { BA_PYTHON_TRY; - Object::Ref m = *self->collision_mesh_; + assert(self->collision_mesh_); + auto&& m = *self->collision_mesh_; return Py_BuildValue( "s", (std::string("name() + "\"") : "(empty ref)") + ">") diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.cc b/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.cc index 7ed427a7..90fc888f 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.cc @@ -12,7 +12,7 @@ namespace ballistica::scene_v1 { auto PythonClassSceneDataAsset::tp_repr(PythonClassSceneDataAsset* self) -> PyObject* { BA_PYTHON_TRY; - Object::Ref m = *self->data_; + auto&& m = *self->data_; return Py_BuildValue( "s", (std::string("name() + "\"") : "(empty ref)") + ">") diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_mesh.cc b/src/ballistica/scene_v1/python/class/python_class_scene_mesh.cc index 303dc1f2..73ad5c0f 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_mesh.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_mesh.cc @@ -11,7 +11,7 @@ namespace ballistica::scene_v1 { auto PythonClassSceneMesh::tp_repr(PythonClassSceneMesh* self) -> PyObject* { BA_PYTHON_TRY; - Object::Ref m = *(self->mesh_); + auto&& m = *(self->mesh_); return Py_BuildValue( "s", (std::string("name() + "\"") : "(empty ref)") + ">") diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_sound.cc b/src/ballistica/scene_v1/python/class/python_class_scene_sound.cc index 7b660e38..dfc7b95b 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_sound.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_sound.cc @@ -30,7 +30,7 @@ void PythonClassSceneSound::SetupType(PyTypeObject* cls) { auto PythonClassSceneSound::tp_repr(PythonClassSceneSound* self) -> PyObject* { BA_PYTHON_TRY; - Object::Ref m = *(self->sound_); + auto&& m = *(self->sound_); return Py_BuildValue( "s", (std::string("name() + "\"") : "(empty ref)") + ">") diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_texture.cc b/src/ballistica/scene_v1/python/class/python_class_scene_texture.cc index 0fad3617..3c0cd8d6 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_texture.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_texture.cc @@ -12,7 +12,7 @@ namespace ballistica::scene_v1 { auto PythonClassSceneTexture::tp_repr(PythonClassSceneTexture* self) -> PyObject* { BA_PYTHON_TRY; - Object::Ref t = *(self->texture_); + auto&& t = *(self->texture_); return Py_BuildValue( "s", (std::string("name() + "\"") : "(empty ref)") + ">") diff --git a/src/ballistica/scene_v1/support/host_activity.cc b/src/ballistica/scene_v1/support/host_activity.cc index 24bfffd1..5fc1b899 100644 --- a/src/ballistica/scene_v1/support/host_activity.cc +++ b/src/ballistica/scene_v1/support/host_activity.cc @@ -193,7 +193,7 @@ auto HostActivity::NewMaterial(const std::string& name) auto m(Object::New(name, scene())); materials_.emplace_back(m); - return m; + return Object::Ref(m); } auto HostActivity::GetTexture(const std::string& name) diff --git a/src/ballistica/scene_v1/support/host_session.cc b/src/ballistica/scene_v1/support/host_session.cc index 5e7329af..0601c0bb 100644 --- a/src/ballistica/scene_v1/support/host_session.cc +++ b/src/ballistica/scene_v1/support/host_session.cc @@ -275,7 +275,7 @@ void HostSession::RemovePlayer(Player* player) { if (i->Get() == player) { // Grab a ref to keep the player alive, pull him off the list, then call // his leaving callback. - Object::Ref player2 = *i; + auto player2 = Object::Ref(*i); players_.erase(i); // Clear the player's attachment to its host-session so it doesn't diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index a130007f..afb2e7d6 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int { namespace ballistica { // These are set automatically via script; don't modify them here. -const int kEngineBuildNumber = 21418; +const int kEngineBuildNumber = 21421; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/object.h b/src/ballistica/shared/foundation/object.h index 73c16437..8b98b457 100644 --- a/src/ballistica/shared/foundation/object.h +++ b/src/ballistica/shared/foundation/object.h @@ -151,7 +151,7 @@ class Object { friend class Object; }; // WeakRefBase - /// Weak-reference to an instance of a specific Object subclass. + /// A weak-reference to an instance of a specific Object subclass. template class WeakRef : public WeakRefBase { public: @@ -179,11 +179,14 @@ class Object { return reinterpret_cast(obj_); } - // These operators throw exceptions if the object is dead. + // ----------------------------- Operators --------------------------------- + + /// Access the referenced object; throws an Exception if ref is invalid. auto operator*() const -> T& { if (!obj_) { - throw Exception("Dereferencing invalid " + static_type_name() - + " ref."); + throw Exception( + "Dereferencing invalid " + static_type_name() + " ref.", + PyExcType::kReference); } // Yes, reinterpret_cast is evil, but we make sure @@ -191,10 +194,13 @@ class Object { // (see Acquire()). return *reinterpret_cast(obj_); } + + /// Access the referenced object; throws an Exception if ref is invalid. auto operator->() const -> T* { if (!obj_) { - throw Exception("Dereferencing invalid " + static_type_name() - + " ref."); + throw Exception( + "Dereferencing invalid " + static_type_name() + " ref.", + PyExcType::kReference); } // Yes, reinterpret_cast is evil, but we make sure we only operate @@ -202,7 +208,53 @@ class Object { return reinterpret_cast(obj_); } - // Assign/compare with any compatible pointer. + /// Compare to a pointer of any compatible type. + template + auto operator==(U* ptr) -> bool { + return (Get() == ptr); + } + + /// Compare to a pointer of any compatible type. + template + auto operator!=(U* ptr) -> bool { + return (Get() != ptr); + } + + /// Compare to a strong ref of any compatible type. + template + auto operator==(const Ref& ref) -> bool { + return (Get() == ref.Get()); + } + + /// Compare to a strong ref to a compatible type. + template + auto operator!=(const Ref& ref) -> bool { + return (Get() != ref.Get()); + } + + /// Compare to a weak ref of any compatible type. + template + auto operator==(const WeakRef& ref) -> bool { + return (Get() == ref.Get()); + } + + /// Compare to a weak ref of any compatible type. + template + auto operator!=(const WeakRef& ref) -> bool { + return (Get() != ref.Get()); + } + + /// Assign from our exact type. Note: it might seem like our template + /// assigment operator (taking typename U) would cover this case, but + /// that's not how it works. If we remove this, the default generated + /// piecewise assignment operator gets selected as the best match for + /// our exact type and we crash horrifically. + auto operator=(const WeakRef& ref) -> WeakRef& { + *this = ref.Get(); + return *this; + } + + /// Assign from a pointer of any compatible type. template auto operator=(U* ptr) -> WeakRef& { Release(); @@ -219,104 +271,60 @@ class Object { return *this; } - template - auto operator==(U* ptr) -> bool { - return (Get() == ptr); - } - - template - auto operator!=(U* ptr) -> bool { - return (Get() != ptr); - } - - // Assign/compare with same type ref (apparently the template below - // doesn't cover this case?). - // - // Update: Actually now getting errors that - // having both is ambiguous, so maybe can kill these now?.. - - // Update 2: Oops; we (still?) crash without this. - // re-enabling for now. Need to get to the bottom of this. - auto operator=(const WeakRef& ref) -> WeakRef& { - *this = ref.Get(); - return *this; - } - - // auto operator==(const WeakRef& ref) -> bool { - // return (Get() == ref.Get()); - // } - - // auto operator!=(const WeakRef& ref) -> bool { - // return (Get() != ref.Get()); - // } - - // Assign/compare with a compatible weak-ref. - template - auto operator=(const WeakRef& ref) -> WeakRef& { - *this = ref.Get(); - return *this; - } - - template - auto operator==(const WeakRef& ref) -> bool { - return (Get() == ref.Get()); - } - - template - auto operator!=(const WeakRef& ref) -> bool { - return (Get() != ref.Get()); - } - - // Assign/compare with a compatible strong-ref. + /// Assign from a strong ref of any compatible type. template auto operator=(const Ref& ref) -> WeakRef& { *this = ref.Get(); return *this; } + /// Assign from a weak ref of any compatible type (except our exact + /// type which has its own overload). template - auto operator==(const Ref& ref) -> bool { - return (Get() == ref.Get()); + auto operator=(const WeakRef& ref) -> WeakRef& { + *this = ref.Get(); + return *this; } - template - auto operator!=(const Ref& ref) -> bool { - return (Get() != ref.Get()); - } + // ---------------------------- Constructors ------------------------------- - // Various constructors: - - // Empty. + // Default constructor. WeakRef() = default; - // From our type pointer. - explicit WeakRef(T* obj) { *this = obj; } + /// Copy constructor. Note that, by making this explicit, we require 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 + /// Object::WeakRef(some_ref)'. However I feel this extra + /// verbosity is good; we're tossing around a mix of pointers and + /// strong-refs and weak-refs so it's good to be aware exactly where refs + /// are being added/etc. + explicit WeakRef(const WeakRef& ref) { *this = ref.Get(); } - // Copy constructor (only non-explicit one). - WeakRef(const WeakRef& ref) { *this = ref.Get(); } - - // From a compatible pointer. + /// Create from a pointer of any compatible type. template explicit WeakRef(U* ptr) { *this = ptr; } - // From a compatible strong ref. + /// Create from a strong ref of any compatible type. template explicit WeakRef(const Ref& ref) { *this = ref; } - // From a compatible weak ref. + /// Create from a weak ref of any compatible type. template explicit WeakRef(const WeakRef& ref) { *this = ref; } + // ------------------------------------------------------------------------- + private: void Acquire(T* obj) { if (obj == nullptr) { - throw Exception("Acquiring invalid ptr of " + static_type_name()); + throw Exception("Acquiring invalid ptr of " + static_type_name(), + PyExcType::kReference); } #if BA_DEBUG_BUILD @@ -355,22 +363,8 @@ class Object { ~Ref() { Release(); } auto Get() const -> T* { return obj_; } - // These operators throw an Exception if the object is dead. - auto operator*() const -> T& { - if (!obj_) { - throw Exception("Dereferencing invalid " + static_type_name() - + " ref."); - } - return *obj_; - } - auto operator->() const -> T* { - if (!obj_) { - throw Exception("Dereferencing invalid " + static_type_name() - + " ref."); - } - return obj_; - } auto Exists() const -> bool { return (obj_ != nullptr); } + void Clear() { Release(); } /// Convenience wrapper for Object::IsValidManagedObject. @@ -381,7 +375,67 @@ class Object { return false; } - // Assign/compare with any compatible pointer. + // ----------------------------- Operators --------------------------------- + + /// Access the referenced object; throws an Exception if ref is invalid. + auto operator*() const -> T& { + if (!obj_) { + throw Exception( + "Dereferencing invalid " + static_type_name() + " ref.", + PyExcType::kReference); + } + return *obj_; + } + + /// Access the referenced object; throws an Exception if ref is invalid. + auto operator->() const -> T* { + if (!obj_) { + throw Exception( + "Dereferencing invalid " + static_type_name() + " ref.", + PyExcType::kReference); + } + return obj_; + } + + /// Compare to a pointer of any compatible type. + template + auto operator==(U* ptr) -> bool { + return (Get() == ptr); + } + + /// Compare to a pointer of any compatible type. + template + auto operator!=(U* ptr) -> bool { + return (Get() != ptr); + } + + /// Compare to a strong ref of any compatible type. + template + auto operator==(const Ref& ref) -> bool { + return (Get() == ref.Get()); + } + + /// Compare to a strong ref of any compatible type. + template + auto operator!=(const Ref& ref) -> bool { + return (Get() != ref.Get()); + } + + // Note: we don't need to include comparisons to weak-refs because that + // is handled on the weak-ref side (and we can get ambiguity errors if + // we handle them here too). + + /// Assign from our exact type. Note: it might seem like our template + /// assigment operator (taking typename U) would cover this case, but + /// that's not how it works. If we remove this, the default generated + /// piecewise assignment operator gets selected as the best match for + /// our exact type and we crash horrifically. + auto operator=(const Ref& ref) -> Ref& { + *this = ref.Get(); + return *this; + } + + /// Assign from a pointer of any compatible type. template auto operator=(U* ptr) -> Ref& { Release(); @@ -390,98 +444,61 @@ class Object { } return *this; } - template - auto operator==(U* ptr) -> bool { - return (Get() == ptr); - } - template - auto operator!=(U* ptr) -> bool { - return (Get() != ptr); - } - auto operator==(const Ref& ref) -> bool { return (Get() == ref.Get()); } - auto operator!=(const Ref& ref) -> bool { return (Get() != ref.Get()); } - - // Assign/compare with same type ref (apparently the generic template below - // doesn't cover that case?..) - // DANGER: Seems to still compile if we comment this out, but crashes. - // Should get to the bottom of that. - auto operator=(const Ref& ref) -> Ref& { - assert(this != &ref); // Shouldn't be self-assigning. - *this = ref.Get(); - return *this; - } - - // Assign/compare with a compatible strong-ref. + /// Assign from a strong ref of any compatible type (except our exact + /// type which has its own overload). template auto operator=(const Ref& ref) -> Ref& { *this = ref.Get(); return *this; } - template - auto operator==(const Ref& ref) -> bool { - return (Get() == ref.Get()); - } - - template - auto operator!=(const Ref& ref) -> bool { - return (Get() != ref.Get()); - } - - // Assign from a compatible weak-ref. Comparing to compatible weak-refs - // is covered by the operators on the weak-ref side. + /// Assign from a weak ref to any compatible type. template auto operator=(const WeakRef& ref) -> Ref& { *this = ref.Get(); return *this; } - // These are already covered by the equivalent operators - // on the WeakRef side. - // template - // auto operator==(const WeakRef& ref) -> bool { - // return (Get() == ref.Get()); - // } + // ---------------------------- Constructors ------------------------------- - // template - // auto operator!=(const WeakRef& ref) -> bool { - // return (Get() != ref.Get()); - // } - - // Various constructors: - - // Empty. + /// Default constructor. Ref() = default; - // From our type pointer. - explicit Ref(T* obj) { *this = obj; } + /// Copy constructor. Note that, by making this explicit, we require 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 + /// Object::Ref(some_ref)'. However I feel this extra verbosity + /// is good; we're tossing around a mix of pointers and strong-refs and + /// weak-refs so it's good to be aware exactly where refs are being + /// added/etc. + explicit Ref(const Ref& ref) { *this = ref.Get(); } - // Copy constructor (only non-explicit one). - Ref(const Ref& ref) { *this = ref.Get(); } - - // From a compatible pointer. + /// Create from a compatible pointer. template explicit Ref(U* ptr) { *this = ptr; } - // From a compatible strong ref. + /// Create from a compatible strong ref. template explicit Ref(const Ref& ref) { *this = ref; } - // From a compatible weak ref. + /// Create from a compatible weak ref. template explicit Ref(const WeakRef& ref) { *this = ref; } + // ------------------------------------------------------------------------- + private: void Acquire(T* obj) { if (obj == nullptr) { - throw Exception("Acquiring invalid ptr of " + static_type_name()); + throw Exception("Acquiring invalid ptr of " + static_type_name(), + PyExcType::kReference); } #if BA_DEBUG_BUILD @@ -549,13 +566,13 @@ class Object { /// In some cases it may be handy to allocate an object for ref-counting /// but not actually create references yet. An example is when creating an - /// object in one thread to be passed to another which will own said object. - /// For such cases, allocate using NewDeferred() and then create the initial - /// strong ref in the desired thread using CompleteDeferred(). - /// Note that in debug builds, checks may be run to make sure deferred - /// objects wind up with references added to them at some point. If you - /// want to allocate an object for manual deallocation or permanent - /// existence, use NewUnmanaged() instead. + /// object in one thread to be passed to another which will own said + /// object. For such cases, allocate using NewDeferred() and then create + /// the initial strong ref in the desired thread using CompleteDeferred(). + /// Note that, in debug builds, checks may be run to make sure deferred + /// objects wind up with references added to them at some point. For this + /// reason, if you want to allocate an object for manual deallocation or + /// permanent existence, use NewUnmanaged() instead. template [[nodiscard]] static auto NewDeferred(ARGS&&... args) -> T* { T* ptr = new T(std::forward(args)...); diff --git a/src/ballistica/shared/foundation/types.h b/src/ballistica/shared/foundation/types.h index eebe0b7a..50678979 100644 --- a/src/ballistica/shared/foundation/types.h +++ b/src/ballistica/shared/foundation/types.h @@ -273,6 +273,7 @@ enum class PyExcType { kIndex, kType, kValue, + kReference, kContext, kNotFound, kNodeNotFound, diff --git a/src/ballistica/shared/python/python.cc b/src/ballistica/shared/python/python.cc index e35ca919..567a9831 100644 --- a/src/ballistica/shared/python/python.cc +++ b/src/ballistica/shared/python/python.cc @@ -49,6 +49,9 @@ void Python::SetPythonException(const Exception& exc) { case PyExcType::kValue: pytype = PyExc_ValueError; break; + case PyExcType::kReference: + pytype = PyExc_ReferenceError; + break; case PyExcType::kType: pytype = PyExc_TypeError; break; diff --git a/src/ballistica/ui_v1/widget/container_widget.cc b/src/ballistica/ui_v1/widget/container_widget.cc index 19357160..e88af6b6 100644 --- a/src/ballistica/ui_v1/widget/container_widget.cc +++ b/src/ballistica/ui_v1/widget/container_widget.cc @@ -1268,7 +1268,7 @@ void ContainerWidget::DeleteWidget(Widget* w) { } // Grab a ref until we clear it off the list to avoid funky recursion // issues. - Object::Ref w2 = *i; + auto w2 = Object::Ref(*i); widgets_.erase(i); found = true; break;