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

120 lines
3.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MassSubsystemAccess.h"
namespace UE::Mass::Private
{
template<typename T>
TSubclassOf<T> ConvertToSubsystemClass(TSubclassOf<USubsystem> SubsystemClass)
{
return *(reinterpret_cast<TSubclassOf<T>*>(&SubsystemClass));
}
}
//-----------------------------------------------------------------------------
// FMassSubsystemAccess
//-----------------------------------------------------------------------------
FMassSubsystemAccess::FMassSubsystemAccess(UWorld* InWorld)
: World(InWorld)
{
Subsystems.AddZeroed(FMassExternalSubsystemBitSet::GetMaxNum());
}
USubsystem* FMassSubsystemAccess::FetchSubsystemInstance(UWorld* World, TSubclassOf<USubsystem> SubsystemClass)
{
QUICK_SCOPE_CYCLE_COUNTER(Mass_FetchSubsystemInstance);
check(SubsystemClass);
if (SubsystemClass->IsChildOf<UWorldSubsystem>())
{
return World
? World->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass<UWorldSubsystem>(SubsystemClass))
: nullptr;
}
if (SubsystemClass->IsChildOf<UEngineSubsystem>())
{
return GEngine->GetEngineSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass<UEngineSubsystem>(SubsystemClass));
}
if (SubsystemClass->IsChildOf<UGameInstanceSubsystem>())
{
return (World && World->GetGameInstance())
? World->GetGameInstance()->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass<UGameInstanceSubsystem>(SubsystemClass))
: nullptr;
}
if (SubsystemClass->IsChildOf<ULocalPlayerSubsystem>())
{
const ULocalPlayer* LocalPlayer = World ? World->GetFirstLocalPlayerFromController() : nullptr;
return LocalPlayer
? LocalPlayer->GetSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass<ULocalPlayerSubsystem>(SubsystemClass))
: nullptr;
}
#if WITH_EDITOR
if (SubsystemClass->IsChildOf<UEditorSubsystem>())
{
return GEditor->GetEditorSubsystemBase(UE::Mass::Private::ConvertToSubsystemClass<UEditorSubsystem>(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<USubsystem> SubsystemSubclass(const_cast<UClass*>(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();
}