// 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 ObservedType, const uint8 OperationFlags, TSubclassOf ObserverClass) { check(ObserverClass); const bool bIsFragment = UE::Mass::IsA(ObservedType); checkSlow(bIsFragment || UE::Mass::IsA(ObservedType)); FObserverClassesMap* ObserversMap = bIsFragment ? FragmentObserverMaps : TagObserverMaps; for (uint8 OperationIndex = 0; OperationIndex < static_cast(EMassObservedOperation::MAX); ++OperationIndex) { if ((OperationFlags & (1 << OperationIndex))) { ObserversMap[OperationIndex].FindOrAdd(ObservedType).AddUnique(FSoftClassPath(ObserverClass)); } } } void UMassObserverRegistry::RegisterObserver(const UScriptStruct& ObservedType, const EMassObservedOperation Operation, TSubclassOf ObserverClass) { RegisterObserver(&ObservedType, static_cast(1 << static_cast(Operation)), ObserverClass); } void UMassObserverRegistry::OnModulePackagesUnloaded(TConstArrayView Packages) { TRACE_CPUPROFILER_EVENT_SCOPE(UMassObserverRegistry::OnModulePackagesUnloaded); const auto ProcessObserversMap = [&Packages](FObserverClassesMap& ObserversMap) { for (auto MapIt = ObserversMap.CreateIterator(); MapIt; ++MapIt) { TArray& 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(EMassObservedOperation::MAX); ++OperationIndex) { ProcessObserversMap(FragmentObserverMaps[OperationIndex]); ProcessObserversMap(TagObserverMaps[OperationIndex]); } }