diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 7cf27a21..c9d7f507 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -95450,14 +95450,14 @@ Address,Quality,Size,Name 0x00000071012b1940,U,000004, 0x00000071012b1944,U,000004, 0x00000071012b1948,U,000008, -0x00000071012b1950,U,000108,phys::makeSensorContactListener -0x00000071012b19bc,U,000004,j_ksys::phys::ContactListener::dtor_0 -0x00000071012b19c0,U,000036, -0x00000071012b19e4,U,000424, -0x00000071012b1b8c,U,000136, -0x00000071012b1c14,U,000532, -0x00000071012b1e28,U,000204, -0x00000071012b1ef4,U,000092, +0x00000071012b1950,O,000108,_ZN4ksys4phys21SensorContactListener4makeEPNS0_10ContactMgrEPN4sead4HeapE +0x00000071012b19bc,O,000004,_ZN4ksys4phys21SensorContactListenerD1Ev +0x00000071012b19c0,O,000036,_ZN4ksys4phys21SensorContactListenerD0Ev +0x00000071012b19e4,O,000424,_ZN4ksys4phys21SensorContactListener20handleCollisionAddedERK17hkpCollisionEventPNS0_9RigidBodyES6_ +0x00000071012b1b8c,O,000136,_ZN4ksys4phys21SensorContactListener28manifoldContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_ +0x00000071012b1c14,O,000532,_ZN4ksys4phys21SensorContactListener27regularContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_PN4sead9SafeArrayIjLi2EEE +0x00000071012b1e28,O,000204,_ZNK4ksys4phys21SensorContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071012b1ef4,O,000092,_ZNK4ksys4phys21SensorContactListener18getRuntimeTypeInfoEv 0x00000071012b1f50,m,000484,_ZN4ksys4phys10SystemDataC1Ev 0x00000071012b2134,O,000864,_ZN4ksys4phys10SystemDataD1Ev 0x00000071012b2494,O,000404,_ZN4sead9SafeArrayIN4ksys4phys10SystemData6TablesINS2_10LayerTableELi32EEELi2EED2Ev diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 557424ba..010eeae4 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -137,6 +137,8 @@ target_sources(uking PRIVATE System/physParamSet.h System/physQueryContactPointInfo.cpp System/physQueryContactPointInfo.h + System/physSensorContactListener.cpp + System/physSensorContactListener.h System/physSensorGroupFilter.cpp System/physSensorGroupFilter.h System/physSystem.cpp diff --git a/src/KingSystem/Physics/System/physSensorContactListener.cpp b/src/KingSystem/Physics/System/physSensorContactListener.cpp new file mode 100644 index 00000000..bf6f35c1 --- /dev/null +++ b/src/KingSystem/Physics/System/physSensorContactListener.cpp @@ -0,0 +1,99 @@ +#include "KingSystem/Physics/System/physSensorContactListener.h" +#include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include "KingSystem/Physics/System/physCollisionInfo.h" +#include "KingSystem/Physics/System/physContactLayerCollisionInfo.h" +#include "KingSystem/Physics/System/physContactMgr.h" +#include "KingSystem/Physics/System/physSystem.h" +#include "KingSystem/Physics/physConversions.h" + +namespace ksys::phys { + +SensorContactListener* SensorContactListener::make(ContactMgr* mgr, sead::Heap* heap) { + auto* listener = new (heap) SensorContactListener(mgr); + listener->init(heap); + return listener; +} + +SensorContactListener::SensorContactListener(ContactMgr* mgr) + : ContactListener(mgr, ContactLayerType::Sensor, LastSensor - FirstSensor + 1) {} + +SensorContactListener::~SensorContactListener() = default; + +void SensorContactListener::handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b) { + registerForEndOfStepContactPointCallbacks(event); + + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + + const auto rlayer_a = int(layer_a - mLayerBase); + const auto rlayer_b = int(layer_b - mLayerBase); + + if (body_a->getContactMask().isOnBit(rlayer_b) || body_b->getContactMask().isOnBit(rlayer_a)) + return; + + if (body_a->getCollisionInfo() && body_a->getCollisionInfo()->isLayerEnabled(layer_b)) + mMgr->registerCollision(body_a->getCollisionInfo(), body_a, body_b); + + if (body_b->getCollisionInfo() && body_b->getCollisionInfo()->isLayerEnabled(layer_a)) + mMgr->registerCollision(body_b->getCollisionInfo(), body_b, body_a); + + if (areContactsTrackedForLayerPair(rlayer_a, rlayer_b)) { + auto* layer_col_info = getContactLayerCollisionInfo(rlayer_a, rlayer_b); + if (body_a->isFlag8Set() && body_b->isFlag8Set()) { + const auto layer_a_ = int(layer_a); + const auto tracked_layer = layer_col_info->getLayer(); + const bool body_a_first = layer_a_ == tracked_layer; + auto* body1 = body_a_first ? body_a : body_b; + auto* body2 = body_a_first ? body_b : body_a; + mMgr->registerCollision(layer_col_info, body1, body2); + } + } +} + +bool SensorContactListener::manifoldContactPointCallback(const hkpContactPointEvent& event, + RigidBody* body_a, RigidBody* body_b) { + [[maybe_unused]] auto* filter = System::instance()->getGroupFilter(mLayerType); + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + + return contactPointCallbackImpl(0, 0, body_a, body_b, layer_a, layer_b, event); +} + +bool SensorContactListener::regularContactPointCallback( + const hkpContactPointEvent& event, RigidBody* body_a, RigidBody* body_b, + sead::SafeArray* out_material_masks) { + [[maybe_unused]] auto* filter = System::instance()->getGroupFilter(mLayerType); + + RigidBody::CollisionMasks masks_a, masks_b; + sead::Vector3f contact_point_pos; + + storeToVec3(&contact_point_pos, event.m_contactPoint->getPosition()); + body_a->getCollisionMasks(&masks_a, event.getShapeKeys(0), contact_point_pos); + body_b->getCollisionMasks(&masks_b, event.getShapeKeys(1), contact_point_pos); + + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + + const auto rlayer_a = layer_a - int(mLayerBase); + const auto rlayer_b = layer_b - int(mLayerBase); + const auto& entries = mTrackedContactPointLayers[rlayer_a][rlayer_b]; + + const bool result = contactPointCallbackImpl(0, 0, body_a, body_b, layer_a, layer_b, event); + + if (body_a->getIgnoredLayers().isOnBit(rlayer_b) && + body_b->getIgnoredLayers().isOnBit(rlayer_a)) { + const auto notify_result = + notifyContactPointInfo(body_a, body_b, layer_a, layer_b, masks_a, masks_b, event, true); + + for (int idx = 0; idx < entries.size(); ++idx) { + notifyLayerContactPointInfo(*entries[idx], notify_result, body_a, body_b, layer_a, + layer_b, masks_a.material_mask, masks_b.material_mask, + event); + } + } + + return result; +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physSensorContactListener.h b/src/KingSystem/Physics/System/physSensorContactListener.h new file mode 100644 index 00000000..8c961279 --- /dev/null +++ b/src/KingSystem/Physics/System/physSensorContactListener.h @@ -0,0 +1,26 @@ +#pragma once + +#include "KingSystem/Physics/System/physContactListener.h" + +namespace ksys::phys { + +class SensorContactListener : public ContactListener { + SEAD_RTTI_OVERRIDE(SensorContactListener, ContactListener) +public: + static SensorContactListener* make(ContactMgr* mgr, sead::Heap* heap); + + ~SensorContactListener() override; + +protected: + explicit SensorContactListener(ContactMgr* mgr); + + void handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b) override; + bool manifoldContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + RigidBody* body_b) override; + bool regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + RigidBody* body_b, + sead::SafeArray* out_material_masks) override; +}; + +} // namespace ksys::phys