A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
CollisionIgnoreSubsystem.h
Go to the documentation of this file.
1// Fill out your copyright notice in the Description page of Project Settings.
2
3#pragma once
4
5#include "CoreMinimal.h"
6#include "Subsystems/WorldSubsystem.h"
7#include "TimerManager.h"
8#include "Components/PrimitiveComponent.h"
10#include "CollisionIgnoreSubsystem.generated.h"
11//#include "GrippablePhysicsReplication.generated.h"
12
13DECLARE_LOG_CATEGORY_EXTERN(VRE_CollisionIgnoreLog, Log, All);
14
15USTRUCT()
17{
18 GENERATED_BODY()
19public:
21 UPROPERTY()
22 TWeakObjectPtr<UPrimitiveComponent> Prim1;
23 UPROPERTY()
24 TWeakObjectPtr<UPrimitiveComponent> Prim2;
25
27 {
28 Prim1 = nullptr;
29 Prim2 = nullptr;
30 }
31
32 FORCEINLINE bool operator==(const FCollisionPrimPair& Other) const
33 {
34 /*if (!Prim1.IsValid() || !Prim2.IsValid())
35 return false;
36
37 if (!Other.Prim1.IsValid() || !Other.Prim2.IsValid())
38 return false;*/
39
40 return(
41 (Prim1.Get() == Other.Prim1.Get() || Prim1.Get() == Other.Prim2.Get()) &&
42 (Prim2.Get() == Other.Prim1.Get() || Prim2.Get() == Other.Prim2.Get())
43 );
44 }
45
46 friend uint32 GetTypeHash(const FCollisionPrimPair& InKey)
47 {
48 return GetTypeHash(InKey.Prim1) ^ GetTypeHash(InKey.Prim2);
49 }
50
51};
53USTRUCT()
55{
56 GENERATED_BODY()
57public:
58
60 FPhysicsActorHandle Actor1;
61 UPROPERTY()
62 FName BoneName1;
63 FPhysicsActorHandle Actor2;
64 UPROPERTY()
65 FName BoneName2;
66
67 FORCEINLINE bool operator==(const FCollisionIgnorePair& Other) const
68 {
69 return (
70 (BoneName1 == Other.BoneName1 || BoneName1 == Other.BoneName2) &&
71 (BoneName2 == Other.BoneName2 || BoneName2 == Other.BoneName1)
72 );
73 }
74
75 FORCEINLINE bool operator==(const FName& Other) const
76 {
77 return (BoneName1 == Other || BoneName2 == Other);
78 }
79};
80
81USTRUCT()
83{
84 GENERATED_BODY()
85public:
86
87 UPROPERTY()
88 TArray<FCollisionIgnorePair> PairArray;
89};
90
91UCLASS()
92class VREXPANSIONPLUGIN_API UCollisionIgnoreSubsystem : public UWorldSubsystem
93{
94 GENERATED_BODY()
95
96public:
97
100 Super()
101 {
102 }
103
104 virtual bool DoesSupportWorldType(EWorldType::Type WorldType) const override
105 {
106 return WorldType == EWorldType::Game || WorldType == EWorldType::PIE;
107 // Not allowing for editor type as this is a replication subsystem
108 }
109
111 virtual void Initialize(FSubsystemCollectionBase& Collection) override
113 Super::Initialize(Collection);
114 }
115
116 virtual void Deinitialize() override
118 Super::Deinitialize();
119
120 if (UpdateHandle.IsValid())
121 {
122 GetWorld()->GetTimerManager().ClearTimer(UpdateHandle);
123 }
124 }
125
126 UPROPERTY()
127 TMap<FCollisionPrimPair, FCollisionIgnorePairArray> CollisionTrackedPairs;
128 //TArray<FCollisionIgnorePair> CollisionTrackedPairs;
130 UPROPERTY()
132 //TArray<FCollisionIgnorePair> RemovedPairs;
133
134 //
135 void UpdateTimer()
136 {
137
138#if PHYSICS_INTERFACE_PHYSX
139 for (const TPair<FCollisionPrimPair, FCollisionIgnorePairArray>& Pair : RemovedPairs)
140 {
141 bool bSkipPrim1 = false;
142 bool bSkipPrim2 = false;
143
144 if (!Pair.Key.Prim1.IsValid())
145 bSkipPrim1 = true;
146
147 if (!Pair.Key.Prim2.IsValid())
148 bSkipPrim2 = true;
149
150 if (!bSkipPrim1 || !bSkipPrim2)
151 {
152 for (const FCollisionIgnorePair& BonePair : Pair.Value.PairArray)
154 bool bPrim1Exists = false;
155 bool bPrim2Exists = false;
156
157 for (const TPair<FCollisionPrimPair, FCollisionIgnorePairArray>& KeyPair : CollisionTrackedPairs)
158 {
159 if (!bPrim1Exists && !bSkipPrim1)
160 {
161 if (KeyPair.Key.Prim1 == Pair.Key.Prim1)
162 {
163 bPrim1Exists = KeyPair.Value.PairArray.ContainsByPredicate([BonePair](const FCollisionIgnorePair& Other)
164 {
165 return BonePair.BoneName1 == Other.BoneName1;
166 });
167 }
168 else if (KeyPair.Key.Prim2 == Pair.Key.Prim1)
169 {
170 bPrim1Exists = KeyPair.Value.PairArray.ContainsByPredicate([BonePair](const FCollisionIgnorePair& Other)
171 {
172 return BonePair.BoneName1 == Other.BoneName2;
173 });
174 }
175 }
176
177 if (!bPrim2Exists && !bSkipPrim2)
178 {
179 if (KeyPair.Key.Prim1 == Pair.Key.Prim2)
180 {
181 bPrim2Exists = KeyPair.Value.PairArray.ContainsByPredicate([BonePair](const FCollisionIgnorePair& Other)
182 {
183 return BonePair.BoneName2 == Other.BoneName1;
184 });
185 }
186 else if (KeyPair.Key.Prim2 == Pair.Key.Prim2)
187 {
188 bPrim2Exists = KeyPair.Value.PairArray.ContainsByPredicate([BonePair](const FCollisionIgnorePair& Other)
189 {
190 return BonePair.BoneName2 == Other.BoneName2;
191 });
192 }
193 }
194
195
196 if ((bPrim1Exists || bSkipPrim1) && (bPrim2Exists || bSkipPrim2))
197 {
198 break; // Exit early
199 }
200 }
201
202 if (!bPrim1Exists && !bSkipPrim1)
203 {
204 Pair.Key.Prim1->GetBodyInstance(BonePair.BoneName1)->SetContactModification(false);
205 }
206
207
208 if (!bPrim2Exists && !bSkipPrim2)
209 {
210 Pair.Key.Prim2->GetBodyInstance(BonePair.BoneName2)->SetContactModification(false);
211 }
212 }
213 }
214 }
215
216#endif
217 RemovedPairs.Reset();
218
219 if (CollisionTrackedPairs.Num() > 0)
220 {
221 if (!UpdateHandle.IsValid())
222 {
223 // Setup the heartbeat on 1htz checks
224 GetWorld()->GetTimerManager().SetTimer(UpdateHandle, this, &UCollisionIgnoreSubsystem::CheckActiveFilters, 1.0f, true, 1.0f);
225 }
226 }
227 else if (UpdateHandle.IsValid())
228 {
229 GetWorld()->GetTimerManager().ClearTimer(UpdateHandle);
230 }
231 }
232
233 UFUNCTION(Category = "Collision")
234 void CheckActiveFilters();
235
236 // #TODO implement this, though it should be rare
237 void InitiateIgnore();
238
239 void SetComponentCollisionIgnoreState(bool bIterateChildren1, bool bIterateChildren2, UPrimitiveComponent* Prim1, FName OptionalBoneName1, UPrimitiveComponent* Prim2, FName OptionalBoneName2, bool bIgnoreCollision, bool bCheckFilters = false);
240 void RemoveComponentCollisionIgnoreState(UPrimitiveComponent* Prim1);
241 bool IsComponentIgnoringCollision(UPrimitiveComponent* Prim1);
242 bool AreComponentsIgnoringCollisions(UPrimitiveComponent* Prim1, UPrimitiveComponent* Prim2);
243 bool HasCollisionIgnorePairs();
244private:
245
246 FTimerHandle UpdateHandle;
247
248};
DECLARE_LOG_CATEGORY_EXTERN(VRE_CollisionIgnoreLog, Log, All)
virtual void Deinitialize() override
void CheckActiveFilters()
UFUNCTION(Category = "Collision")
virtual bool DoesSupportWorldType(EWorldType::Type WorldType) const override
virtual void Initialize(FSubsystemCollectionBase &Collection) override
TMap< FCollisionPrimPair, FCollisionIgnorePairArray > CollisionTrackedPairs
UPROPERTY()
TMap< FCollisionPrimPair, FCollisionIgnorePairArray > RemovedPairs
UPROPERTY()
TArray< FCollisionIgnorePair > PairArray
UPROPERTY()
FORCEINLINE bool operator==(const FCollisionIgnorePair &Other) const
FORCEINLINE bool operator==(const FName &Other) const
FPhysicsActorHandle Actor1
FCollisionPrimPair PrimitivePair;.
friend uint32 GetTypeHash(const FCollisionPrimPair &InKey)
FORCEINLINE bool operator==(const FCollisionPrimPair &Other) const
TWeakObjectPtr< UPrimitiveComponent > Prim2
UPROPERTY()
TWeakObjectPtr< UPrimitiveComponent > Prim1
UPROPERTY()