Files
UnrealEngine/Engine/Source/Runtime/Experimental/Chaos/Private/EventManager.cpp
2025-05-18 13:04:45 +08:00

154 lines
3.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "EventManager.h"
namespace Chaos
{
namespace Private
{
// This is required to be able to track continuous collisions (so that we can detect the "no collision" state)
bool bEventManagerDispatchEmptyEvents = true;
FAutoConsoleVariableRef CVarEventManagerDispatchEmptyEvent(TEXT("p.Chaos.EventManager.DispatchEmptyEvents"), bEventManagerDispatchEmptyEvents, TEXT("Whether to dispatch events even if the event buffers are empty"));
}
void FEventManager::Reset()
{
ContainerLock.WriteLock();
for (FEventContainerBasePtr Container : EventContainers)
{
delete Container;
Container = nullptr;
}
EventContainers.Reset();
ContainerLock.WriteUnlock();
}
void FEventManager::UnregisterEvent(const EEventType& EventType)
{
const FEventID EventID = (FEventID)EventType;
ContainerLock.WriteLock();
if (EventID < EventContainers.Num())
{
delete EventContainers[EventID];
EventContainers.RemoveAt(EventID);
}
ContainerLock.WriteUnlock();
}
void FEventManager::UnregisterHandler(const EEventType& EventType, const void* InHandler)
{
const FEventID EventID = (FEventID)EventType;
ContainerLock.ReadLock();
checkf(EventID < EventContainers.Num(), TEXT("Unregistering event Handler for an event ID that does not exist"));
EventContainers[EventID]->UnregisterHandler(InHandler);
ContainerLock.ReadUnlock();
}
void FEventManager::FillProducerData(const Chaos::FPBDRigidsSolver* Solver, bool bResetData)
{
if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.ReadLock();
}
ContainerLock.ReadLock();
for (FEventContainerBasePtr EventContainer : EventContainers)
{
if (EventContainer)
{
EventContainer->InjectProducerData(Solver, bResetData);
}
}
ContainerLock.ReadUnlock();
if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.ReadUnlock();
}
}
void FEventManager::FlipBuffersIfRequired()
{
if (BufferMode == EMultiBufferMode::Single)
{
return;
}
else if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.WriteLock();
}
ContainerLock.ReadLock();
for (FEventContainerBasePtr EventContainer : EventContainers)
{
if (EventContainer)
{
EventContainer->ResetConsumerBuffer();
EventContainer->FlipBufferIfRequired();
}
}
ContainerLock.ReadUnlock();
if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.WriteUnlock();
}
}
void FEventManager::DispatchEvents()
{
if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.ReadLock();
}
ContainerLock.ReadLock();
for (FEventContainerBasePtr EventContainer : EventContainers)
{
if (EventContainer)
{
EventContainer->DispatchConsumerData();
}
}
ContainerLock.ReadUnlock();
if (BufferMode == EMultiBufferMode::Double)
{
ResourceLock.ReadUnlock();
}
else if (BufferMode == EMultiBufferMode::Single)
{
for (FEventContainerBasePtr EventContainer : EventContainers)
{
if (EventContainer)
{
EventContainer->ResetConsumerBuffer();
EventContainer->FlipBufferIfRequired();
}
}
}
}
void FEventManager::InternalRegisterInjector(const FEventID& EventID, const FEventContainerBasePtr& Container)
{
if (EventID > EventContainers.Num())
{
for (int i = EventContainers.Num(); i < EventID; i++)
{
EventContainers.Push(nullptr);
}
}
EventContainers.EmplaceAt(EventID, Container);
}
int32 FEventManager::EncodeCollisionIndex(int32 ActualCollisionIndex, bool bSwapOrder)
{
return bSwapOrder ? (ActualCollisionIndex | (1 << 31)) : ActualCollisionIndex;
}
int32 FEventManager::DecodeCollisionIndex(int32 EncodedCollisionIdx, bool& bSwapOrder)
{
bSwapOrder = EncodedCollisionIdx & (1 << 31);
return EncodedCollisionIdx & ~(1 << 31);
}
}