Cleaned up the ballistica::Object class and its reference types to try and minimize ambiguity

This commit is contained in:
Eric 2023-10-05 11:56:14 -07:00
parent a3c4d0e07e
commit a2ea720bb9
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
20 changed files with 245 additions and 220 deletions

90
.efrocachemap generated
View File

@ -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/achievement.ogg": "079a366ce183b25a63550ef7072af605",
"build/assets/ba_data/audio/actionHero1.ogg": "f0f986f268f036a5ac2f940e07f2f27e", "build/assets/ba_data/audio/actionHero1.ogg": "f0f986f268f036a5ac2f940e07f2f27e",
"build/assets/ba_data/audio/actionHero2.ogg": "204a6735dc655f0975cf8308b585f2fd", "build/assets/ba_data/audio/actionHero2.ogg": "204a6735dc655f0975cf8308b585f2fd",
@ -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": "00df85426f2fd425284d788ad2001163", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6cdefa5cd565abee912694fb28d828d3",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "ec7fd15e05dc966ed5fe2dc53082b8dc", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "c51444bf5d10839e45a347c3200a6055",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5a07480211a13748414bccdb33ab50e0", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0ab2bbf81b5a23d9cd0df2c8c71d1df8",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "cee4f0b1f606e2cd4e0084821803bbda", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "767696047eb3faa9dcab8edcef4e776b",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ec670868f9b49d8b300e7c096d45fccd", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "18ef5fd23969bbd009bb1360a161fca4",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "55e11d3f9f2dafbe4a785ad8d53a5191", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "680935c4c7d3cfe1d74afdb5376c55a2",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "66a165dce9b2576796b61a0190ee2360", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "7fd4da4a5ef6ed013fad3e5ab360cbae",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "0973f550afc8dc1a966f0cf34119bdee", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "65fa11a84646d483601ee37a0c1ba653",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "be55036d49b2aac4f7fb34acda7ae46a", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "530214ddb822998dfdb61107dded1802",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "0b5b2fcbe365f1465d1eaf6663efddef", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "52924ddffd34be9cb9b78ef4757a7f45",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "198ab1ae413439560c94e7e70dccb8e1", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a9b3849992aa832e2265f626e46773f4",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "832d429448bf666876ecc2dfbdce6ac1", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e56702bd5e1fd7e5c613ea6dd4b8801a",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "42a60e06d573fd770bf085d1de1e8426", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "c96db4026b4ff8d7b2f6fd189778db50",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "4b3b7f626517f5b83973e23728182fa0", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "de5638c952f8d71b26235f30bc957f2c",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b7b82fe0bef26f414f952038982ba94c", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "17d898335005122c303ea1811dd06c77",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "99156961b81f9849e7055f5e73449735", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0941c6dfb7b7a5ebfc0e4e8f93cb3fb7",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "93ae112921fa541badb6844eb913b825", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "cdcdb3a9fc357e025ce2ed6d864a0e80",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "08a27186747d3a1fe854014243d39550", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d68b729ed88d9eef64bc1a40cc34b67f",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "10ec7da590f68e1cc1a6f9b9ed4abf25", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "fa3cd09737f23271f66ca7d7bb1e629a",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c76a8d161dae2b3ec3ae2898803e6387", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "4ea0a028f40afc4456135f34a95d652b",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "76d9f578bc7395af5ddef379a85e6354", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "dd14e0abacf5a27d9823b0a41127e3e3",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "48dd3167591df4494852c6c3e9047f1b", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bd994ca8a1896ada5c582be155db5c36",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "76d9f578bc7395af5ddef379a85e6354", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "dd14e0abacf5a27d9823b0a41127e3e3",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "48dd3167591df4494852c6c3e9047f1b", "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "bd994ca8a1896ada5c582be155db5c36",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "4a757f9ede607532cd5c8c2589f05bb4", "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d855693f8342c4080ce0f452784e5cf9",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "9a9e18d3856e343c3ca6ac136a64235a", "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "eeaf4e383752fdcdaaae1cb863208870",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "4a757f9ede607532cd5c8c2589f05bb4", "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d855693f8342c4080ce0f452784e5cf9",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "9a9e18d3856e343c3ca6ac136a64235a", "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "eeaf4e383752fdcdaaae1cb863208870",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "da8bef9f3989024b8f45b7c27d41ce06", "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "ba391e47cc87b609ea794cdf9e693163",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f2f9159cd08054e71ed87db479b18d21", "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "84e913835ae280a59045bed189c920b0",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "da8bef9f3989024b8f45b7c27d41ce06", "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "ba391e47cc87b609ea794cdf9e693163",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f2f9159cd08054e71ed87db479b18d21", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "84e913835ae280a59045bed189c920b0",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "dfb64c08a34939df60bae54579cc662c", "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8f147ca53e6e261becb37d7ff5490b59",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0c0e93911fda8343f06b76a84b2331a3", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "7d386ab4fc78cc7598188df82bf4f04a",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "5414ebd032c5b437f0b6a6ea952667d0", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "5627e6b08b61024650420b849d41721b",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0c0e93911fda8343f06b76a84b2331a3", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "7d386ab4fc78cc7598188df82bf4f04a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c376e54bfa43c7411464c86b7ebbe7d2", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "36dc4b524796e12a1bda3dd96cc5a102",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "92509f7dbfdd5628f71a9f5e0453c1de", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "6e97a4ada89c867ea6795b792a37091a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "187084265adac8497ebd6f43b82c6a9f", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "1aeee25b763b80b7f291e5adfd025557",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "bf66ac68f2d9deea5f310e3e8a40e4da", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6903271f88d2a904fb0394e99098f746",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c570f55f73054b411dbaca428062c3d7", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c2888b185b9ac3ddae1db665839765b5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "0fa9d0afbbe2fb2de1a19a6be66d04d2", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e7a19af8da2c3910080d411a11429723",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c08bdaebba8bbbe2a92a6c17b11a8ccc", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "9093de58a5aa33b8061057ac500a3f6d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "17809e9b9a2e62cb49d952ac41d79a13", "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/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318", "src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "9f71f171464dc004dbaab87e9bb4b03b", "src/ballistica/base/mgen/pyembed/binding_base.inc": "9f71f171464dc004dbaab87e9bb4b03b",

