1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#pragma once
#include "KingSystem/Physics/System/physGroupFilter.h"
#include "KingSystem/Physics/physDefines.h"
namespace ksys::phys {
class SensorSystemGroupHandler : public SystemGroupHandler {
public:
explicit SensorSystemGroupHandler(int i) : SystemGroupHandler(i, ContactLayerType::Sensor) {}
u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) override;
u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
bool m8() override;
};
class SensorGroupFilter : public GroupFilter {
SEAD_RTTI_OVERRIDE(SensorGroupFilter, GroupFilter)
public:
static SensorGroupFilter* make(ContactLayer::ValueType last, sead::Heap* heap);
SensorGroupFilter(ContactLayer::ValueType first, ContactLayer::ValueType last);
~SensorGroupFilter() override;
hkBool isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const override;
hkBool isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& a,
const hkpCdBody& b, const hkpShapeContainer& bContainer,
hkpShapeKey bKey) const override;
hkBool isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& collectionBodyA,
const hkpCdBody& collectionBodyB,
const hkpShapeContainer& containerShapeA,
const hkpShapeContainer& containerShapeB, hkpShapeKey keyA,
hkpShapeKey keyB) const override;
hkBool isCollisionEnabled(const hkpShapeRayCastInput& aInput,
const hkpShapeContainer& bContainer, hkpShapeKey bKey) const override;
hkBool isCollisionEnabled(const hkpWorldRayCastInput& inputA,
const hkpCollidable& collidableB) const 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;
u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) override;
virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5,
u32 unk10);
virtual void setSensorLayerCollisionEnabledMask(ContactLayer layer, u32 mask);
protected:
/// Checks whether two sensors are colliding.
hkBool testCollisionForSensors(u32 infoA, u32 infoB) const;
hkBool testCollisionForRayCasting(u32 infoRayCast, u32 info) const;
void doInitSystemGroupHandlerLists_(sead::Heap* heap) override;
int getFreeListIndex(const SystemGroupHandler* handler) override;
void doInit_(sead::Heap* heap) override;
};
/// Set the contact layer in a sensor collision mask.
/// @param layer A sensor contact layer
/// @param mask An existing sensor collision mask
u32 sensorCollisionMaskSetLayer(ContactLayer layer, u32 mask);
/// Set or clear a contact layer to ignore during collision detection in a sensor collision mask.
/// This function does nothing when using a custom receiver.
/// @param set If true, set the specified layer. Clear it otherwise
/// @param layer A sensor contact layer to be ignored
/// @param mask An existing sensor collision mask
u32 sensorCollisionMaskSetIgnoredLayer(bool set, ContactLayer layer, u32 mask);
inline u32 SensorSystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLayer layer,
GroundHit ground_hit) {
const SensorCollisionMask current_info{info};
SensorCollisionMask result;
if (layer == ContactLayer::SensorCustomReceiver) {
result.is_custom_receiver = true;
result.group_handler_index.Init(getIndex());
result.custom_receiver_data.layer.Init(current_info.custom_receiver_data.layer);
} else {
result.is_custom_receiver = false;
result.group_handler_index.Init(getIndex());
result.data.layer.Init(layer - FirstSensor);
}
return result.raw;
}
inline u32 SensorSystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
bool unk) {
SensorQueryCollisionMask mask;
mask.layer_mask = layer_mask;
mask.group_handler_index.Init(getIndex());
return mask.raw;
}
inline bool SensorSystemGroupHandler::m8() {
return getIndex() > 0 && getIndex() < 0x400;
}
inline u32 SensorGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) {
return SensorCollisionMask::make(layer).raw;
}
inline ContactLayer SensorGroupFilter::getCollisionFilterInfoLayer(u32 info) {
return SensorCollisionMask(info).getLayer();
}
inline u32 SensorGroupFilter::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit,
bool unk) {
SensorQueryCollisionMask mask;
mask.layer_mask = layer_mask;
return mask.raw;
}
inline GroundHit SensorGroupFilter::getQueryCollisionMaskGroundHit(u32 info) {
return GroundHit::HitAll;
}
inline void SensorGroupFilter::getCollisionFilterInfoLayerAndGroundHit(u32 info,
ContactLayer* layer,
GroundHit* ground_hit) {
SensorCollisionMask mask{info};
*layer = mask.getLayer();
*ground_hit = {};
}
inline const char* SensorGroupFilter::getCollisionFilterInfoLayerText(u32 info) {
return contactLayerToText(getCollisionFilterInfoLayer(info));
}
inline u32 SensorGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
return SensorCollisionMask(info).group_handler_index;
}
inline u32 SensorGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
u32 unk5, u32 unk10) {
return 0;
}
inline void SensorGroupFilter::setSensorLayerCollisionEnabledMask(ContactLayer layer, u32 mask) {
m_collisionLookupTable[layer - mLayerFirst] = mask;
}
} // namespace ksys::phys
|