UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
EventManager.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
9#include "Misc/ScopeLock.h"
10#include "Chaos/Defines.h"
12#include "Misc/ScopeRWLock.h"
13
14namespace Chaos
15{
16 namespace Private
17 {
19 }
20
21 //#todo : need to enable disable events, or not register them if disabled.
22 //#todo : add timers
23 //#todo : warning if trying to add same event ID twice
24 //#todo : need sparse array for EventID -> EventContainer?
25
29 enum class EEventType : int32
30 {
31 Collision = 0,
32 Breaking = 1,
33 Trailing = 2,
34 Sleeping = 3,
35 Removal = 4,
36 Crumbling = 5,
37 };
38
39 typedef int32 FEventID;
40
41
46 {
47 template<typename PayloadType>
48 friend class TEventContainer;
49
50 public:
51 virtual ~IEventHandler() {}
52 virtual void HandleEvent(const void* EventData) const = 0;
54 virtual void* GetHandler() const = 0;
55 };
56
58 template<typename PayloadType, typename HandlerType>
60 {
61 public:
62 typedef void (HandlerType::*FHandlerFunction)(const PayloadType&);
64
66 : Handler(InHandler)
67 , HandlerFunction(InFunction)
68 , InterestedProxyOwnersFunction(InFunctionProxyOwners)
69 {
70 check(Handler);
71 check(HandlerFunction);
72 // This can be a nullptr
73 //check(InterestedProxyOwnersFunction);
74 }
75
76 virtual void HandleEvent(const void* EventData) const override
77 {
78 (Handler->*HandlerFunction)(*(const PayloadType*)EventData);
79 }
80
81 virtual bool GetInterestedProxyOwners(TArray<UObject*>& Output) const override
82 {
83 if (!InterestedProxyOwnersFunction)
84 {
85 return false;
86 }
87
88 Output = (Handler->*InterestedProxyOwnersFunction)();
89 return true;
90 }
91
92 void* GetHandler() const override
93 {
94 return Handler;
95 }
96
97 private:
98 HandlerType* Handler;
99 FHandlerFunction HandlerFunction;
100 // This function is used to get the proxies we are interested in, used for optimization
101 // Will be a nullptr if the handler is interested in all proxies
102 FInterestedProxyOwnerFunction InterestedProxyOwnersFunction;
103 };
104
109
114 {
115 public:
120 virtual void RegisterHandler(const FEventHandlerPtr& Handler) = 0;
121
125 virtual void UnregisterHandler(const void* Handler) = 0;
126
127 /*
128 * Inject data from the physics solver into the producer side of the buffer
129 */
130 virtual void InjectProducerData(const FPBDRigidsSolver* Solver, bool bResetData) = 0;
131
135 virtual void FlipBufferIfRequired() = 0;
136
140 virtual void ResetConsumerBuffer() = 0;
141
145 virtual void DispatchConsumerData() = 0;
146 };
147
151 template<typename PayloadType>
153 {
154 public:
158 TEventContainer(const Chaos::EMultiBufferMode& BufferMode, TFunction<void(const FPBDRigidsSolver* Solver, PayloadType& EventDataInOut, bool bResetData)> InFunction)
159 : InjectedFunction(InFunction)
160 , EventBuffer(Chaos::FMultiBufferFactory<PayloadType>::CreateBuffer(BufferMode))
161 {
162 }
163
168 {
169 InjectedFunction = Other.InjectedFunction;
170 EventBuffer = MoveTemp(Other.EventBuffer);
171 bDispatchInProgress = Other.bDispatchInProgress;
172 }
173
178 {
179 UE::TWriteScopeLock ScopeLock(HandlerLock);
180
181 for (TPair<void*, FEventHandlerPtr>& Pair : HandlerMap)
182 {
183 delete Pair.Value;
184 Pair.Value = nullptr;
185 }
186 }
187#
191 virtual void RegisterHandler(const FEventHandlerPtr& Handler)
192 {
194
195 if(bDispatchInProgress)
196 {
197 UE::TWriteScopeLock ScopeLock(DeferredHandlerLock);
198 DeferredHandlers.AddUnique(Handler);
199
200 return;
201 }
202
204
205 HandlerMap.Add(Handler->GetHandler(), Handler);
208
210 {
212 {
213 ProxyOwnerToHandlerMap.Add(ProxyOwner, Handler);
214 }
215 }
216 else
217 {
218 if(GetProxyToIndexMap(EventBuffer.Get()->GetConsumerBuffer()) != nullptr) // Only if our type supports getting the ProxyToIndexMap do we bother adding this
219 {
220 HandlersNotInProxyOwnerMap.Add(Handler->GetHandler(), Handler);
221 }
222 }
223 }
224
228 virtual void UnregisterHandler(const void* InHandler)
229 {
231
232 if(bDispatchInProgress)
233 {
234 UE::TWriteScopeLock ScopeLock(DeferredHandlerLock);
235 DeferredUnregisterHandlers.AddUnique(InHandler);
236
237 return;
238 }
239
240 UE::TWriteScopeLock ScopeLock(HandlerLock);
241
243 for(const TPair<UObject*, FEventHandlerPtr>& KeyValue : ProxyOwnerToHandlerMap)
244 {
245 const FEventHandlerPtr Value = KeyValue.Value;
246 if(Value && Value->GetHandler() == InHandler)
247 {
249 }
250 }
251
253 {
254 ProxyOwnerToHandlerMap.Remove(KeyAndValue.Get<0>(), KeyAndValue.Get<1>());
255 }
256
257 HandlersNotInProxyOwnerMap.Remove(InHandler);
258
259 if(FEventHandlerPtr* HandlerPtr = HandlerMap.Find(InHandler))
260 {
261 DeleteHandler(*HandlerPtr);
262 HandlerMap.Remove(InHandler);
263 }
264 }
265
266 /*
267 * Inject data from the physics solver into the producer side of the buffer
268 */
269 virtual void InjectProducerData(const FPBDRigidsSolver* Solver, bool bResetData)
270 {
271 InjectedFunction(Solver, *EventBuffer->AccessProducerBuffer(), bResetData);
272 }
273
274
275 virtual void DestroyStaleEvents(TFunction<void(PayloadType & EventDataInOut)> InFunction)
276 {
277 InFunction(*EventBuffer->AccessProducerBuffer());
278 }
279
280 virtual void AddEvent(TFunction<void(PayloadType& EventDataInOut)> InFunction)
281 {
282 InFunction(*EventBuffer->AccessProducerBuffer());
283 }
284
288 virtual void FlipBufferIfRequired()
289 {
290 EventBuffer->FlipProducer();
291 }
292
296 virtual void ResetConsumerBuffer()
297 {
298 EventBuffer->GetConsumerBufferMutable()->Reset();
299 }
300
304 virtual void DispatchConsumerData()
305 {
307
308 const PayloadType* Buffer = EventBuffer.Get()->GetConsumerBuffer();
309
310 // We dispatch events even when the event buffers are empty because the absence
311 // of collisions/breaks/etc is required information for some use-cases like
312 // tracking continuous collisions.
315 {
316 return;
317 }
318
319 // Unregister any handlers that should no longer be invoked
320 UnregisterDeferedHandler();
321
322 {
323 // We're going to iterate the handlers and invoke them, read lock the list to block any changes
324 UE::TReadScopeLock ScopeLock(HandlerLock);
325
326 // Dispatch process beginning, we can no longer modify the handlers until the dispatch
327 // completes, register and unregister will defer while this guard is set
328 TGuardValue<bool> ReentrancyGuard(bDispatchInProgress, true);
329
330 const TMap<IPhysicsProxyBase*, TArray<int32>>* Map = GetProxyToIndexMap(Buffer); // Use t his map to get all proxies used in the event buffer
331 // Only take this path if we have fewer Events than Handlers
332 if(Map && Map->Num() + HandlersNotInProxyOwnerMap.Num() < HandlerMap.Num())
333 {
334 if(!ProxyOwnerToHandlerMap.IsEmpty())
335 {
337 UniqueHandlers.Reserve(Map->Num());
338 for(auto& KeyValue : *Map) // Only iterating over objects that are associated with events here
339 {
340 const IPhysicsProxyBase* Proxy = KeyValue.Get<0>();
341 const UObject* Owner = Proxy->GetOwner();
342 for(TMultiMap<UObject*, FEventHandlerPtr>::TConstKeyIterator It = ProxyOwnerToHandlerMap.CreateConstKeyIterator(Owner); It; ++It)
343 {
344 UniqueHandlers.Add(It.Value());
345 }
346 }
347
348 for(const FEventHandlerPtr Handler : UniqueHandlers)
349 {
350 Handler->HandleEvent(Buffer);
351 }
352 }
353
354 for(const TPair<void*, FEventHandlerPtr>& Pair : HandlersNotInProxyOwnerMap)
355 {
356 Pair.Value->HandleEvent(Buffer);
357 }
358 }
359 else
360 // This path is taken if there are fewer Handlers than events or the handler does not support GetProxyToIndexMap
361 {
362 for(const TPair<void*, FEventHandlerPtr>& Pair : HandlerMap)
363 {
364 Pair.Value->HandleEvent(Buffer);
365 }
366 }
367 }
368
369 // Register any new handlers enqueued during the dispatch process
370 RegisterDeferedHandler();
371 }
372
373private:
374
375 void UnregisterDeferedHandler()
376 {
378
379 {
380 UE::TWriteScopeLock ScopeLock(DeferredHandlerLock);
381
382 DeferredRequests = MoveTemp(DeferredUnregisterHandlers);
383 check(DeferredUnregisterHandlers.Num() == 0);
384 }
385
386 for (const void* HandlerPtr : DeferredRequests)
387 {
389 }
390 }
391
392 void RegisterDeferedHandler()
393 {
395
396 {
397 UE::TWriteScopeLock ScopeLock(DeferredHandlerLock);
398
399 DeferredRequests = MoveTemp(DeferredHandlers);
400 check(DeferredHandlers.Num() == 0);
401 }
402
404 {
406 }
407 }
408
409 void DeleteHandler(FEventHandlerPtr& HandlerPtr)
410 {
411 delete HandlerPtr;
412 HandlerPtr = nullptr;
413 }
414
418 TFunction<void(const FPBDRigidsSolver* Solver, PayloadType& EventData, bool bResetData)> InjectedFunction;
419
424
425 TMultiMap<UObject*, FEventHandlerPtr> ProxyOwnerToHandlerMap; // Used to prevent us from iterating through the whole HandlerMap
426 TMap<void*, FEventHandlerPtr> HandlersNotInProxyOwnerMap; // Handlers not added to ProxyOwnerToHandlerMap since they do not support it
427
432
433 FTransactionallySafeRWLock HandlerLock; // protect access ProxyOwnerToHandlerMap, HandlersNotInProxyOwnerMap, HandlerMap
434 TArray<FEventHandlerPtr> DeferredHandlers; // Store handler to register, they couldn't registered to avoid reentrant lock
435 TArray<const void*> DeferredUnregisterHandlers; // Store handler to unregister, they couldn't unregistered to avoid reentrant lock
436 FTransactionallySafeRWLock DeferredHandlerLock; // protect access to DeferredHandlers and DeferredUnregisterHandlers
437
439 bool bDispatchInProgress = false;
440 };
441
446
448 {
449 friend class FPBDRigidsSolver;
450
451 public:
452
456
458 {
459 Reset();
460 }
461
465 CHAOS_API void Reset();
466
471 {
472 BufferMode = BufferModeIn;
473 }
474
478 template<typename PayloadType>
479 void RegisterEvent(const EEventType& EventType, TFunction<void(const Chaos::FPBDRigidsSolver* Solver, PayloadType& EventData, bool bResetData)> InFunction)
480 {
481 ContainerLock.WriteLock();
482 InternalRegisterInjector(FEventID(EventType), new TEventContainer<PayloadType>(BufferMode, InFunction));
483 ContainerLock.WriteUnlock();
484 }
485
489 template<typename PayloadType>
490 void ClearEvents(const EEventType& EventType, TFunction<void(PayloadType & EventData)> InFunction)
491 {
492 ContainerLock.WriteLock();
493
495 {
496 EventContainer->DestroyStaleEvents(InFunction);
497 }
498 ContainerLock.WriteUnlock();
499 }
500
504 CHAOS_API void UnregisterEvent(const EEventType& EventType);
505
509 template<typename PayloadType, typename HandlerType>
511 {
512 const FEventID EventID = FEventID(EventType);
513 ContainerLock.ReadLock();
514 checkf(EventID < EventContainers.Num(), TEXT("Registering event Handler for an event ID that does not exist"));
515 EventContainers[EventID]->RegisterHandler(new TRawEventHandler<PayloadType, HandlerType>(Handler, HandlerFunction, InterestedProxyOwnerFunction));
516 ContainerLock.ReadUnlock();
517 }
518
522 CHAOS_API void UnregisterHandler(const EEventType& EventType, const void* InHandler);
523
527 CHAOS_API void FillProducerData(const Chaos::FPBDRigidsSolver* Solver, bool bResetData = true);
528
533
538
543
544
545 template<typename PayloadType>
546 void AddEvent(const EEventType& EventType, TFunction<void(PayloadType& EventData)> InFunction)
547 {
548 if (BufferMode == EMultiBufferMode::Double)
549 {
550 ResourceLock.ReadLock();
551 }
552 ContainerLock.ReadLock();
554 {
555 EventContainer->AddEvent(InFunction);
556 }
557 ContainerLock.ReadUnlock();
558 if (BufferMode == EMultiBufferMode::Double)
559 {
560 ResourceLock.ReadUnlock();
561 }
562 }
563
564 private:
565
566 CHAOS_API void InternalRegisterInjector(const FEventID& EventID, const FEventContainerBasePtr& Container);
567
568 Chaos::EMultiBufferMode BufferMode; // specifies the buffer type to be constructed, single, double, triple
569 TArray<FEventContainerBasePtr> EventContainers; // Array of event types
570 FTransactionallySafeRWLock ResourceLock;
571 FTransactionallySafeRWLock ContainerLock;
572 };
573
574}
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ SLT_Write
Definition ScopeRWLock.h:139
CORE_API bool IsInGameThread()
Definition ThreadingBase.cpp:185
UE_REWRITE T StaticCast(ArgType &&Arg)
Definition UnrealTemplate.h:638
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition EventManager.h:114
virtual void DispatchConsumerData()=0
virtual void InjectProducerData(const FPBDRigidsSolver *Solver, bool bResetData)=0
virtual ~FEventContainerBase()
Definition EventManager.h:116
virtual void ResetConsumerBuffer()=0
virtual void RegisterHandler(const FEventHandlerPtr &Handler)=0
virtual void FlipBufferIfRequired()=0
virtual void UnregisterHandler(const void *Handler)=0
Definition EventManager.h:448
CHAOS_API void UnregisterHandler(const EEventType &EventType, const void *InHandler)
Definition EventManager.cpp:38
FEventManager(const Chaos::EMultiBufferMode &BufferModeIn)
Definition EventManager.h:453
CHAOS_API void DispatchEvents()
Definition EventManager.cpp:96
static CHAOS_API int32 DecodeCollisionIndex(int32 EncodedCollisionIdx, bool &bSwapOrder)
Definition EventManager.cpp:148
CHAOS_API void UnregisterEvent(const EEventType &EventType)
Definition EventManager.cpp:26
void SetBufferMode(const Chaos::EMultiBufferMode &BufferModeIn)
Definition EventManager.h:470
~FEventManager()
Definition EventManager.h:457
CHAOS_API void FillProducerData(const Chaos::FPBDRigidsSolver *Solver, bool bResetData=true)
Definition EventManager.cpp:47
void RegisterEvent(const EEventType &EventType, TFunction< void(const Chaos::FPBDRigidsSolver *Solver, PayloadType &EventData, bool bResetData)> InFunction)
Definition EventManager.h:479
void AddEvent(const EEventType &EventType, TFunction< void(PayloadType &EventData)> InFunction)
Definition EventManager.h:546
CHAOS_API void Reset()
Definition EventManager.cpp:14
void RegisterHandler(const EEventType &EventType, HandlerType *Handler, typename TRawEventHandler< PayloadType, HandlerType >::FHandlerFunction HandlerFunction, typename TRawEventHandler< PayloadType, HandlerType >::FInterestedProxyOwnerFunction InterestedProxyOwnerFunction=nullptr)
Definition EventManager.h:510
void ClearEvents(const EEventType &EventType, TFunction< void(PayloadType &EventData)> InFunction)
Definition EventManager.h:490
static CHAOS_API int32 EncodeCollisionIndex(int32 ActualCollisionIndex, bool bSwapOrder)
Definition EventManager.cpp:143
CHAOS_API void FlipBuffersIfRequired()
Definition EventManager.cpp:68
Definition MultiBufferResource.h:309
Definition PBDRigidsSolver.h:84
Definition EventManager.h:46
virtual ~IEventHandler()
Definition EventManager.h:51
virtual void HandleEvent(const void *EventData) const =0
virtual void * GetHandler() const =0
virtual bool GetInterestedProxyOwners(TArray< UObject * > &Output) const =0
Definition EventManager.h:153
virtual void RegisterHandler(const FEventHandlerPtr &Handler)
Definition EventManager.h:191
virtual void DispatchConsumerData()
Definition EventManager.h:304
virtual void InjectProducerData(const FPBDRigidsSolver *Solver, bool bResetData)
Definition EventManager.h:269
virtual void AddEvent(TFunction< void(PayloadType &EventDataInOut)> InFunction)
Definition EventManager.h:280
TEventContainer(TEventContainer< PayloadType > &Other)
Definition EventManager.h:167
~TEventContainer()
Definition EventManager.h:177
virtual void FlipBufferIfRequired()
Definition EventManager.h:288
virtual void ResetConsumerBuffer()
Definition EventManager.h:296
virtual void UnregisterHandler(const void *InHandler)
Definition EventManager.h:228
TEventContainer(const Chaos::EMultiBufferMode &BufferMode, TFunction< void(const FPBDRigidsSolver *Solver, PayloadType &EventDataInOut, bool bResetData)> InFunction)
Definition EventManager.h:158
virtual void DestroyStaleEvents(TFunction< void(PayloadType &EventDataInOut)> InFunction)
Definition EventManager.h:275
Definition EventManager.h:60
virtual void HandleEvent(const void *EventData) const override
Definition EventManager.h:76
virtual bool GetInterestedProxyOwners(TArray< UObject * > &Output) const override
Definition EventManager.h:81
void * GetHandler() const override
Definition EventManager.h:92
TRawEventHandler(HandlerType *InHandler, FHandlerFunction InFunction, FInterestedProxyOwnerFunction InFunctionProxyOwners=nullptr)
Definition EventManager.h:65
void(HandlerType::* FHandlerFunction)(const PayloadType &)
Definition EventManager.h:62
TArray< UObject * >(HandlerType::* FInterestedProxyOwnerFunction)()
Definition EventManager.h:63
Definition PhysicsProxyBase.h:97
UObject * GetOwner() const
Definition PhysicsProxyBase.h:107
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_FORCEINLINE_HINT SizeType AddUnique(ElementType &&Item)
Definition Array.h:2993
Definition AndroidPlatformMisc.h:14
Definition UnrealString.h.inl:34
Definition UniquePtr.h:107
Definition CriticalSection.h:14
UE_REWRITE void WriteLock()
Definition CriticalSection.h:21
UE_REWRITE void ReadUnlock()
Definition CriticalSection.h:41
UE_REWRITE void WriteUnlock()
Definition CriticalSection.h:26
UE_REWRITE void ReadLock()
Definition CriticalSection.h:36
Definition ScopeRWLock.h:154
Definition ScopeRWLock.h:21
Definition ScopeRWLock.h:60
Definition Object.h:95
bool bEventManagerDispatchEmptyEvents
Definition EventManager.cpp:10
Definition SkeletalMeshComponent.h:307
EMultiBufferMode
Definition MultiBufferResource.h:9
EEventType
Definition EventManager.h:30
bool IsEventDataEmpty(const PayloadType *Buffer)
Definition EventsData.h:235
IEventHandler * FEventHandlerPtr
Definition EventManager.h:108
int32 FEventID
Definition EventManager.h:39
const TMap< IPhysicsProxyBase *, TArray< int32 > > * GetProxyToIndexMap(const PayloadType *Buffer)
Definition EventsData.h:273
Definition OverriddenPropertySet.cpp:45
Definition Pair.h:8
Definition UnrealTemplate.h:341
Definition Tuple.h:652