View File

@ -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, - 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
@ -101,6 +101,9 @@
- Now that all our compilers support it, updating from the C++17 standard to - 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 C++20. This will allow a few useful things such as being able to pack 8 bools
into 1 byte. 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) ### 1.7.27 (build 21282, api 8, 2023-08-30)

View File

@ -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 = 21418 TARGET_BALLISTICA_BUILD = 21421
TARGET_BALLISTICA_VERSION = '1.7.28' TARGET_BALLISTICA_VERSION = '1.7.28'

View File

@ -473,7 +473,7 @@ auto Assets::GetAsset(const std::string& file_name,
MarkAssetForLoad(d.Get()); MarkAssetForLoad(d.Get());
} }
d->set_last_used_time(g_core->GetAppTimeMillisecs()); d->set_last_used_time(g_core->GetAppTimeMillisecs());
return d; return Object::Ref<T>(d);
} }
} }
@ -485,7 +485,7 @@ auto Assets::GetTexture(TextPacker* packer) -> Object::Ref<TextureAsset> {
if (i != text_textures_.end()) { if (i != text_textures_.end()) {
return Object::Ref<TextureAsset>(i->second.Get()); return Object::Ref<TextureAsset>(i->second.Get());
} else { } else {
auto d(Object::New<TextureAsset>(packer)); auto d{Object::New<TextureAsset>(packer)};
text_textures_[hash] = d; text_textures_[hash] = d;
{ {
Asset::LockGuard lock(d.Get()); Asset::LockGuard lock(d.Get());
@ -493,7 +493,7 @@ auto Assets::GetTexture(TextPacker* packer) -> Object::Ref<TextureAsset> {
MarkAssetForLoad(d.Get()); MarkAssetForLoad(d.Get());
} }
d->set_last_used_time(g_core->GetAppTimeMillisecs()); d->set_last_used_time(g_core->GetAppTimeMillisecs());
return d; return Object::Ref<TextureAsset>(d);
} }
} }
@ -513,7 +513,7 @@ auto Assets::GetQRCodeTexture(const std::string& url)
MarkAssetForLoad(d.Get()); MarkAssetForLoad(d.Get());
} }
d->set_last_used_time(g_core->GetAppTimeMillisecs()); d->set_last_used_time(g_core->GetAppTimeMillisecs());
return d; return Object::Ref<TextureAsset>(d);
} }
} }
@ -536,7 +536,7 @@ auto Assets::GetCubeMapTexture(const std::string& file_name)
MarkAssetForLoad(d.Get()); MarkAssetForLoad(d.Get());
} }
d->set_last_used_time(g_core->GetAppTimeMillisecs()); d->set_last_used_time(g_core->GetAppTimeMillisecs());
return d; return Object::Ref<TextureAsset>(d);
} }
} }
@ -592,7 +592,7 @@ auto Assets::GetTexture(const std::string& file_name)
MarkAssetForLoad(d.Get()); MarkAssetForLoad(d.Get());
} }
d->set_last_used_time(g_core->GetAppTimeMillisecs()); d->set_last_used_time(g_core->GetAppTimeMillisecs());
return d; return Object::Ref<TextureAsset>(d);
} }
} }

