Files
UnrealEngine/Engine/Source/Runtime/MassEntity/Private/MassObserverRegistry.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

86 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MassObserverRegistry.h"
#include "Algo/Find.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(MassObserverRegistry)
//----------------------------------------------------------------------//
// UMassObserverRegistry
//----------------------------------------------------------------------//
UMassObserverRegistry::UMassObserverRegistry()
{
// there can be only one!
check(HasAnyFlags(RF_ClassDefaultObject));
if (!ModulesUnloadedHandle.IsValid())
{
ModulesUnloadedHandle = FCoreUObjectDelegates::CompiledInUObjectsRemovedDelegate.AddUObject(this, &UMassObserverRegistry::OnModulePackagesUnloaded);
}
}
void UMassObserverRegistry::RegisterObserver(TNotNull<const UScriptStruct*> ObservedType, const uint8 OperationFlags, TSubclassOf<UMassProcessor> ObserverClass)
{
check(ObserverClass);
const bool bIsFragment = UE::Mass::IsA<FMassFragment>(ObservedType);
checkSlow(bIsFragment || UE::Mass::IsA<FMassTag>(ObservedType));
FObserverClassesMap* ObserversMap = bIsFragment
? FragmentObserverMaps
: TagObserverMaps;
for (uint8 OperationIndex = 0; OperationIndex < static_cast<uint8>(EMassObservedOperation::MAX); ++OperationIndex)
{
if ((OperationFlags & (1 << OperationIndex)))
{
ObserversMap[OperationIndex].FindOrAdd(ObservedType).AddUnique(FSoftClassPath(ObserverClass));
}
}
}
void UMassObserverRegistry::RegisterObserver(const UScriptStruct& ObservedType, const EMassObservedOperation Operation, TSubclassOf<UMassProcessor> ObserverClass)
{
RegisterObserver(&ObservedType, static_cast<uint8>(1 << static_cast<uint8>(Operation)), ObserverClass);
}
void UMassObserverRegistry::OnModulePackagesUnloaded(TConstArrayView<UPackage*> Packages)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UMassObserverRegistry::OnModulePackagesUnloaded);
const auto ProcessObserversMap = [&Packages](FObserverClassesMap& ObserversMap)
{
for (auto MapIt = ObserversMap.CreateIterator(); MapIt; ++MapIt)
{
TArray<FSoftClassPath>& ObserverClasses = MapIt->Value;
for (auto ObserverIt = ObserverClasses.CreateIterator(); ObserverIt; ++ObserverIt)
{
const FSoftClassPath& ObservedClass = *ObserverIt;
const FName PackageName = ObservedClass.GetLongPackageFName();
bool bRemove = !!Algo::FindByPredicate(Packages, [PackageName](const UPackage* Package)
{
return PackageName == Package->GetFName();
});
if (bRemove)
{
UE_LOG(LogMass, Log, TEXT("%hs: removed observer %s (%s)"), __FUNCTION__, *ObservedClass.ToString(), *PackageName.ToString());
ObserverIt.RemoveCurrent();
}
}
if (ObserverClasses.Num() == 0)
{
MapIt.RemoveCurrent();
}
}
};
for (uint8 OperationIndex = 0; OperationIndex < static_cast<uint8>(EMassObservedOperation::MAX); ++OperationIndex)
{
ProcessObserversMap(FragmentObserverMaps[OperationIndex]);
ProcessObserversMap(TagObserverMaps[OperationIndex]);
}
}