diff options
| author | Léo Lam <leo@leolam.fr> | 2022-02-12 12:06:43 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2022-02-12 16:43:48 +0100 |
| commit | bc66305e3d8c537f446dde96d607e63f5e4d3f2e (patch) | |
| tree | bf792dc3a7584bafe6b5bd384e93faf37d3774bd /src | |
| parent | 4a1bb88bd565a54b71b95744f504d6de4ea7f6e3 (diff) | |
ksys/phys: Add ListShape
Diffstat (limited to 'src')
13 files changed, 439 insertions, 10 deletions
diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 65cbc4b5..268622b4 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -64,6 +64,10 @@ target_sources(uking PRIVATE RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h RigidBody/Shape/CylinderWater/physCylinderWaterShape.cpp RigidBody/Shape/CylinderWater/physCylinderWaterShape.h + RigidBody/Shape/List/physListShape.cpp + RigidBody/Shape/List/physListShape.h + RigidBody/Shape/List/physListShapeRigidBody.cpp + RigidBody/Shape/List/physListShapeRigidBody.h RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp RigidBody/Shape/Polytope/physPolytopeRigidBody.h RigidBody/Shape/Polytope/physPolytopeShape.cpp @@ -133,4 +137,5 @@ target_sources(uking PRIVATE System/physUserTag.h physConversions.h + physHeapUtil.h ) diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp index e03df7ed..1226372b 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.cpp @@ -145,7 +145,7 @@ const hkpShape* BoxShape::updateHavokShape() { if (mFlags.isOn(Flag::DirtyTransform)) { mFlags.reset(Flag::DirtyTransform); - return std::as_const(*this).getHavokShape(); + return getHavokShapeConst(); } return nullptr; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h index 561454ee..9c8497dd 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h @@ -42,6 +42,7 @@ public: bool setExtents(const sead::Vector3f& extents); bool setTranslate(const sead::Vector3f& translate); void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return mMaterialMask; } ShapeType getType() const override { return ShapeType::Box; } float getVolume() const override; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h index 375e480d..04cf1d3a 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h @@ -50,6 +50,7 @@ public: bool setVertices(const sead::Vector3f& va, const sead::Vector3f& vb); void transformVertices(sead::Vector3f* veca, sead::Vector3f* vecb, const hkTransformf& rb_vec); void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return material_mask; } sead::Vector3f vertex_a; sead::TypedBitFlag<Flag, sead::Atomic<u32>> flags{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h index 737026cf..2d528659 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h @@ -12,4 +12,14 @@ struct CharacterPrismShapeParam { CommonShapeParam common; }; +class CharacterPrismShape : public Shape { + SEAD_RTTI_OVERRIDE(CharacterPrismShape, Shape) +public: + static CharacterPrismShape* make(const CharacterPrismShapeParam& param, sead::Heap* heap); + CharacterPrismShape* clone(sead::Heap* heap) const; + + void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const; +}; + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp new file mode 100644 index 00000000..fbffbb46 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.cpp @@ -0,0 +1,260 @@ +#include "KingSystem/Physics/RigidBody/Shape/List/physListShape.h" +#include <Havok/Physics2012/Collide/Shape/Compound/Collection/List/hkpListShape.h> +#include <Havok/Physics2012/Collide/Shape/Convex/Sphere/hkpSphereShape.h> +#include <basis/seadRawPrint.h> +#include <container/seadSafeArray.h> +#include "KingSystem/Physics/RigidBody/Shape/Box/physBoxShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleShape.h" +#include "KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" +#include "KingSystem/Physics/physHeapUtil.h" + +namespace ksys::phys { + +ListShape* ListShape::make(const ListShapeParam& param, sead::Heap* heap) { + auto* sphere = new hkpSphereShape(1.0); + if (!sphere) + return nullptr; + + auto shapes = sead::toArray<const hkpShape*>({sphere}); + auto* list_shape = new hkpListShape(shapes.getBufferPtr(), shapes.size()); + sphere->removeReference(); + + if (!list_shape) + return nullptr; + + return new (heap) ListShape(param, list_shape, heap); +} + +ListShape* ListShape::clone(sead::Heap* heap) const { + ListShapeParam param; + param.num_shapes = static_cast<decltype(param.num_shapes)>(mShapes.size()); + + auto* cloned = make(param, heap); + if (!cloned) + return nullptr; + + for (int i = 0, n = mShapes.size(); i < n; ++i) + cloned->replaceWithClone(i, mShapes[i], heap); + + return cloned; +} + +ListShape::ListShape(const ListShapeParam& param, hkpListShape* shape, sead::Heap* heap) + : mHavokShape(shape) { + mShapes.allocBufferAssert(param.num_shapes, heap); + for (int i = 0; i < int(param.num_shapes); ++i) + mShapes[i] = nullptr; +} + +ListShape::~ListShape() { + deleteRefCountedHavokObject(mHavokShape); + + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) { + delete mShapes[i]; + mShapes[i] = nullptr; + } + } + + mShapes.freeBuffer(); +} + +Shape* ListShape::replaceWithClone(int index, const Shape* shape_to_clone, sead::Heap* heap) { + delete mShapes[index]; + + switch (shape_to_clone->getType()) { + case ShapeType::Sphere: + mShapes[index] = sead::DynamicCast<const SphereShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::Capsule: + mShapes[index] = sead::DynamicCast<const CapsuleShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::Box: + mShapes[index] = sead::DynamicCast<const BoxShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::Cylinder: + mShapes[index] = sead::DynamicCast<const CylinderShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::Polytope: + mShapes[index] = sead::DynamicCast<const PolytopeShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::CharacterPrism: + mShapes[index] = sead::DynamicCast<const CharacterPrismShape>(shape_to_clone)->clone(heap); + break; + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } + + mFlags.set(Flag::NeedsHavokShapeUpdate); + return mShapes[index]; +} + +Shape* ListShape::replaceWithNewSphere(int index, const SphereShapeParam& param, sead::Heap* heap) { + return replaceWithNewShape<SphereShape, SphereShapeParam>(index, param, heap); +} + +Shape* ListShape::replaceWithNewCapsule(int index, const CapsuleShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape<CapsuleShape, CapsuleShapeParam>(index, param, heap); +} + +Shape* ListShape::replaceWithNewCylinder(int index, const CylinderShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape<CylinderShape, CylinderShapeParam>(index, param, heap); +} + +Shape* ListShape::replaceWithNewBox(int index, const BoxShapeParam& param, sead::Heap* heap) { + return replaceWithNewShape<BoxShape, BoxShapeParam>(index, param, heap); +} + +Shape* ListShape::replaceWithNewPolytope(int index, const PolytopeShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape<PolytopeShape, PolytopeShapeParam>(index, param, heap); +} + +Shape* ListShape::replaceWithNewCharacterPrism(int index, const CharacterPrismShapeParam& param, + sead::Heap* heap) { + return replaceWithNewShape<CharacterPrismShape, CharacterPrismShapeParam>(index, param, heap); +} + +void ListShape::setMaterialMask(const MaterialMask& mask, int index) { + switch (mShapes[index]->getType()) { + case ShapeType::Sphere: + sead::DynamicCast<SphereShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Capsule: + sead::DynamicCast<CapsuleShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Box: + sead::DynamicCast<BoxShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Cylinder: + sead::DynamicCast<CylinderShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::Polytope: + sead::DynamicCast<PolytopeShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::CharacterPrism: + sead::DynamicCast<CharacterPrismShape>(mShapes[index])->setMaterialMask(mask); + break; + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } +} + +const MaterialMask& ListShape::getMaterialMask(int index) const { + if (index >= mShapes.size()) + index = 0; + + switch (mShapes[index]->getType()) { + case ShapeType::Sphere: + return sead::DynamicCast<SphereShape>(mShapes[index])->getMaterialMask(); + case ShapeType::Capsule: + return sead::DynamicCast<CapsuleShape>(mShapes[index])->getMaterialMask(); + case ShapeType::Box: + return sead::DynamicCast<BoxShape>(mShapes[index])->getMaterialMask(); + case ShapeType::Cylinder: + return sead::DynamicCast<CylinderShape>(mShapes[index])->getMaterialMask(); + case ShapeType::Polytope: + return sead::DynamicCast<PolytopeShape>(mShapes[index])->getMaterialMask(); + case ShapeType::CharacterPrism: + return sead::DynamicCast<CharacterPrismShape>(mShapes[index])->getMaterialMask(); + case ShapeType::List: + case ShapeType::BoxWater: + case ShapeType::CylinderWater: + case ShapeType::Unknown: + SEAD_ASSERT_MSG(false, "unexpected shape type"); + break; + } + return sead::DynamicCast<SphereShape>(mShapes[index])->getMaterialMask(); +} + +float ListShape::getVolume() const { + float volume = 0.0; + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) + volume += mShapes[i]->getVolume(); + } + return volume; +} + +hkpShape* ListShape::getHavokShape() { + return mHavokShape; +} + +const hkpShape* ListShape::getHavokShape() const { + return mHavokShape; +} + +const hkpShape* ListShape::updateHavokShape() { + bool updated = false; + + if (mFlags.isOn(Flag::NeedsHavokShapeUpdate)) { + hkArray<const hkpShape*> havok_shapes; + int num_shapes = 0; + + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (!mShapes[i]) + continue; + + const hkpShape* havok_shape = mShapes[i]->updateHavokShape(); + if (havok_shape) { + // If one of the shapes was recreated, then we need to recreate the list shape. + havok_shapes.pushBack(havok_shape); + updated = true; + } else { + havok_shape = mShapes[i]->getHavokShapeConst(); + havok_shapes.pushBack(havok_shape); + + // Otherwise, we only need to recreate the list shape if the list has changed. + if (!updated && mHavokShape->m_childInfo.getSize() > num_shapes && + mHavokShape->getChildShapeInl(num_shapes) != havok_shapes[num_shapes]) { + updated = true; + } + } + + ++num_shapes; + } + + if (updated) { + const auto collision_filter_info = + mHavokShape->getCollisionFilterInfo(mHavokShape->getFirstKey()); + + mHavokShape->removeReference(); + mHavokShape = new hkpListShape(havok_shapes.data(), num_shapes); + + for (auto key = mHavokShape->getFirstKey(); key != HK_INVALID_SHAPE_KEY; + key = mHavokShape->getNextKey(key)) { + mHavokShape->setCollisionFilterInfo(key, collision_filter_info); + } + } else { + mHavokShape->recalcAabbExtents(); + } + + mFlags.reset(Flag::NeedsHavokShapeUpdate); + } + + return updated ? mHavokShape : nullptr; +} + +void ListShape::setScale(float scale) { + for (int i = 0, n = mShapes.size(); i < n; ++i) { + if (mShapes[i]) + mShapes[i]->setScale(scale); + } + + mFlags.set(Flag::NeedsHavokShapeUpdate); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h new file mode 100644 index 00000000..eb66a258 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShape.h @@ -0,0 +1,107 @@ +#pragma once + +#include <container/seadBuffer.h> +#include <prim/seadTypedBitFlag.h> +#include <thread/seadAtomic.h> +#include "KingSystem/Physics/RigidBody/Shape/physShape.h" +#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" + +class hkpListShape; + +namespace ksys::phys { + +struct BoxShapeParam; +struct CapsuleShapeParam; +struct CharacterPrismShapeParam; +struct CylinderShapeParam; +struct PolytopeShapeParam; +struct SphereShapeParam; + +class MaterialMask; + +struct ListShapeParam { + u8 num_shapes = 1; +}; + +class ListShape : public Shape { + SEAD_RTTI_OVERRIDE(ListShape, Shape) +public: + static ListShape* make(const ListShapeParam& param, sead::Heap* heap); + ListShape* clone(sead::Heap* heap) const; + + ListShape(const ListShapeParam& param, hkpListShape* shape, sead::Heap* heap); + ~ListShape() override; + + /// Replace the shape at the specified index with a clone of `shape_to_clone`. + /// The shape that is being replaced will be deleted. + /// @return the cloned heap + Shape* replaceWithClone(int index, const Shape* shape_to_clone, sead::Heap* heap); + + /// Replace the shape at the specified index with a new sphere shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewSphere(int index, const SphereShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new capsule shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCapsule(int index, const CapsuleShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new cylinder shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCylinder(int index, const CylinderShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new box shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewBox(int index, const BoxShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new polytope shape. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewPolytope(int index, const PolytopeShapeParam& param, sead::Heap* heap); + + /// Replace the shape at the specified index with a new character prism. + /// The shape that is being replaced will be deleted. + Shape* replaceWithNewCharacterPrism(int index, const CharacterPrismShapeParam& param, + sead::Heap* heap); + + /// Set the material mask for the shape at the specified index. + void setMaterialMask(const MaterialMask& mask, int index); + + /// Get the material mask for the shape at the specified index. + const MaterialMask& getMaterialMask(int index) const; + + ShapeType getType() const override { return ShapeType::List; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + void setScale(float scale) override; + +private: + enum class Flag { + /// Whether the Havok list shape needs to be recreated. + NeedsHavokShapeUpdate = 1 << 0, + }; + + template <typename T, typename ParamType> + Shape* replaceWithNewShape(int index, const ParamType& param, sead::Heap* heap) { + delete mShapes[index]; + auto* shape = T::make(param, heap); + mShapes[index] = shape; + mFlags.set(Flag::NeedsHavokShapeUpdate); + return shape; + } + + /// Child shapes. These are owned by this class. + sead::Buffer<Shape*> mShapes; + /// The Havok list shape. This is owned by this class. + hkpListShape* mHavokShape{}; + sead::TypedBitFlag<Flag, sead::Atomic<u32>> mFlags{Flag::NeedsHavokShapeUpdate}; +}; + +class ListShapeRigidBodyParam : public RigidBodyInstanceParam { + SEAD_RTTI_OVERRIDE(ListShapeRigidBodyParam, RigidBodyInstanceParam) +public: + u8 _90; + ListShapeParam shape; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp new file mode 100644 index 00000000..8dff51a3 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp @@ -0,0 +1 @@ +#include "KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h" diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h new file mode 100644 index 00000000..6b61a7d4 --- /dev/null +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h @@ -0,0 +1,13 @@ +#pragma once + +#include "KingSystem/Physics/RigidBody/physRigidBodyFromShape.h" + +namespace ksys::phys { + +class ListShapeRigidBody : public RigidBodyFromShape { + SEAD_RTTI_OVERRIDE(ListShapeRigidBody, RigidBodyFromShape) +public: + static ListShapeRigidBody* make(RigidBodyInstanceParam* param, sead::Heap* heap); +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp index 9ac2f120..8ce7f93d 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.cpp @@ -4,6 +4,7 @@ #include <Havok/Physics2012/Collide/Shape/Convex/ConvexVertices/hkpConvexVerticesShape.h> #include <math/seadMathCalcCommon.h> #include <prim/seadScopedLock.h> +#include "KingSystem/Physics/physHeapUtil.h" #include "KingSystem/Utils/HeapUtil.h" #include "KingSystem/Utils/SafeDelete.h" @@ -71,14 +72,7 @@ PolytopeShape::PolytopeShape(const PolytopeShapeParam& param) } PolytopeShape::~PolytopeShape() { - if (mHavokShape) { - /// @bug This is not how reference counting is supposed to work. - for (int i = 0, n = mHavokShape->getReferenceCount(); i < n; ++i) - mHavokShape->removeReference(); - - mHavokShape = nullptr; - } - + deleteRefCountedHavokObject(mHavokShape); util::deallocateObjectUnsafe(mTransformShape); mVertices.freeBuffer(); } @@ -147,7 +141,7 @@ const hkpShape* PolytopeShape::updateHavokShape() { return nullptr; } - return std::as_const(*this).getHavokShape(); + return getHavokShapeConst(); } void PolytopeShape::setScale(float scale) { diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h index 1c24a50f..fd5e7c0f 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h @@ -19,6 +19,14 @@ class SphereShape : public Shape { SEAD_RTTI_OVERRIDE(SphereShape, Shape) public: static SphereShape* make(const SphereShapeParam& param, sead::Heap* heap); + SphereShape* clone(sead::Heap* heap) const; + + void setMaterialMask(const MaterialMask& mask); + const MaterialMask& getMaterialMask() const { return mMaterialMask; } + +private: + char _8[0x28 - 0x8]; + MaterialMask mMaterialMask; }; class SphereParam : public RigidBodyInstanceParam { diff --git a/src/KingSystem/Physics/RigidBody/Shape/physShape.h b/src/KingSystem/Physics/RigidBody/Shape/physShape.h index 9f0f91e6..672c6cb4 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/physShape.h @@ -15,6 +15,7 @@ enum class ShapeType { Box = 2, Cylinder = 3, Polytope = 4, + List = 5, CharacterPrism = 6, BoxWater = 7, CylinderWater = 8, @@ -29,11 +30,18 @@ public: virtual ShapeType getType() const = 0; virtual float getVolume() const = 0; virtual ~Shape() = default; + virtual hkpShape* getHavokShape() = 0; virtual const hkpShape* getHavokShape() const = 0; + + /// Update the underlying Havok shape if necessary. This may recreate the Havok shape. + /// @return a pointer to the new underlying Havok shape if it was recreated, null otherwise virtual const hkpShape* updateHavokShape() = 0; + /// @param scale New scale (relative to the current scale) virtual void setScale(float scale) = 0; + + const hkpShape* getHavokShapeConst() const { return getHavokShape(); } }; struct CommonShapeParam { diff --git a/src/KingSystem/Physics/physHeapUtil.h b/src/KingSystem/Physics/physHeapUtil.h new file mode 100644 index 00000000..06890a95 --- /dev/null +++ b/src/KingSystem/Physics/physHeapUtil.h @@ -0,0 +1,21 @@ +#pragma once + +#include <Havok/Common/Base/Object/hkReferencedObject.h> + +namespace ksys::phys { + +template <typename T> +inline std::enable_if_t<std::is_base_of_v<hkReferencedObject, T>, void> +deleteRefCountedHavokObject(T*& object) { + if (!object) + return; + + /// @bug This should just be a delete expression. Decrementing the reference count + /// n times (with n = the reference count) is not how reference counting is supposed to work. + for (int i = 0, n = object->getReferenceCount(); i < n; ++i) + object->removeReference(); + + object = nullptr; +} + +} // namespace ksys::phys |
