Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Abstract Instances and FGBuildable #268

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public AbstractInstance(ReadOnlyTargetRules Target) : base(Target)
// ... add other public dependencies that you statically link with here ...
}
);


PrivateDependencyModuleNames.AddRange(
new string[]
Expand All @@ -44,6 +43,10 @@ public AbstractInstance(ReadOnlyTargetRules Target) : base(Target)
}
);

if (Target.bBuildEditor)
{
PrivateDependencyModuleNames.Add("UnrealEd");
}

DynamicallyLoadedModuleNames.AddRange(
new string[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

#include "AbstractInstance.h"

#if AI_PIE
#include "AbstractInstanceManager.h"
#include "Editor.h"
#endif

#define LOCTEXT_NAMESPACE "FAbstractInstanceModule"

void FAbstractInstanceModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
#if AI_PIE
FEditorDelegates::BeginPIE.AddStatic(&AAbstractInstanceManager::BeginPIE);
FEditorDelegates::PostPIEStarted.AddStatic(&AAbstractInstanceManager::PostPIEStarted);
FWorldDelegates::OnWorldCleanup.AddStatic(&AAbstractInstanceManager::OnWorldCleanup);
#endif
}

void FAbstractInstanceModule::ShutdownModule()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#include "Engine/World.h"
#include "GameFramework/PlayerController.h"

#if AI_PIE
#include "EngineUtils.h"
#include "Editor.h"
#endif

static TAutoConsoleVariable<int32> CVarAllowLazySpawning(
TEXT("lightweightinstances.AllowLazySpawn"),
0,
Expand Down Expand Up @@ -57,7 +62,8 @@ constexpr int32 NumCollisionInstances = 500;
#if !AI_PIE
AAbstractInstanceManager* AAbstractInstanceManager::StaticManager = nullptr;
#else
TMap<UWorld*,AAbstractInstanceManager*> AAbstractInstanceManager::StaticManager_PIE;
TMap<TObjectPtr<UWorld>, TObjectPtr<AAbstractInstanceManager>> AAbstractInstanceManager::StaticManager_PIE;
static FRWLock StaticRWLock;
#endif

// Sets default values
Expand All @@ -68,29 +74,90 @@ AAbstractInstanceManager::AAbstractInstanceManager()

RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
RootComponent->SetMobility( EComponentMobility::Static );

if (!this->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) {
this->SetFlags(RF_Transient | RF_NonPIEDuplicateTransient);
}
}

/* FIXME(Th3): this terribleness feels like paranoia, is it even needed? */
void AAbstractInstanceManager::Destroyed()
{
Super::Destroyed();
#if AI_PIE
const UWorld* World = GetWorld();
EditorCheck(World);
FRWScopeLock Lock(StaticRWLock, FRWScopeLockType::SLT_Write);
if (StaticManager_PIE.Contains(World) && StaticManager_PIE[World] == this) {
StaticManager_PIE.Remove(World);
}
#endif
}

#if AI_PIE
void AAbstractInstanceManager::OnWorldCleanup(UWorld* World, bool bSessionEnded, bool bCleanupResources)
{
StaticManager_PIE.Remove(World);
}

static AAbstractInstanceManager* GetEditorInstanceManager()
{
UWorld* EditorWorld = GetValid(GEditor->EditorWorld);
if (!EditorWorld) {
EditorWorld = GetValid(GWorld.GetReference());
}
return EditorWorld ? AAbstractInstanceManager::GetInstanceManager(EditorWorld) : nullptr;
}

void AAbstractInstanceManager::PostPIEStarted(bool bIsSimulating)
{
if (AAbstractInstanceManager* Manager = GetEditorInstanceManager()) {
Manager->SetFlags(RF_Transient | RF_NonPIEDuplicateTransient);
}
}

void AAbstractInstanceManager::BeginPIE(bool bIsSimulating)
{
if (AAbstractInstanceManager* Manager = GetEditorInstanceManager()) {
Manager->ClearFlags(RF_Transient | RF_NonPIEDuplicateTransient);
}
}

static AAbstractInstanceManager* GetExistingInstanceManager(UWorld* World)
{
for (TActorIterator<AAbstractInstanceManager> It(World, AAbstractInstanceManager::StaticClass(), EActorIteratorFlags::AllActors); It; ++It) {
return *It;
}
return nullptr;
}
#endif

AAbstractInstanceManager* AAbstractInstanceManager::GetInstanceManager( UObject* WorldContext )
{
UWorld* World = WorldContext->GetWorld();
#if !AI_PIE
if(!AAbstractInstanceManager::StaticManager)
{
AAbstractInstanceManager::StaticManager = WorldContext->GetWorld()->SpawnActor< AAbstractInstanceManager >();
if (IsValid(AAbstractInstanceManager::StaticManager)) {
return AAbstractInstanceManager::StaticManager;
}

AAbstractInstanceManager::StaticManager = World->SpawnActor<AAbstractInstanceManager>();
return AAbstractInstanceManager::StaticManager;
#else
if (StaticManager_PIE.Contains(WorldContext->GetWorld()))
{
return StaticManager_PIE[WorldContext->GetWorld()];
/* FIXME(Th3): why do we maintain a map if we're iterating over actors anyway */
if (AAbstractInstanceManager* ExistingManager = GetExistingInstanceManager(World)) {
return ExistingManager;
}
else
{
auto NewManager = WorldContext->GetWorld()->SpawnActor< AAbstractInstanceManager >();
StaticManager_PIE.Add(WorldContext->GetWorld(),NewManager);

FRWScopeLock Lock(StaticRWLock, FRWScopeLockType::SLT_Write);
if (StaticManager_PIE.Contains(World)) {
if (IsValid(StaticManager_PIE[World])) {
return StaticManager_PIE[World];
}
StaticManager_PIE.Remove(World);
}
if (AAbstractInstanceManager* NewManager = World->SpawnActor<AAbstractInstanceManager>()) {
StaticManager_PIE.Add(World, NewManager);
return NewManager;
}
return nullptr;
#endif
}

Expand All @@ -100,6 +167,7 @@ AAbstractInstanceManager* AAbstractInstanceManager::GetInstanceManager()
return AAbstractInstanceManager::StaticManager;
#else
// TODO implement.
EditorCheck(false);
return nullptr;
#endif
}
Expand Down Expand Up @@ -592,7 +660,12 @@ void AAbstractInstanceManager::EndPlay( const EEndPlayReason::Type EndPlayReason
#if !AI_PIE
AAbstractInstanceManager::StaticManager = nullptr;
#else
AAbstractInstanceManager::StaticManager_PIE.Empty();
FRWScopeLock Lock(StaticRWLock, FRWScopeLockType::SLT_Write);
const UWorld* World = GetWorld();
EditorCheck(World);
if (StaticManager_PIE.Contains(World) && StaticManager_PIE[World] == this) {
StaticManager_PIE.Remove(World);
}
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class ABSTRACTINSTANCE_API AAbstractInstanceManager : public AActor
static AAbstractInstanceManager* GetInstanceManager( UObject* WorldContext );
static AAbstractInstanceManager* GetInstanceManager();

virtual void Destroyed() override;

virtual void Tick(float DeltaSeconds) override;

static void SetInstancedStatic( AActor* OwnerActor, const FTransform& ActorTransform, const UAbstractInstanceDataObject* InstanceData, TArray<FInstanceHandle*>& OutHandle, bool bInitializeHidden = false );
Expand Down Expand Up @@ -170,9 +172,15 @@ class ABSTRACTINSTANCE_API AAbstractInstanceManager : public AActor
#if !AI_PIE
static AAbstractInstanceManager* StaticManager;
#else // PIE support
static TMap<UWorld*,AAbstractInstanceManager*> StaticManager_PIE;
static TMap<TObjectPtr<UWorld>, TObjectPtr<AAbstractInstanceManager>> StaticManager_PIE;
#endif

static FName BuildUniqueName( const FInstanceData& InstanceData );
static FName BuildUniqueName( const UInstancedStaticMeshComponent* MeshComponent );
public:
#if AI_PIE
static void OnWorldCleanup(UWorld* World, bool bSessionEnded, bool bCleanupResources);
static void BeginPIE(bool bIsSimulating);
static void PostPIEStarted(bool bIsSimulating);
#endif
};
35 changes: 23 additions & 12 deletions Source/FactoryGame/Private/Buildables/FGBuildable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "Net/UnrealNetwork.h"
#include "AbstractInstanceManager.h"

DEFINE_LOG_CATEGORY(LogBuilding);

#if WITH_EDITOR
void AFGBuildable::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) {
Super::PostEditChangeProperty(PropertyChangedEvent);
Expand Down Expand Up @@ -44,25 +46,33 @@ TArray<struct FInstanceData> AFGBuildable::GetActorLightweightInstanceData_Imple
return TArray<FInstanceData>();
}
void AFGBuildable::SetupInstances_Native(bool bInitializeHidden) {
if (this && GetWorld() && IsValid(mInstanceDataCDO)) {
if (GetWorld() && IsValid(mInstanceDataCDO)) {
for (FInstanceData InstanceData : mInstanceDataCDO->GetInstanceData()) {
if (IsValid(InstanceData.StaticMesh) && !InstanceData.OverridenMaterials.Contains(nullptr)) {
FInstanceHandle* Handle;
AAbstractInstanceManager::SetInstanceFromDataStatic(this, FTransform(), InstanceData, Handle, bInitializeHidden);
mInstanceHandles.Add(Handle);
FInstanceHandle* Handle = nullptr;
AAbstractInstanceManager::SetInstanceFromDataStatic(this, this->GetActorTransform(), InstanceData, Handle, bInitializeHidden);
if (Handle && Handle->IsValid()) {
mInstanceHandles.Add(Handle);
} else {
UE_LOG(LogBuilding, Warning, TEXT("[Th3] Invalid Handle for %s mesh %s at %s"),
*this->GetPathName(),
InstanceData.StaticMesh ? *InstanceData.StaticMesh->GetName() : TEXT("nullptr"),
*InstanceData.RelativeTransform.ToString());
}
}
}
}
}
void AFGBuildable::RemoveInstances_Native() {
if (this && GetWorld()) {
AAbstractInstanceManager* Manager = AAbstractInstanceManager::GetInstanceManager(GetWorld());
for (FInstanceHandle* InstanceHandle : mInstanceHandles) {
if (InstanceHandle->IsInstanced()) {
Manager->RemoveInstance(InstanceHandle);
}
}
mInstanceHandles.Empty();
if (UWorld* World = GetWorld()) {
if (AAbstractInstanceManager* Manager = AAbstractInstanceManager::GetInstanceManager(World)) {
for (FInstanceHandle* InstanceHandle : mInstanceHandles) {
if (InstanceHandle->IsInstanced()) {
Manager->RemoveInstance(InstanceHandle);
}
}
}
mInstanceHandles.Empty();
}
}

Expand Down Expand Up @@ -165,6 +175,7 @@ AFGBuildable::AFGBuildable(const FObjectInitializer& ObjectInitializer) : Super(
this->NetDormancy = ENetDormancy::DORM_Initial;
this->NetCullDistanceSquared = 5625000000.0;
this->RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
this->RootComponent->SetMobility(EComponentMobility::Static);
}
void AFGBuildable::Serialize(FArchive& ar){ Super::Serialize(ar); }
void AFGBuildable::PostLoad(){ Super::PostLoad(); }
Expand Down
Loading