// Copyright Epic Games, Inc. All Rights Reserved. #include "MassSubsystemAccess.h" namespace UE::Mass::Private { template TSubclassOf ConvertToSubsystemClass(TSubclassOf SubsystemClass) { return *(reinterpret_cast*>(&SubsystemClass)); } } //----------------------------------------------------------------------------- // FMassSubsystemAccess //----------------------------------------------------------------------------- FMassSubsystemAccess::FMassSubsystemAccess(UWorld* InWorld) : World(InWorld) { Subsystems.AddZeroed(FMassExternalSubsystemBitSet::GetMaxNum()); } USubsystem* FMassSubsystemAccess::FetchSubsystemInstance(UWorld* World, TSubclassOf SubsystemClass) { QUICK_SCOPE_CYCLE_COUNTER(Mass_FetchSubsystemInstance); check(SubsystemClass); if (SubsystemClass->IsChildOf()) { return World ? World->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass(SubsystemClass)) : nullptr; } if (SubsystemClass->IsChildOf()) { return GEngine->GetEngineSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass(SubsystemClass)); } if (SubsystemClass->IsChildOf()) { return (World && World->GetGameInstance()) ? World->GetGameInstance()->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass(SubsystemClass)) : nullptr; } if (SubsystemClass->IsChildOf()) { const ULocalPlayer* LocalPlayer = World ? World->GetFirstLocalPlayerFromController() : nullptr; return LocalPlayer ? LocalPlayer->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass(SubsystemClass)) : nullptr; } #if WITH_EDITOR if (SubsystemClass->IsChildOf()) { return GEditor->GetEditorSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass(SubsystemClass)); } #endif // WITH_EDITOR return nullptr; } bool FMassSubsystemAccess::CacheSubsystemRequirements(const FMassSubsystemRequirements& SubsystemRequirements) { bool bResult = true; if (SubsystemRequirements.IsEmpty() == false) { for (FMassExternalSubsystemBitSet::FIndexIterator It = SubsystemRequirements.GetRequiredConstSubsystems().GetIndexIterator(); It && bResult; ++It) { bResult = bResult && CacheSubsystem(*It); } for (FMassExternalSubsystemBitSet::FIndexIterator It = SubsystemRequirements.GetRequiredMutableSubsystems().GetIndexIterator(); It && bResult; ++It) { bResult = bResult && CacheSubsystem(*It); } } if (bResult) { ConstSubsystemsBitSet = SubsystemRequirements.GetRequiredConstSubsystems(); MutableSubsystemsBitSet = SubsystemRequirements.GetRequiredMutableSubsystems(); } return bResult; } bool FMassSubsystemAccess::CacheSubsystem(const uint32 SystemIndex) { if (UNLIKELY(Subsystems.IsValidIndex(SystemIndex) == false)) { Subsystems.AddZeroed(Subsystems.Num() - SystemIndex + 1); } if (Subsystems[SystemIndex]) { return true; } const UClass* SubsystemClass = FMassExternalSubsystemBitSet::GetTypeAtIndex(SystemIndex); checkSlow(SubsystemClass); TSubclassOf SubsystemSubclass(const_cast(SubsystemClass)); checkSlow(*SubsystemSubclass); if (SubsystemSubclass) { USubsystem* SystemInstance = FMassSubsystemAccess::FetchSubsystemInstance(World.Get(), SubsystemSubclass); Subsystems[SystemIndex] = SystemInstance; return SystemInstance != nullptr; } return false; } void FMassSubsystemAccess::SetSubsystemRequirements(const FMassSubsystemRequirements& SubsystemRequirements) { ConstSubsystemsBitSet = SubsystemRequirements.GetRequiredConstSubsystems(); MutableSubsystemsBitSet = SubsystemRequirements.GetRequiredMutableSubsystems(); }