View File

@ -1002,7 +1002,7 @@ void TextGraphics::GetOSTextSpanBoundsAndWidth(const std::string& s, Rect* r,
// so let's use a cache of recent results. // so let's use a cache of recent results.
auto i = text_span_bounds_cache_map_.find(s); auto i = text_span_bounds_cache_map_.find(s);
if (i != text_span_bounds_cache_map_.end()) { if (i != text_span_bounds_cache_map_.end()) {
Object::Ref<TextSpanBoundsCacheEntry> entry = i->second; auto entry = Object::Ref<TextSpanBoundsCacheEntry>(i->second);
*r = entry->r; *r = entry->r;
*width = entry->width; *width = entry->width;

View File

@ -369,7 +369,7 @@ void Input::RemoveInputDevice(InputDevice* input, bool standard_message) {
if (input_device.Exists() && (input_device.Get() == input)) { if (input_device.Exists() && (input_device.Get() == input)) {
// Pull it off the list before killing it (in case it tries to trigger // Pull it off the list before killing it (in case it tries to trigger
// another kill itself). // another kill itself).
Object::Ref<InputDevice> device = input_device; auto device = Object::Ref<InputDevice>(input_device);
// Ok we cleared its slot in our vector; now we just have // Ok we cleared its slot in our vector; now we just have
// the local variable 'device' keeping it alive. // the local variable 'device' keeping it alive.

View File

@ -30,7 +30,7 @@ static auto GetAsset(std::unordered_map<std::string, Object::WeakRef<T> >* list,
// strong-ref to it. // strong-ref to it.
auto t(Object::New<T>(name, scene)); auto t(Object::New<T>(name, scene));
(*list)[name] = t; (*list)[name] = t;
return t; return Object::Ref<T>(t);
} }
} }

View File

@ -50,7 +50,7 @@ class FlagNode : public Node {
base::AreaOfInterest* area_of_interest_ = nullptr; base::AreaOfInterest* area_of_interest_ = nullptr;
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_{nullptr}; Object::Ref<RigidBody> body_;
Object::Ref<SceneTexture> color_texture_; Object::Ref<SceneTexture> color_texture_;
base::MeshIndexedObjectSplit mesh_; base::MeshIndexedObjectSplit mesh_;
Object::Ref<FullShadowSet> full_shadow_set_; Object::Ref<FullShadowSet> full_shadow_set_;

View File

@ -12,7 +12,8 @@ namespace ballistica::scene_v1 {
auto PythonClassSceneCollisionMesh::tp_repr(PythonClassSceneCollisionMesh* self) auto PythonClassSceneCollisionMesh::tp_repr(PythonClassSceneCollisionMesh* self)
-> PyObject* { -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
Object::Ref<SceneCollisionMesh> m = *self->collision_mesh_; assert(self->collision_mesh_);
auto&& m = *self->collision_mesh_;
return Py_BuildValue( return Py_BuildValue(
"s", (std::string("<bascenev1.CollisionMesh ") "s", (std::string("<bascenev1.CollisionMesh ")
+ (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">") + (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">")

View File

@ -12,7 +12,7 @@ namespace ballistica::scene_v1 {
auto PythonClassSceneDataAsset::tp_repr(PythonClassSceneDataAsset* self) auto PythonClassSceneDataAsset::tp_repr(PythonClassSceneDataAsset* self)
-> PyObject* { -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
Object::Ref<SceneDataAsset> m = *self->data_; auto&& m = *self->data_;
return Py_BuildValue( return Py_BuildValue(
"s", (std::string("<ba.Data ") "s", (std::string("<ba.Data ")
+ (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">") + (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">")

View File

@ -11,7 +11,7 @@ namespace ballistica::scene_v1 {
auto PythonClassSceneMesh::tp_repr(PythonClassSceneMesh* self) -> PyObject* { auto PythonClassSceneMesh::tp_repr(PythonClassSceneMesh* self) -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
Object::Ref<SceneMesh> m = *(self->mesh_); auto&& m = *(self->mesh_);
return Py_BuildValue( return Py_BuildValue(
"s", (std::string("<bascenev1.Mesh ") "s", (std::string("<bascenev1.Mesh ")
+ (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">") + (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">")

View File

@ -30,7 +30,7 @@ void PythonClassSceneSound::SetupType(PyTypeObject* cls) {
auto PythonClassSceneSound::tp_repr(PythonClassSceneSound* self) -> PyObject* { auto PythonClassSceneSound::tp_repr(PythonClassSceneSound* self) -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
Object::Ref<SceneSound> m = *(self->sound_); auto&& m = *(self->sound_);
return Py_BuildValue( return Py_BuildValue(
"s", (std::string("<bascenev1.Sound ") "s", (std::string("<bascenev1.Sound ")
+ (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">") + (m.Exists() ? ("\"" + m->name() + "\"") : "(empty ref)") + ">")

View File

@ -12,7 +12,7 @@ namespace ballistica::scene_v1 {
auto PythonClassSceneTexture::tp_repr(PythonClassSceneTexture* self) auto PythonClassSceneTexture::tp_repr(PythonClassSceneTexture* self)
-> PyObject* { -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
Object::Ref<SceneTexture> t = *(self->texture_); auto&& t = *(self->texture_);
return Py_BuildValue( return Py_BuildValue(
"s", (std::string("<bascenev1.Texture ") "s", (std::string("<bascenev1.Texture ")
+ (t.Exists() ? ("\"" + t->name() + "\"") : "(empty ref)") + ">") + (t.Exists() ? ("\"" + t->name() + "\"") : "(empty ref)") + ">")

View File

@ -193,7 +193,7 @@ auto HostActivity::NewMaterial(const std::string& name)
auto m(Object::New<Material>(name, scene())); auto m(Object::New<Material>(name, scene()));
materials_.emplace_back(m); materials_.emplace_back(m);
return m; return Object::Ref<Material>(m);
} }
auto HostActivity::GetTexture(const std::string& name) auto HostActivity::GetTexture(const std::string& name)

View File

@ -275,7 +275,7 @@ void HostSession::RemovePlayer(Player* player) {
if (i->Get() == player) { if (i->Get() == player) {
// Grab a ref to keep the player alive, pull him off the list, then call // Grab a ref to keep the player alive, pull him off the list, then call
// his leaving callback. // his leaving callback.
Object::Ref<Player> player2 = *i; auto player2 = Object::Ref<Player>(*i);
players_.erase(i); players_.erase(i);
// Clear the player's attachment to its host-session so it doesn't // Clear the player's attachment to its host-session so it doesn't

View File

@ -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 = 21418; const int kEngineBuildNumber = 21421;
const char* kEngineVersion = "1.7.28"; const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -151,7 +151,7 @@ class Object {
friend class Object; friend class Object;
}; // WeakRefBase }; // WeakRefBase
/// Weak-reference to an instance of a specific Object subclass. /// A weak-reference to an instance of a specific Object subclass.
template <typename T> template <typename T>
class WeakRef : public WeakRefBase { class WeakRef : public WeakRefBase {
public: public:
@ -179,11 +179,14 @@ class Object {
return reinterpret_cast<T*>(obj_); return reinterpret_cast<T*>(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& { auto operator*() const -> T& {
if (!obj_) { if (!obj_) {
throw Exception("Dereferencing invalid " + static_type_name<T>() throw Exception(
+ " ref."); "Dereferencing invalid " + static_type_name<T>() + " ref.",
PyExcType::kReference);
} }
// Yes, reinterpret_cast is evil, but we make sure // Yes, reinterpret_cast is evil, but we make sure
@ -191,10 +194,13 @@ class Object {
// (see Acquire()). // (see Acquire()).
return *reinterpret_cast<T*>(obj_); return *reinterpret_cast<T*>(obj_);
} }
/// Access the referenced object; throws an Exception if ref is invalid.
auto operator->() const -> T* { auto operator->() const -> T* {
if (!obj_) { if (!obj_) {
throw Exception("Dereferencing invalid " + static_type_name<T>() throw Exception(
+ " ref."); "Dereferencing invalid " + static_type_name<T>() + " ref.",
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
@ -202,7 +208,53 @@ class Object {
return reinterpret_cast<T*>(obj_); return reinterpret_cast<T*>(obj_);
} }
// Assign/compare with any compatible pointer. /// Compare to a pointer of any compatible type.
template <typename U>
auto operator==(U* ptr) -> bool {
return (Get() == ptr);
}
/// Compare to a pointer of any compatible type.
template <typename U>
auto operator!=(U* ptr) -> bool {
return (Get() != ptr);
}
/// Compare to a strong ref of any compatible type.
template <typename U>
auto operator==(const Ref<U>& ref) -> bool {
return (Get() == ref.Get());
}
/// Compare to a strong ref to a compatible type.
template <typename U>
auto operator!=(const Ref<U>& ref) -> bool {
return (Get() != ref.Get());
}
/// Compare to a weak ref of any compatible type.
template <typename U>
auto operator==(const WeakRef<U>& ref) -> bool {
return (Get() == ref.Get());
}
/// Compare to a weak ref of any compatible type.
template <typename U>
auto operator!=(const WeakRef<U>& 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<T>& ref) -> WeakRef<T>& {
*this = ref.Get();
return *this;
}
/// Assign from a pointer of any compatible type.
template <typename U> template <typename U>
auto operator=(U* ptr) -> WeakRef<T>& { auto operator=(U* ptr) -> WeakRef<T>& {
Release(); Release();
@ -219,104 +271,60 @@ class Object {
return *this; return *this;
} }
template <typename U> /// Assign from a strong ref of any compatible type.
auto operator==(U* ptr) -> bool {
return (Get() == ptr);
}
template <typename U>
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<T>& ref) -> WeakRef<T>& {
*this = ref.Get();
return *this;
}
// auto operator==(const WeakRef<T>& ref) -> bool {
// return (Get() == ref.Get());
// }
// auto operator!=(const WeakRef<T>& ref) -> bool {
// return (Get() != ref.Get());
// }
// Assign/compare with a compatible weak-ref.
template <typename U>
auto operator=(const WeakRef<U>& ref) -> WeakRef<T>& {
*this = ref.Get();
return *this;
}
template <typename U>
auto operator==(const WeakRef<U>& ref) -> bool {
return (Get() == ref.Get());
}
template <typename U>
auto operator!=(const WeakRef<U>& ref) -> bool {
return (Get() != ref.Get());
}
// Assign/compare with a compatible strong-ref.
template <typename U> template <typename U>
auto operator=(const Ref<U>& ref) -> WeakRef<T>& { auto operator=(const Ref<U>& ref) -> WeakRef<T>& {
*this = ref.Get(); *this = ref.Get();
return *this; return *this;
} }
/// Assign from a weak ref of any compatible type (except our exact
/// type which has its own overload).
template <typename U> template <typename U>
auto operator==(const Ref<U>& ref) -> bool { auto operator=(const WeakRef<U>& ref) -> WeakRef<T>& {
return (Get() == ref.Get()); *this = ref.Get();
return *this;
} }
template <typename U> // ---------------------------- Constructors -------------------------------
auto operator!=(const Ref<U>& ref) -> bool {
return (Get() != ref.Get());
}
// Various constructors: // Default constructor.
// Empty.
WeakRef() = default; WeakRef() = default;
// From our type pointer. /// Copy constructor. Note that, by making this explicit, we require code
explicit WeakRef(T* obj) { *this = obj; } /// 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<SomeType>(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<T>& ref) { *this = ref.Get(); }
// Copy constructor (only non-explicit one). /// Create from a pointer of any compatible type.
WeakRef(const WeakRef<T>& ref) { *this = ref.Get(); }
// From a compatible pointer.
template <typename U> template <typename U>
explicit WeakRef(U* ptr) { explicit WeakRef(U* ptr) {
*this = ptr; *this = ptr;
} }
// From a compatible strong ref. /// Create from a strong ref of any compatible type.
template <typename U> template <typename U>
explicit WeakRef(const Ref<U>& ref) { explicit WeakRef(const Ref<U>& ref) {
*this = ref; *this = ref;
} }
// From a compatible weak ref. /// Create from a weak ref of any compatible type.
template <typename U> template <typename U>
explicit WeakRef(const WeakRef<U>& ref) { explicit WeakRef(const WeakRef<U>& ref) {
*this = ref; *this = ref;
} }
// -------------------------------------------------------------------------
private: private:
void Acquire(T* obj) { void Acquire(T* obj) {
if (obj == nullptr) { if (obj == nullptr) {
throw Exception("Acquiring invalid ptr of " + static_type_name<T>()); throw Exception("Acquiring invalid ptr of " + static_type_name<T>(),
PyExcType::kReference);
} }
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
@ -355,22 +363,8 @@ class Object {
~Ref() { Release(); } ~Ref() { Release(); }
auto Get() const -> T* { return obj_; } 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<T>()
+ " ref.");
}
return *obj_;
}
auto operator->() const -> T* {
if (!obj_) {
throw Exception("Dereferencing invalid " + static_type_name<T>()
+ " ref.");
}
return obj_;
}
auto Exists() const -> bool { return (obj_ != nullptr); } auto Exists() const -> bool { return (obj_ != nullptr); }
void Clear() { Release(); } void Clear() { Release(); }
/// Convenience wrapper for Object::IsValidManagedObject. /// Convenience wrapper for Object::IsValidManagedObject.
@ -381,7 +375,67 @@ class Object {
return false; 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<T>() + " 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<T>() + " ref.",
PyExcType::kReference);
}
return obj_;
}
/// Compare to a pointer of any compatible type.
template <typename U>
auto operator==(U* ptr) -> bool {
return (Get() == ptr);
}
/// Compare to a pointer of any compatible type.
template <typename U>
auto operator!=(U* ptr) -> bool {
return (Get() != ptr);
}
/// Compare to a strong ref of any compatible type.
template <typename U>
auto operator==(const Ref<U>& ref) -> bool {
return (Get() == ref.Get());
}
/// Compare to a strong ref of any compatible type.
template <typename U>
auto operator!=(const Ref<U>& 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<T>& ref) -> Ref<T>& {
*this = ref.Get();
return *this;
}
/// Assign from a pointer of any compatible type.
template <typename U> template <typename U>
auto operator=(U* ptr) -> Ref<T>& { auto operator=(U* ptr) -> Ref<T>& {
Release(); Release();
@ -390,98 +444,61 @@ class Object {
} }
return *this; return *this;
} }
template <typename U>
auto operator==(U* ptr) -> bool {
return (Get() == ptr);
}
template <typename U>
auto operator!=(U* ptr) -> bool {
return (Get() != ptr);
}
auto operator==(const Ref<T>& ref) -> bool { return (Get() == ref.Get()); } /// Assign from a strong ref of any compatible type (except our exact
auto operator!=(const Ref<T>& ref) -> bool { return (Get() != ref.Get()); } /// type which has its own overload).
// 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<T>& ref) -> Ref<T>& {
assert(this != &ref); // Shouldn't be self-assigning.
*this = ref.Get();
return *this;
}
// Assign/compare with a compatible strong-ref.
template <typename U> template <typename U>
auto operator=(const Ref<U>& ref) -> Ref<T>& { auto operator=(const Ref<U>& ref) -> Ref<T>& {
*this = ref.Get(); *this = ref.Get();
return *this; return *this;
} }
template <typename U> /// Assign from a weak ref to any compatible type.
auto operator==(const Ref<U>& ref) -> bool {
return (Get() == ref.Get());
}
template <typename U>
auto operator!=(const Ref<U>& 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.
template <typename U> template <typename U>
auto operator=(const WeakRef<U>& ref) -> Ref<T>& { auto operator=(const WeakRef<U>& ref) -> Ref<T>& {
*this = ref.Get(); *this = ref.Get();
return *this; return *this;
} }
// These are already covered by the equivalent operators // ---------------------------- Constructors -------------------------------
// on the WeakRef side.
// template <typename U>
// auto operator==(const WeakRef<U>& ref) -> bool {
// return (Get() == ref.Get());
// }
// template <typename U> /// Default constructor.
// auto operator!=(const WeakRef<U>& ref) -> bool {
// return (Get() != ref.Get());
// }
// Various constructors:
// Empty.
Ref() = default; Ref() = default;
// From our type pointer. /// Copy constructor. Note that, by making this explicit, we require code
explicit Ref(T* obj) { *this = obj; } /// 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<SomeType>(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<T>& ref) { *this = ref.Get(); }
// Copy constructor (only non-explicit one). /// Create from a compatible pointer.
Ref(const Ref<T>& ref) { *this = ref.Get(); }
// From a compatible pointer.
template <typename U> template <typename U>
explicit Ref(U* ptr) { explicit Ref(U* ptr) {
*this = ptr; *this = ptr;
} }
// From a compatible strong ref. /// Create from a compatible strong ref.
template <typename U> template <typename U>
explicit Ref(const Ref<U>& ref) { explicit Ref(const Ref<U>& ref) {
*this = ref; *this = ref;
} }
// From a compatible weak ref. /// Create from a compatible weak ref.
template <typename U> template <typename U>
explicit Ref(const WeakRef<U>& ref) { explicit Ref(const WeakRef<U>& ref) {
*this = ref; *this = ref;
} }
// -------------------------------------------------------------------------
private: private:
void Acquire(T* obj) { void Acquire(T* obj) {
if (obj == nullptr) { if (obj == nullptr) {
throw Exception("Acquiring invalid ptr of " + static_type_name<T>()); throw Exception("Acquiring invalid ptr of " + static_type_name<T>(),
PyExcType::kReference);
} }
#if BA_DEBUG_BUILD #if BA_DEBUG_BUILD
@ -549,13 +566,13 @@ class Object {
/// In some cases it may be handy to allocate an object for ref-counting /// 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 /// 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. /// object in one thread to be passed to another which will own said
/// For such cases, allocate using NewDeferred() and then create the initial /// object. For such cases, allocate using NewDeferred() and then create
/// strong ref in the desired thread using CompleteDeferred(). /// the initial strong ref in the desired thread using CompleteDeferred().
/// Note that in debug builds, checks may be run to make sure deferred /// 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 /// objects wind up with references added to them at some point. For this
/// want to allocate an object for manual deallocation or permanent /// reason, if you want to allocate an object for manual deallocation or
/// existence, use NewUnmanaged() instead. /// permanent existence, use NewUnmanaged() instead.
template <typename T, typename... ARGS> template <typename T, typename... ARGS>
[[nodiscard]] static auto NewDeferred(ARGS&&... args) -> T* { [[nodiscard]] static auto NewDeferred(ARGS&&... args) -> T* {
T* ptr = new T(std::forward<ARGS>(args)...); T* ptr = new T(std::forward<ARGS>(args)...);

View File

@ -273,6 +273,7 @@ enum class PyExcType {
kIndex, kIndex,
kType, kType,
kValue, kValue,
kReference,
kContext, kContext,
kNotFound, kNotFound,
kNodeNotFound, kNodeNotFound,

View File

@ -49,6 +49,9 @@ void Python::SetPythonException(const Exception& exc) {
case PyExcType::kValue: case PyExcType::kValue:
pytype = PyExc_ValueError; pytype = PyExc_ValueError;
break; break;
case PyExcType::kReference:
pytype = PyExc_ReferenceError;
break;
case PyExcType::kType: case PyExcType::kType:
pytype = PyExc_TypeError; pytype = PyExc_TypeError;
break; break;

View File

@ -1268,7 +1268,7 @@ void ContainerWidget::DeleteWidget(Widget* w) {
} }
// Grab a ref until we clear it off the list to avoid funky recursion // Grab a ref until we clear it off the list to avoid funky recursion
// issues. // issues.
Object::Ref<Widget> w2 = *i; auto w2 = Object::Ref<Widget>(*i);
widgets_.erase(i); widgets_.erase(i);
found = true; found = true;
break; break;