diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 5588a757..8e9fae07 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84291,13 +84291,13 @@ Address,Quality,Size,Name 0x0000007100fcdb38,U,000224, 0x0000007100fcdc18,U,000020, 0x0000007100fcdc2c,U,000204, -0x0000007100fcdcf8,U,000104, -0x0000007100fcdd60,U,000024, -0x0000007100fcdd78,U,000060, -0x0000007100fcddb4,U,000972, -0x0000007100fce180,U,000020, -0x0000007100fce194,U,000136, -0x0000007100fce21c,U,000136, +0x0000007100fcdcf8,O,000104,_ZN4ksys4phys15ContactListenerC1EPNS0_10ContactMgrENS0_16ContactLayerTypeEi +0x0000007100fcdd60,O,000024,_ZN4ksys4phys15ContactListenerD1Ev +0x0000007100fcdd78,O,000060,_ZN4ksys4phys15ContactListenerD0Ev +0x0000007100fcddb4,O,000972,_ZN4ksys4phys15ContactListener4initEPN4sead4HeapE +0x0000007100fce180,O,000020,_ZN4ksys4phys15ContactListener10clearTableEv +0x0000007100fce194,O,000136,_ZN4ksys4phys15ContactListener22collisionAddedCallbackERK17hkpCollisionEvent +0x0000007100fce21c,O,000136,_ZN4ksys4phys15ContactListener24collisionRemovedCallbackERK17hkpCollisionEvent 0x0000007100fce2a4,U,000236, 0x0000007100fce390,U,000416, 0x0000007100fce530,U,000028, @@ -84313,10 +84313,10 @@ Address,Quality,Size,Name 0x0000007100fcf6b4,U,000124, 0x0000007100fcf730,U,000156, 0x0000007100fcf7cc,U,000024, -0x0000007100fcf7e4,U,000112, -0x0000007100fcf854,U,000092, -0x0000007100fcf8b0,U,000004,nullsub_4257 -0x0000007100fcf8b4,U,000008, +0x0000007100fcf7e4,O,000112,_ZNK4ksys4phys15ContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fcf854,O,000092,_ZNK4ksys4phys15ContactListener18getRuntimeTypeInfoEv +0x0000007100fcf8b0,O,000004,_ZN4ksys4phys15ContactListener3m11Ev +0x0000007100fcf8b4,O,000008,_ZN4ksys4phys15ContactListener3m15Ev 0x0000007100fcf8bc,O,000072,_ZN4ksys4phys20RigidContactPointsEx4makeEPN4sead4HeapEiiRKNS2_14SafeStringBaseIcEEiii 0x0000007100fcf904,O,000348,_ZN4ksys4phys20RigidContactPointsEx17registerLayerPairENS0_12ContactLayerES2_b 0x0000007100fcfa60,O,000024,_ZN4ksys4phys20RigidContactPointsEx4freeEPS1_ diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 31d62f2e..7b7f5a78 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -70,6 +70,8 @@ target_sources(uking PRIVATE System/physConstraint.h System/physContactInfoParam.cpp System/physContactInfoParam.h + System/physContactListener.cpp + System/physContactListener.h System/physContactMgr.cpp System/physContactMgr.h System/physDefines.cpp diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index aeb20df5..c1467df3 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -365,6 +365,18 @@ public: virtual void resetPosition(); virtual const char* getName(); + // Internal. + void onCollisionAdded() { + if (mCollisionCount.increment() == 0) + clearFlag4000000(false); + } + + // Internal. + void onCollisionRemoved() { + if (mCollisionCount.decrement() == 1) + clearFlag4000000(true); + } + private: void createMotionAccessor(sead::Heap* heap); void onInvalidParameter(int code = 0); @@ -385,8 +397,7 @@ private: f32 _b0 = 1.0f; Type mType{}; MotionAccessor* mMotionAccessor = nullptr; - u16 _c0 = 0; - u16 _c2 = 0; + sead::Atomic mCollisionCount; void* _c8 = nullptr; }; KSYS_CHECK_SIZE_NX150(RigidBody, 0xD0); diff --git a/src/KingSystem/Physics/System/physContactListener.cpp b/src/KingSystem/Physics/System/physContactListener.cpp new file mode 100644 index 00000000..c3ad636b --- /dev/null +++ b/src/KingSystem/Physics/System/physContactListener.cpp @@ -0,0 +1,68 @@ +#include "KingSystem/Physics/System/physContactListener.h" +#include +#include +#include +#include +#include "KingSystem/Physics/RigidBody/physRigidBody.h" + +namespace ksys::phys { + +static RigidBody* getRigidBody(hkpRigidBody* hk_body) { + // This needs to be kept in sync with the RigidBody constructor! + return reinterpret_cast(hk_body->getUserData()); +} + +ContactListener::ContactListener(ContactMgr* mgr, ContactLayerType layer_type, int layer_count) + : mMgr(mgr), mLayerType(layer_type), mLayerBase(getContactLayerBase(layer_type)), + mLayerCount(layer_count) {} + +ContactListener::~ContactListener() = default; + +void ContactListener::init(sead::Heap* heap) { + // NOLINTBEGIN(cppcoreguidelines-narrowing-conversions) + _20.allocBufferAssert(mLayerCount, nullptr); + for (u32 i = 0; i < mLayerCount; ++i) { + _20[i].allocBufferAssert(mLayerCount, nullptr); + } + + _30.allocBufferAssert(mLayerCount, nullptr); + for (u32 i = 0; i < mLayerCount; ++i) { + auto& row = _30[i]; + row.allocBufferAssert(mLayerCount, nullptr); + + for (u32 j = 0; j < mLayerCount; ++j) { + if (j >= i) { + row[j] = new (heap) ContactUnk1(mLayerBase + i); + } else { + row[j] = _30[j][i]; + } + } + } + // NOLINTEND(cppcoreguidelines-narrowing-conversions) + + _48 = sead::Mathu::roundUpPow2(mLayerCount * mLayerCount, 0x20); + _40 = ::operator new[](_48, heap, 0x20); + clearTable(); +} + +void ContactListener::clearTable() { + sead::MemUtil::fillZero(_40, _48); +} + +void ContactListener::collisionAddedCallback(const hkpCollisionEvent& event) { + auto* bodyA = getRigidBody(event.getBody(0)); + auto* bodyB = getRigidBody(event.getBody(1)); + handleCollisionAdded(event, bodyA, bodyB); + bodyA->onCollisionAdded(); + bodyB->onCollisionAdded(); +} + +void ContactListener::collisionRemovedCallback(const hkpCollisionEvent& event) { + auto* bodyA = getRigidBody(event.getBody(0)); + auto* bodyB = getRigidBody(event.getBody(1)); + handleCollisionRemoved(event, bodyA, bodyB); + bodyA->onCollisionRemoved(); + bodyB->onCollisionRemoved(); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physContactListener.h b/src/KingSystem/Physics/System/physContactListener.h new file mode 100644 index 00000000..b5f3d057 --- /dev/null +++ b/src/KingSystem/Physics/System/physContactListener.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "KingSystem/Physics/System/physDefines.h" + +namespace ksys::phys { + +class ContactMgr; +class RigidBody; + +struct ContactUnk1 { + ContactUnk1(u32 layer); + virtual ~ContactUnk1(); + + u8 _8[0x68]; +}; + +class ContactListener : public hkpContactListener, public sead::hostio::Node { + SEAD_RTTI_BASE(ContactListener) +public: + ContactListener(ContactMgr* mgr, ContactLayerType layer_type, int layer_count); + ~ContactListener() override; + + void init(sead::Heap* heap); + void clearTable(); + + void contactPointCallback(const hkpContactPointEvent& event) override; + void collisionAddedCallback(const hkpCollisionEvent& event) override; + void collisionRemovedCallback(const hkpCollisionEvent& event) override; + void contactPointAddedCallback(hkpContactPointAddedEvent& event) override; + void contactPointRemovedCallback(hkpContactPointRemovedEvent& event) override; + void contactProcessCallback(hkpContactProcessEvent& event) override; + + virtual void m10(); + virtual void m11() {} + virtual void handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* bodyA, + RigidBody* bodyB); + virtual void m13(); + virtual void m14(); + virtual u32 m15() { return 0; } + +protected: + void handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* bodyA, RigidBody* bodyB); + +private: + struct Unk1 { + void* _0; + void* _8; + }; + + ContactMgr* mMgr{}; + ContactLayerType mLayerType{}; + u32 mLayerBase{}; + sead::Buffer>> _20; + sead::Buffer> _30; + void* _40{}; + u32 _48{}; + u32 mLayerCount{}; + sead::CriticalSection mCS; + u16 _90{}; + bool _92{}; +}; + +} // namespace ksys::phys