mirror of https://github.com/zeldaret/botw.git
ksys/phys: Add more EntityGroupFilter functions
This commit is contained in:
parent
b3b97a93aa
commit
c32557b793
|
@ -83797,17 +83797,17 @@ Address,Quality,Size,Name
|
|||
0x0000007100fb503c,O,000096,_ZThn32_N4ksys4phys17EntityGroupFilterD0Ev
|
||||
0x0000007100fb509c,O,000096,_ZThn40_N4ksys4phys17EntityGroupFilterD0Ev
|
||||
0x0000007100fb50fc,O,000032,_ZN4ksys4phys17EntityGroupFilter7doInit_EPN4sead4HeapE
|
||||
0x0000007100fb511c,U,001440,phys::EntityGroupFilter::isCollisionEnabled
|
||||
0x0000007100fb511c,m,001440,_ZNK4ksys4phys17EntityGroupFilter24testCollisionForEntitiesEjj
|
||||
0x0000007100fb56bc,O,000268,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK13hkpCollidableS4_
|
||||
0x0000007100fb57c8,O,000028,_ZThn16_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK13hkpCollidableS4_
|
||||
0x0000007100fb57e4,O,000176,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerSA_jj
|
||||
0x0000007100fb5894,O,000176,_ZThn24_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerSA_jj
|
||||
0x0000007100fb5944,O,000304,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerj
|
||||
0x0000007100fb5a74,O,000028,_ZThn24_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK17hkpCollisionInputRK9hkpCdBodyS7_RK17hkpShapeContainerj
|
||||
0x0000007100fb5a90,U,000284,phys::EntityGroupFilter::isCollisionEnabled__3
|
||||
0x0000007100fb5bac,U,000284,
|
||||
0x0000007100fb5cc8,U,000256,phys::EntityGroupFilter::isCollisionEnabled__4
|
||||
0x0000007100fb5dc8,U,000028,
|
||||
0x0000007100fb5a90,O,000284,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpShapeRayCastInputRK17hkpShapeContainerj
|
||||
0x0000007100fb5bac,O,000284,_ZThn32_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpShapeRayCastInputRK17hkpShapeContainerj
|
||||
0x0000007100fb5cc8,O,000256,_ZNK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpWorldRayCastInputRK13hkpCollidable
|
||||
0x0000007100fb5dc8,O,000028,_ZThn40_NK4ksys4phys17EntityGroupFilter18isCollisionEnabledERK20hkpWorldRayCastInputRK13hkpCollidable
|
||||
0x0000007100fb5de4,O,000192,_ZN4ksys4phys17EntityGroupFilter30doInitSystemGroupHandlerLists_EPN4sead4HeapE
|
||||
0x0000007100fb5ea4,O,000016,_ZN4ksys4phys17EntityGroupFilter16getFreeListIndexEPKNS0_18SystemGroupHandlerE
|
||||
0x0000007100fb5eb4,O,000036,_ZN4ksys4phys21orEntityGroundHitMaskEjNS0_9GroundHitE
|
||||
|
@ -83815,29 +83815,29 @@ Address,Quality,Size,Name
|
|||
0x0000007100fb5f14,O,000032,_ZN4ksys4phys23makeEntityGroundHitMaskENS0_12ContactLayerEj
|
||||
0x0000007100fb5f34,O,000068,_ZN4ksys4phys23makeEntityCollisionMaskENS0_12ContactLayerEj
|
||||
0x0000007100fb5f78,O,000036,_ZN4ksys4phys31setEntityCollisionMaskGroundHitENS0_9GroundHitEj
|
||||
0x0000007100fb5f9c,U,000084,EntitySystemGroupHandler::m5
|
||||
0x0000007100fb5ff0,U,000048,EntitySystemGroupHandler::m6
|
||||
0x0000007100fb6020,U,000040,EntitySystemGroupHandler::m7
|
||||
0x0000007100fb6048,U,000020,EntitySystemGroupHandler::m8
|
||||
0x0000007100fb5f9c,O,000084,_ZN4ksys4phys24EntitySystemGroupHandler23makeCollisionFilterInfoEjNS0_12ContactLayerENS0_9GroundHitE
|
||||
0x0000007100fb5ff0,O,000048,_ZN4ksys4phys24EntitySystemGroupHandler22makeQueryCollisionMaskEjNS0_9GroundHitEb
|
||||
0x0000007100fb6020,O,000040,_ZN4ksys4phys24EntitySystemGroupHandler30makeRagdollCollisionFilterInfoENS0_9GroundHitE
|
||||
0x0000007100fb6048,O,000020,_ZN4ksys4phys24EntitySystemGroupHandler2m8Ev
|
||||
0x0000007100fb605c,O,000112,_ZNK4ksys4phys18SystemGroupHandler27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fb60cc,O,000092,_ZNK4ksys4phys18SystemGroupHandler18getRuntimeTypeInfoEv
|
||||
0x0000007100fb6128,O,000004,_ZN4ksys4phys18SystemGroupHandlerD2Ev
|
||||
0x0000007100fb612c,O,000004,_ZN4ksys4phys18SystemGroupHandlerD0Ev
|
||||
0x0000007100fb612c,O,000004,_ZN4ksys4phys24EntitySystemGroupHandlerD0Ev
|
||||
0x0000007100fb6130,O,000004,_ZN18hkpCollisionFilter4initEP8hkpWorld
|
||||
0x0000007100fb6134,O,000008,_ZN14hkpGroupFilter11dummyUnusedEv
|
||||
0x0000007100fb613c,O,000204,_ZNK4ksys4phys17EntityGroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fb6208,O,000092,_ZNK4ksys4phys17EntityGroupFilter18getRuntimeTypeInfoEv
|
||||
0x0000007100fb6264,U,000044,phys::EntityGroupFilter::m2
|
||||
0x0000007100fb6290,U,000028,phys::EntityGroupFilter::m3
|
||||
0x0000007100fb62ac,U,000020,phys::EntityGroupFilter::m4
|
||||
0x0000007100fb62c0,U,000028,phys::EntityGroupFilter::m5
|
||||
0x0000007100fb62dc,U,000008,phys::EntityGroupFilter::m6
|
||||
0x0000007100fb62e4,U,000040,phys::EntityGroupFilter::m7
|
||||
0x0000007100fb630c,U,000048,phys::EntityGroupFilter::m8_GetStringGroundHitMaskModeOrSensorText
|
||||
0x0000007100fb6264,O,000044,_ZN4ksys4phys17EntityGroupFilter2m2ENS0_12ContactLayerES2_
|
||||
0x0000007100fb6290,O,000028,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitE
|
||||
0x0000007100fb62ac,O,000020,_ZN4ksys4phys17EntityGroupFilter27getCollisionFilterInfoLayerEj
|
||||
0x0000007100fb62c0,O,000028,_ZN4ksys4phys17EntityGroupFilter22makeQueryCollisionMaskEjNS0_9GroundHitEb
|
||||
0x0000007100fb62dc,O,000008,_ZN4ksys4phys17EntityGroupFilter30getQueryCollisionMaskGroundHitEj
|
||||
0x0000007100fb62e4,O,000040,_ZN4ksys4phys17EntityGroupFilter39getCollisionFilterInfoLayerAndGroundHitEjPNS0_12ContactLayerEPNS0_9GroundHitE
|
||||
0x0000007100fb630c,O,000048,_ZN4ksys4phys17EntityGroupFilter31getCollisionFilterInfoLayerTextEj
|
||||
0x0000007100fb633c,O,000036,_ZN4ksys4phys17EntityGroupFilter18setLayerCustomMaskENS0_12ContactLayerEj
|
||||
0x0000007100fb6360,U,000008,phys::EntityGroupFilter::m10
|
||||
0x0000007100fb6368,U,000044,phys::EntityGroupFilter::m14
|
||||
0x0000007100fb6394,U,000028,phys::EntityGroupFilter::m15
|
||||
0x0000007100fb6360,O,000008,_ZN4ksys4phys17EntityGroupFilter37getCollisionFilterInfoGroupHandlerIdxEj
|
||||
0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj
|
||||
0x0000007100fb6394,O,000028,_ZN4ksys4phys17EntityGroupFilter34setEntityLayerCollisionEnabledMaskENS0_12ContactLayerEj
|
||||
0x0000007100fb63b0,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys11GroupFilterEE9isDerivedEPKNS0_9InterfaceE
|
||||
0x0000007100fb643c,U,000108,phys::makeEntityContactListener
|
||||
0x0000007100fb64a8,U,000004,j_ksys::phys::ContactListener::dtor
|
||||
|
@ -93391,7 +93391,7 @@ Address,Quality,Size,Name
|
|||
0x0000007101213c68,O,000148,_ZN4ksys4phys11GroupFilter7destroyEv
|
||||
0x0000007101213cfc,O,000160,_ZN4ksys4phys11GroupFilter21addSystemGroupHandlerEi
|
||||
0x0000007101213d9c,O,000148,_ZN4ksys4phys11GroupFilter24removeSystemGroupHandlerEPNS0_18SystemGroupHandlerE
|
||||
0x0000007101213e30,O,000008,_ZN4ksys4phys18SystemGroupHandler2m7Ev
|
||||
0x0000007101213e30,O,000008,_ZN4ksys4phys18SystemGroupHandler30makeRagdollCollisionFilterInfoENS0_9GroundHitE
|
||||
0x0000007101213e38,O,000024,_ZN4ksys4phys18SystemGroupHandler10removeThisEv
|
||||
0x0000007101213e50,O,000112,_ZNK4ksys4phys11GroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007101213ec0,O,000092,_ZNK4ksys4phys11GroupFilter18getRuntimeTypeInfoEv
|
||||
|
|
Can't render this file because it is too large.
|
|
@ -63,6 +63,7 @@ public:
|
|||
inline hkUint32 getCollisionFilterInfo() const;
|
||||
inline void setCollisionFilterInfo(hkUint32 info);
|
||||
|
||||
/// @see hkpWorldObject::BroadPhaseType
|
||||
inline int getType() const;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <Havok/Common/Base/Types/hkBaseTypes.h>
|
||||
|
||||
class hkpWorldRayCastInput;
|
||||
class hkpCollidable;
|
||||
struct hkpWorldRayCastInput;
|
||||
|
||||
class hkpRayCollidableFilter {
|
||||
public:
|
||||
|
|
|
@ -602,8 +602,8 @@ void RigidBody::enableGroundCollision(bool enabled) {
|
|||
|
||||
const auto current_info = getEntityCollisionFilterInfo();
|
||||
auto info = current_info;
|
||||
info.unk5 = false;
|
||||
info.no_ground_collision.SetBit(!enabled);
|
||||
info.ground_col_mode =
|
||||
enabled ? GroundCollisionMode::Normal : GroundCollisionMode::IgnoreGround;
|
||||
if (current_info != info)
|
||||
setCollisionFilterInfo(info.raw);
|
||||
}
|
||||
|
@ -615,9 +615,8 @@ bool RigidBody::isGroundCollisionEnabled() const {
|
|||
const auto info = getEntityCollisionFilterInfo();
|
||||
|
||||
bool enabled = false;
|
||||
enabled |= info.unk5;
|
||||
enabled |= info.ground_col_mode != GroundCollisionMode::IgnoreGround;
|
||||
enabled |= info.unk30;
|
||||
enabled |= !info.no_ground_collision;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
@ -630,7 +629,7 @@ void RigidBody::enableWaterCollision(bool enabled) {
|
|||
|
||||
const auto current_info = getEntityCollisionFilterInfo();
|
||||
auto info = current_info;
|
||||
info.no_water_collision = !enabled;
|
||||
info.water_col_mode = enabled ? WaterCollisionMode::Normal : WaterCollisionMode::IgnoreWater;
|
||||
if (current_info != info)
|
||||
setCollisionFilterInfo(info.raw);
|
||||
}
|
||||
|
@ -644,7 +643,7 @@ bool RigidBody::isWaterCollisionEnabled() const {
|
|||
bool enabled = false;
|
||||
// unk30 enables all collisions?
|
||||
enabled |= info.unk30;
|
||||
enabled |= !info.no_water_collision;
|
||||
enabled |= info.water_col_mode != WaterCollisionMode::IgnoreWater;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
#include <Havok/Physics2012/Collide/Agent/Collidable/hkpCollidable.h>
|
||||
#include <Havok/Physics2012/Collide/Agent/hkpCollisionInput.h>
|
||||
#include <Havok/Physics2012/Collide/Dispatch/hkpCollisionDispatcher.h>
|
||||
#include <Havok/Physics2012/Collide/Query/CastUtil/hkpWorldRayCastInput.h>
|
||||
#include <Havok/Physics2012/Collide/Shape/Compound/Collection/hkpShapeCollection.h>
|
||||
#include <Havok/Physics2012/Collide/Shape/Compound/Tree/hkpBvTreeShape.h>
|
||||
#include <Havok/Physics2012/Collide/Shape/Query/hkpShapeRayCastInput.h>
|
||||
#include <Havok/Physics2012/Collide/Shape/hkpShapeContainer.h>
|
||||
#include <Havok/Physics2012/Dynamics/World/hkpWorldObject.h>
|
||||
#include <heap/seadHeap.h>
|
||||
#include "Havok/Physics2012/Dynamics/Entity/hkpEntity.h"
|
||||
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
|
||||
#include "KingSystem/Physics/System/physContactMgr.h"
|
||||
#include "KingSystem/Physics/System/physSystem.h"
|
||||
#include "KingSystem/Utils/BitField.h"
|
||||
|
@ -49,16 +53,170 @@ void EntityGroupFilter::doInit_(sead::Heap* heap) {
|
|||
mMasks.fill(0xffffffff);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabledPhantom(u32 infoPhantom, u32 infoB) const {
|
||||
hkBool EntityGroupFilter::shouldHandleGroundCollision(u32 infoA, u32 infoB,
|
||||
ContactLayer::ValueType layerA,
|
||||
ContactLayer::ValueType layerB) const {
|
||||
const EntityCollisionFilterInfo a{infoA};
|
||||
const EntityCollisionFilterInfo b{infoB};
|
||||
|
||||
if (EntityCollisionFilterInfo(infoA | infoB).ground_col_mode != GroundCollisionMode::Normal) {
|
||||
if (a.ground_col_mode != GroundCollisionMode::Normal) {
|
||||
bool ground = isEntityGroundLayer(layerB);
|
||||
if (a.ground_col_mode == GroundCollisionMode::IgnoreNonGround && !ground)
|
||||
return false;
|
||||
if (a.ground_col_mode == GroundCollisionMode::IgnoreGround && ground)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (b.ground_col_mode != GroundCollisionMode::Normal) {
|
||||
bool ground = isEntityGroundLayer(layerA);
|
||||
if (b.ground_col_mode == GroundCollisionMode::IgnoreNonGround && !ground)
|
||||
return false;
|
||||
if (b.ground_col_mode == GroundCollisionMode::IgnoreGround && ground)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::shouldHandleWaterCollision(u32 infoA, u32 infoB,
|
||||
ContactLayer::ValueType layerA,
|
||||
ContactLayer::ValueType layerB) const {
|
||||
const EntityCollisionFilterInfo a{infoA};
|
||||
const EntityCollisionFilterInfo b{infoB};
|
||||
|
||||
if (EntityCollisionFilterInfo(infoA | infoB).water_col_mode != WaterCollisionMode::Normal) {
|
||||
if (a.water_col_mode == WaterCollisionMode::IgnoreWater &&
|
||||
layerB == ContactLayer::EntityWater) {
|
||||
return false;
|
||||
}
|
||||
if (b.water_col_mode == WaterCollisionMode::IgnoreWater &&
|
||||
layerA == ContactLayer::EntityWater) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX: find a better name
|
||||
static bool testHandler(u32 idx) {
|
||||
return idx != 0 && idx <= 15;
|
||||
}
|
||||
|
||||
// NON_MATCHING: deduplicated branch: `return a.data.query_custom_receiver_layer_mask & (1 << ...)`
|
||||
hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
|
||||
if (mInhibitCollisions)
|
||||
return false;
|
||||
|
||||
// TODO: figure out what kind of mask infoPhantom is. Receiver/sensor mask?
|
||||
// RigidBodyParam::getParams and ContactInfoTable seem to manipulate similar looking masks.
|
||||
const EntityCollisionFilterInfo a{infoA};
|
||||
const EntityCollisionFilterInfo b{infoB};
|
||||
|
||||
constexpr auto GroupHandlerIdxMask = decltype(a.group_handler_index)::GetMask();
|
||||
constexpr auto GroupHandlerIdxShift = decltype(a.group_handler_index)::StartBit();
|
||||
|
||||
if (!EntityCollisionFilterInfo(infoA | infoB).is_ground_hit_mask) {
|
||||
if (a.unk30 && b.unk30) {
|
||||
if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
|
||||
if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
|
||||
return false;
|
||||
} else if ((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift != 0) {
|
||||
if (a.data.unk5 == b.data.unk10 || b.data.unk5 == a.data.unk10)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
|
||||
|
||||
if (layerA != ContactLayer::EntityQueryCustomReceiver &&
|
||||
layerB != ContactLayer::EntityQueryCustomReceiver) {
|
||||
if (!a.unk30 && !b.unk30) {
|
||||
if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
|
||||
if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
|
||||
return false;
|
||||
} else if (((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift) > 15) {
|
||||
return false;
|
||||
}
|
||||
return testLayerCollision(layerA, layerB);
|
||||
}
|
||||
|
||||
if (layerA == ContactLayer::EntityQueryCustomReceiver &&
|
||||
layerB == ContactLayer::EntityQueryCustomReceiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layerA == ContactLayer::EntityQueryCustomReceiver)
|
||||
return a.data.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
else
|
||||
return b.data.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
}
|
||||
|
||||
if (a.is_ground_hit_mask && b.is_ground_hit_mask) {
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.ground_hit.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.ground_hit.layer.Value());
|
||||
|
||||
if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!testLayerCollision(layerA, layerB))
|
||||
return false;
|
||||
return !a.ground_hit.unk23 && !b.ground_hit.unk23;
|
||||
}
|
||||
|
||||
EntityCollisionFilterInfo entity_mask, ground_hit_mask;
|
||||
|
||||
if (a.is_ground_hit_mask && !b.is_ground_hit_mask) {
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.ground_hit.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
|
||||
entity_mask = b;
|
||||
ground_hit_mask = a;
|
||||
|
||||
if (layerB == ContactLayer::EntityQueryCustomReceiver)
|
||||
return b.data.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
|
||||
if (!b.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!b.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!testLayerCollision(layerA, layerB))
|
||||
return false;
|
||||
|
||||
} else /* A entity, B ground hit */ {
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.ground_hit.layer.Value());
|
||||
entity_mask = a;
|
||||
ground_hit_mask = b;
|
||||
|
||||
if (layerA == ContactLayer::EntityQueryCustomReceiver)
|
||||
return a.data.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
|
||||
if (!a.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!a.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!testLayerCollision(layerB, layerA))
|
||||
return false;
|
||||
}
|
||||
return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.data.ground_hit));
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) const {
|
||||
if (mInhibitCollisions)
|
||||
return false;
|
||||
|
||||
RayCastCollisionMask infoPhantomData{infoPhantom};
|
||||
const EntityCollisionFilterInfo info{infoB};
|
||||
if (info.is_ground_hit_mask)
|
||||
return infoPhantom & (1 << info.ground_hit.getLayer());
|
||||
return (infoPhantom & (1 << info.data.layer)) & 0x1ffff;
|
||||
return infoPhantomData.raw & (1 << info.ground_hit.getLayer());
|
||||
return infoPhantomData.layer_mask & (1 << info.data.layer);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const {
|
||||
|
@ -69,19 +227,19 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCo
|
|||
|
||||
if (a.getType() == hkpWorldObject::BROAD_PHASE_PHANTOM) {
|
||||
if (a.getShape() != nullptr)
|
||||
return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
|
||||
return isCollisionEnabledPhantom(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
return testCollisionForPhantom(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
}
|
||||
|
||||
if (b.getType() == hkpWorldObject::BROAD_PHASE_PHANTOM) {
|
||||
if (b.getShape() != nullptr)
|
||||
return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
|
||||
return isCollisionEnabledPhantom(b.getCollisionFilterInfo(), a.getCollisionFilterInfo());
|
||||
return testCollisionForPhantom(b.getCollisionFilterInfo(), a.getCollisionFilterInfo());
|
||||
}
|
||||
|
||||
return isCollisionEnabled(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
return testCollisionForEntities(a.getCollisionFilterInfo(), b.getCollisionFilterInfo());
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input,
|
||||
|
@ -98,7 +256,7 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input,
|
|||
if (infoB == 0xffffffff)
|
||||
infoB = collectionBodyB.getRootCollidable()->getCollisionFilterInfo();
|
||||
|
||||
return isCollisionEnabled(infoA, infoB);
|
||||
return testCollisionForEntities(infoA, infoB);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& a,
|
||||
|
@ -150,7 +308,72 @@ hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, con
|
|||
}
|
||||
|
||||
end:
|
||||
return isCollisionEnabled(infoA, infoB);
|
||||
return testCollisionForEntities(infoA, infoB);
|
||||
}
|
||||
|
||||
static hkBool
|
||||
checkCollisionWithGroundHitMask(EntityCollisionFilterInfo::GroundHitMask ground_hit_mask,
|
||||
RayCastCollisionMask ray_cast) {
|
||||
if (!(ray_cast.layer_mask & (1 << ground_hit_mask.getLayer())))
|
||||
return false;
|
||||
|
||||
if (ground_hit_mask.unk & ray_cast.unk)
|
||||
return false;
|
||||
|
||||
if (ground_hit_mask.ground_hit_types & (1 << ray_cast.ground_hit_type))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::testCollisionForRayCasting(u32 infoRayCast, u32 info) const {
|
||||
if (mInhibitCollisions)
|
||||
return false;
|
||||
|
||||
RayCastCollisionMask a{infoRayCast};
|
||||
EntityCollisionFilterInfo b{info};
|
||||
|
||||
if (b.is_ground_hit_mask)
|
||||
return checkCollisionWithGroundHitMask(b.ground_hit, a);
|
||||
|
||||
const u32 bHandlerIdx = b.group_handler_index;
|
||||
const u32 aHandlerIdx = a.group_handler_index;
|
||||
|
||||
if (aHandlerIdx == bHandlerIdx) {
|
||||
if (bHandlerIdx > 15)
|
||||
return false;
|
||||
return a.layer_mask & (1 << b.data.layer);
|
||||
}
|
||||
|
||||
if (testHandler(aHandlerIdx) || testHandler(bHandlerIdx))
|
||||
return false;
|
||||
|
||||
return a.layer_mask & (1 << b.data.layer);
|
||||
}
|
||||
|
||||
KSYS_ALWAYS_INLINE hkBool EntityGroupFilter::isCollisionEnabled(const hkpShapeRayCastInput& aInput,
|
||||
const hkpShapeContainer& bContainer,
|
||||
hkpShapeKey bKey) const {
|
||||
u32 bInfo = bContainer.getCollisionFilterInfo(bKey);
|
||||
if (bInfo == 0)
|
||||
return true;
|
||||
|
||||
if (bInfo == 0xffffffff)
|
||||
bInfo = aInput.m_collidable->getCollisionFilterInfo();
|
||||
|
||||
return testCollisionForRayCasting(aInput.m_filterInfo, bInfo);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpWorldRayCastInput& inputA,
|
||||
const hkpCollidable& collidableB) const {
|
||||
if (collidableB.getType() == hkpWorldObject::BROAD_PHASE_ENTITY) {
|
||||
auto* entity = static_cast<const hkpEntity*>(collidableB.getOwner());
|
||||
auto* body = entity ? reinterpret_cast<RigidBody*>(entity->getUserData()) : nullptr;
|
||||
if (body && body->hasFlag(RigidBody::Flag::_200))
|
||||
return false;
|
||||
}
|
||||
|
||||
return testCollisionForRayCasting(inputA.m_filterInfo, collidableB.getCollisionFilterInfo());
|
||||
}
|
||||
|
||||
void EntityGroupFilter::doInitSystemGroupHandlerLists_(sead::Heap* heap) {
|
||||
|
|
|
@ -13,7 +13,8 @@ public:
|
|||
explicit EntitySystemGroupHandler(int i) : SystemGroupHandler(i, ContactLayerType::Entity) {}
|
||||
|
||||
u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) override;
|
||||
u32 m6() override;
|
||||
u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
|
||||
u32 makeRagdollCollisionFilterInfo(GroundHit ground_hit) override;
|
||||
bool m8() override;
|
||||
};
|
||||
|
||||
|
@ -40,27 +41,42 @@ public:
|
|||
hkBool isCollisionEnabled(const hkpWorldRayCastInput& inputA,
|
||||
const hkpCollidable& collidableB) const override;
|
||||
|
||||
bool m2() override { return GroupFilter::m2(); }
|
||||
void m3() override {}
|
||||
void m4() override {}
|
||||
void m5() override {}
|
||||
void m6() override {}
|
||||
void m7() override {}
|
||||
void m8() override {}
|
||||
bool m2(ContactLayer layerA, ContactLayer layerB) override;
|
||||
u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) override;
|
||||
ContactLayer getCollisionFilterInfoLayer(u32 info) override;
|
||||
u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
|
||||
GroundHit getQueryCollisionMaskGroundHit(u32 info) override;
|
||||
void getCollisionFilterInfoLayerAndGroundHit(u32 info, ContactLayer* layer,
|
||||
GroundHit* ground_hit) override;
|
||||
const char* getCollisionFilterInfoLayerText(u32 info) override;
|
||||
void setLayerCustomMask(ContactLayer layer, u32 mask) override;
|
||||
u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) override;
|
||||
|
||||
void setLayerCustomMask(ContactLayer layer, u32 mask) override { mMasks[layer] = mask; }
|
||||
|
||||
void m10() override {}
|
||||
virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5,
|
||||
u32 unk10);
|
||||
/// @param layer An entity layer
|
||||
virtual void setEntityLayerCollisionEnabledMask(ContactLayer layer, u32 mask);
|
||||
|
||||
private:
|
||||
hkBool isCollisionEnabled(u32 infoA, u32 infoB) const;
|
||||
hkBool isCollisionEnabledPhantom(u32 infoPhantom, u32 infoB) const;
|
||||
/// Checks whether two entities are colliding.
|
||||
hkBool testCollisionForEntities(u32 infoA, u32 gh_mask) const;
|
||||
/// Checks whether a phantom and an entity are colliding with each other.
|
||||
hkBool testCollisionForPhantom(u32 infoPhantom, u32 infoB) const;
|
||||
/// Checks whether a ray cast and an entity are colliding with each other.
|
||||
hkBool testCollisionForRayCasting(u32 infoRayCast, u32 info) const;
|
||||
|
||||
hkBool shouldHandleGroundCollision(u32 infoA, u32 infoB, ContactLayer::ValueType layerA,
|
||||
ContactLayer::ValueType layerB) const;
|
||||
hkBool shouldHandleWaterCollision(u32 infoA, u32 infoB, ContactLayer::ValueType layerA,
|
||||
ContactLayer::ValueType layerB) const;
|
||||
|
||||
hkBool testLayerCollision(ContactLayer::ValueType a, ContactLayer::ValueType b) const {
|
||||
return m_collisionLookupTable[a] & (1 << b);
|
||||
}
|
||||
|
||||
void doInitSystemGroupHandlerLists_(sead::Heap* heap) override;
|
||||
int getFreeListIndex(const SystemGroupHandler* handler) override;
|
||||
void doInit_(sead::Heap* heap) override;
|
||||
virtual void m14();
|
||||
virtual void m15();
|
||||
|
||||
sead::SafeArray<u32, ContactLayer::size()> mMasks;
|
||||
};
|
||||
|
@ -84,4 +100,111 @@ u32 makeEntityCollisionMask(ContactLayer layer, u32 mask);
|
|||
/// Updates the collision mask with the specified ground hit type (*not* mask).
|
||||
u32 setEntityCollisionMaskGroundHit(GroundHit ground_hit, u32 mask);
|
||||
|
||||
inline u32 EntitySystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLayer layer,
|
||||
GroundHit ground_hit) {
|
||||
const EntityCollisionFilterInfo current_info{info};
|
||||
EntityCollisionFilterInfo result;
|
||||
|
||||
if (layer == ContactLayer::EntityRagdoll) {
|
||||
result.data.layer.Init(layer);
|
||||
result.data.unk5.Init(current_info.data.unk5);
|
||||
result.data.unk10.Init(current_info.data.unk10);
|
||||
result.group_handler_index.Init(getIndex());
|
||||
result.data.ground_hit.Init(ground_hit);
|
||||
result.unk30 = true;
|
||||
} else {
|
||||
result.data.layer.Init(layer);
|
||||
result.ground_col_mode.Init(current_info.ground_col_mode);
|
||||
result.group_handler_index.Init(getIndex());
|
||||
result.data.ground_hit.Init(ground_hit);
|
||||
}
|
||||
return result.raw;
|
||||
}
|
||||
|
||||
inline u32 EntitySystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
|
||||
bool unk) {
|
||||
RayCastCollisionMask mask;
|
||||
mask.layer_mask = layer_mask;
|
||||
mask.group_handler_index.Init(getIndex());
|
||||
mask.ground_hit_type.Init(static_cast<GroundHit::ValueType>(int(ground_hit)));
|
||||
mask.unk.SetBit(unk);
|
||||
return mask.raw;
|
||||
}
|
||||
|
||||
inline u32 EntitySystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) {
|
||||
EntityCollisionFilterInfo info;
|
||||
info.data.layer.Init(ContactLayer::EntityRagdoll);
|
||||
info.group_handler_index.Init(getIndex());
|
||||
info.data.ground_hit.Init(ground_hit);
|
||||
return info.raw;
|
||||
}
|
||||
|
||||
inline bool EntitySystemGroupHandler::m8() {
|
||||
return getIndex() > 0 && getIndex() < 0x400;
|
||||
}
|
||||
|
||||
inline bool EntityGroupFilter::m2(ContactLayer layerA, ContactLayer layerB) {
|
||||
return (mMasks[layerA.value()] & (1 << layerB.value())) == 0;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) {
|
||||
return EntityCollisionFilterInfo::make(layer, ground_hit).raw;
|
||||
}
|
||||
|
||||
inline ContactLayer EntityGroupFilter::getCollisionFilterInfoLayer(u32 info) {
|
||||
return EntityCollisionFilterInfo(info).getLayer();
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
|
||||
bool unk) {
|
||||
RayCastCollisionMask mask;
|
||||
mask.layer_mask = layer_mask;
|
||||
mask.ground_hit_type = ground_hit.value();
|
||||
mask.unk.SetBit(unk);
|
||||
return mask.raw;
|
||||
}
|
||||
|
||||
inline GroundHit EntityGroupFilter::getQueryCollisionMaskGroundHit(u32 info) {
|
||||
return RayCastCollisionMask(info).ground_hit_type.Value();
|
||||
}
|
||||
|
||||
inline void EntityGroupFilter::getCollisionFilterInfoLayerAndGroundHit(u32 info,
|
||||
ContactLayer* layer,
|
||||
GroundHit* ground_hit) {
|
||||
EntityCollisionFilterInfo info_{info};
|
||||
*layer = info_.getLayer();
|
||||
*ground_hit = info_.getGroundHit();
|
||||
}
|
||||
|
||||
inline const char* EntityGroupFilter::getCollisionFilterInfoLayerText(u32 info) {
|
||||
EntityCollisionFilterInfo info_{info};
|
||||
if (info_.is_ground_hit_mask) {
|
||||
return "GroundHitMaskMode";
|
||||
}
|
||||
return contactLayerToText(getCollisionFilterInfoLayer(info));
|
||||
}
|
||||
|
||||
inline void EntityGroupFilter::setLayerCustomMask(ContactLayer layer, u32 mask) {
|
||||
mMasks[layer] = mask;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
|
||||
return EntityCollisionFilterInfo(info).group_handler_index;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
|
||||
u32 unk5, u32 unk10) {
|
||||
EntityCollisionFilterInfo info;
|
||||
info.data.layer.Init(layer);
|
||||
info.data.unk5.Init(unk5);
|
||||
info.data.unk10.Init(unk10);
|
||||
info.data.ground_hit.Init(ground_hit);
|
||||
info.unk30 = true;
|
||||
return info.raw;
|
||||
}
|
||||
|
||||
inline void EntityGroupFilter::setEntityLayerCollisionEnabledMask(ContactLayer layer, u32 mask) {
|
||||
m_collisionLookupTable[layer] = mask;
|
||||
}
|
||||
|
||||
} // namespace ksys::phys
|
||||
|
|
|
@ -50,7 +50,7 @@ void GroupFilter::removeSystemGroupHandler(SystemGroupHandler* handler) {
|
|||
mUsedList.erase(handler);
|
||||
}
|
||||
|
||||
u32 SystemGroupHandler::m7() {
|
||||
u32 SystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public:
|
|||
|
||||
virtual ~SystemGroupHandler() = default;
|
||||
virtual u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) = 0;
|
||||
virtual u32 m6() = 0;
|
||||
virtual u32 m7();
|
||||
virtual u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) = 0;
|
||||
virtual u32 makeRagdollCollisionFilterInfo(GroundHit ground_hit);
|
||||
virtual bool m8() = 0;
|
||||
|
||||
int getIndex() const { return mIndex; }
|
||||
|
@ -75,15 +75,31 @@ public:
|
|||
m_collisionLookupTable[layer - getLayerFirst()] = mask;
|
||||
}
|
||||
|
||||
virtual bool m2() { return true; }
|
||||
virtual void m3() = 0;
|
||||
virtual void m4() = 0;
|
||||
virtual void m5() = 0;
|
||||
virtual void m6() = 0;
|
||||
virtual void m7() = 0;
|
||||
virtual void m8() = 0;
|
||||
virtual bool m2(ContactLayer layerA, ContactLayer layerB) { return true; }
|
||||
|
||||
/// Make a collision filter mask with the specified layer and ground hit type.
|
||||
virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) = 0;
|
||||
|
||||
/// Get the layer from a collision filter mask.
|
||||
virtual ContactLayer getCollisionFilterInfoLayer(u32 info) = 0;
|
||||
|
||||
/// Make a query collision mask with the specified layer mask, ground hit type and flag.
|
||||
virtual u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) = 0;
|
||||
|
||||
/// Get the ground hit type from a query collision mask.
|
||||
virtual GroundHit getQueryCollisionMaskGroundHit(u32 info) = 0;
|
||||
|
||||
/// Get the layer and ground hit type from a collision filter mask.
|
||||
virtual void getCollisionFilterInfoLayerAndGroundHit(u32 info, ContactLayer* layer,
|
||||
GroundHit* ground_hit) = 0;
|
||||
|
||||
/// Get the layer from a collision filter mask.
|
||||
virtual const char* getCollisionFilterInfoLayerText(u32 info) = 0;
|
||||
|
||||
virtual void setLayerCustomMask(ContactLayer layer, u32 mask) {}
|
||||
virtual void m10() = 0;
|
||||
|
||||
/// Get the group handler index from a collision filter mask.
|
||||
virtual u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) = 0;
|
||||
|
||||
protected:
|
||||
virtual void doInitSystemGroupHandlerLists_(sead::Heap* heap) = 0;
|
||||
|
|
|
@ -80,6 +80,11 @@ constexpr auto LastEntity = ContactLayer::EntityMeshVisualizer;
|
|||
constexpr auto FirstSensor = ContactLayer::SensorObject;
|
||||
constexpr auto LastSensor = ContactLayer::SensorCustomReceiver;
|
||||
|
||||
constexpr bool isEntityGroundLayer(ContactLayer::ValueType layer) {
|
||||
return layer == ContactLayer::EntityGround || layer == ContactLayer::EntityGroundSmooth ||
|
||||
layer == ContactLayer::EntityGroundRough;
|
||||
}
|
||||
|
||||
SEAD_ENUM(Material,
|
||||
Undefined,\
|
||||
Soil,\
|
||||
|
@ -180,6 +185,22 @@ enum class MotionType {
|
|||
Invalid = -1,
|
||||
};
|
||||
|
||||
enum class GroundCollisionMode {
|
||||
/// Ground collision is not handled in any special way.
|
||||
Normal = 0,
|
||||
/// Any collision with a non-ground layer is ignored.
|
||||
IgnoreNonGround = 1,
|
||||
/// Any collision with a ground layer is ignored.
|
||||
IgnoreGround = 2,
|
||||
};
|
||||
|
||||
enum class WaterCollisionMode {
|
||||
/// Water collision is not handled in any special way.
|
||||
Normal = 0,
|
||||
/// Any collision with a water layer is ignored.
|
||||
IgnoreWater = 1,
|
||||
};
|
||||
|
||||
union ReceiverMask {
|
||||
union Data {
|
||||
util::BitField<0, 5, u32> layer;
|
||||
|
@ -229,6 +250,12 @@ union EntityCollisionFilterInfo {
|
|||
|
||||
u32 raw;
|
||||
util::BitField<0, 5, u32> layer;
|
||||
// TODO: figure out what this is
|
||||
util::BitField<5, 5, u32> unk5;
|
||||
util::BitField<10, 5, u32> unk10;
|
||||
/// Layers to collide with for EntityQueryCustomReceiver entities.
|
||||
// XXX: was 17 chosen because ContactLayer::EntityQueryCustomReceiver = 17?
|
||||
util::BitField<5, 17, u32> query_custom_receiver_layer_mask;
|
||||
util::BitField<24, 1, u32> unk24;
|
||||
util::BitField<25, 1, u32> unk25;
|
||||
util::BitField<26, 4, u32> ground_hit;
|
||||
|
@ -244,7 +271,7 @@ union EntityCollisionFilterInfo {
|
|||
u32 raw;
|
||||
util::BitField<0, 1, u32> unk;
|
||||
util::BitField<8, 16, u32> ground_hit_types;
|
||||
util::BitField<24, 1, u32> unk24;
|
||||
util::BitField<23, 1, u32> unk23;
|
||||
util::BitField<25, 5, u32> layer;
|
||||
};
|
||||
|
||||
|
@ -281,17 +308,35 @@ union EntityCollisionFilterInfo {
|
|||
u32 raw;
|
||||
Data data;
|
||||
GroundHitMask ground_hit;
|
||||
util::BitField<5, 1, bool, u32> unk5;
|
||||
/// Whether ground collision is disabled.
|
||||
util::BitField<6, 1, bool, u32> no_ground_collision;
|
||||
/// Whether water collision is disabled.
|
||||
util::BitField<7, 1, bool, u32> no_water_collision;
|
||||
util::BitField<5, 2, GroundCollisionMode, u32> ground_col_mode;
|
||||
util::BitField<7, 1, WaterCollisionMode, u32> water_col_mode;
|
||||
util::BitField<16, 10, u32> group_handler_index;
|
||||
/// If this flag is set, then this entity will always collide with ground or water,
|
||||
/// regardless of the configured GroundCollisionMode or WaterCollisionMode modes.
|
||||
// TODO: is this "is_ragdoll"? See EntitySystemGroupHandler::makeCollisionFilterInfo.
|
||||
util::BitField<30, 1, bool, u32> unk30;
|
||||
util::BitField<31, 1, bool, u32> is_ground_hit_mask;
|
||||
};
|
||||
static_assert(sizeof(EntityCollisionFilterInfo) == sizeof(u32));
|
||||
|
||||
/// Collision mask that is used for raycast-based queries.
|
||||
union RayCastCollisionMask {
|
||||
constexpr explicit RayCastCollisionMask(u32 raw_ = 0) : raw(raw_) {}
|
||||
constexpr RayCastCollisionMask(const RayCastCollisionMask&) = default;
|
||||
constexpr RayCastCollisionMask& operator=(const RayCastCollisionMask& m) {
|
||||
raw = m.raw;
|
||||
return *this;
|
||||
}
|
||||
constexpr bool operator==(RayCastCollisionMask rhs) const { return raw == rhs.raw; }
|
||||
constexpr bool operator!=(RayCastCollisionMask rhs) const { return raw != rhs.raw; }
|
||||
|
||||
util::BitField<0, 17, u32> layer_mask;
|
||||
util::BitField<17, 1, u32> unk;
|
||||
util::BitField<18, 10, u32> group_handler_index;
|
||||
util::BitField<28, 4, GroundHit::ValueType, u32> ground_hit_type;
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
ContactLayerType getContactLayerType(ContactLayer layer);
|
||||
u32 makeContactLayerMask(ContactLayer layer);
|
||||
u32 getContactLayerBase(ContactLayerType type);
|
||||
|
|
|
@ -132,8 +132,7 @@ struct BitField {
|
|||
|
||||
template <auto bits_ = bits, typename = std::enable_if_t<bits_ == 1>>
|
||||
inline constexpr void SetBit(bool set) {
|
||||
const auto mask = set ? ((static_cast<StorageType>(1) << position) & GetMask()) : 0;
|
||||
storage = (storage & ~GetMask()) | mask;
|
||||
storage = (storage & ~GetMask()) | (set ? GetMask() : 0);
|
||||
}
|
||||
|
||||
/// @warning This does *not* check whether the value fits within the mask,
|
||||
|
|
Loading…
Reference in New Issue