10#include "Engine/World.h"
11#include "GeoReferencingSystem.h"
12#include "Kismet/GameplayStatics.h"
18 PrimaryActorTick.bCanEverTick =
false;
32 UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Instance already exists. Destroying this actor.."));
37 UWorld* World = GetWorld();
42 FString MapName = World->GetMapName().ToLower();
43 if (MapName.Contains(TEXT(
"vindeln_dev")) || MapName.Contains(TEXT(
"rovaniemiforest_dev")))
51 TArray<AActor*> Actors;
52 UGameplayStatics::GetAllActorsOfClass(World, AInstancedActor::StaticClass(), Actors);
54 for (AActor* Actor : Actors)
73 if (InstancedActor->CanAddToInstancedRenderer())
82 Super::EndPlay(EndPlayReason);
102 UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Actor is null!"));
110 UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s is set to update transform automatically."), *InstancedActor->GetName());
116 if (!StaticMeshComponent)
119 UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent is null!"), *InstancedActor->GetName());
124 UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
128 UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent mesh is null!"), *InstancedActor->GetName());
136 if (Renderer && Renderer->Matches(StaticMeshComponent, InstancedActor->
AlternativeMaterial))
138 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
141 Comp->AddInstance(InstancedActor->GetActorTransform());
143 InstancedActor->Destroy();
150 FTransform SpawnTransform = FTransform::Identity;
151 FActorSpawnParameters SpawnParams;
154 AInstancedActorRenderer::StaticClass(),
174 if (!Renderer || !Renderer->Matches(ISM))
179 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
185 const int32 InstanceCount = ISM->GetInstanceCount();
186 for (int32 i = 0; i < InstanceCount; ++i)
188 FTransform InstanceTransform;
189 if (ISM->GetInstanceTransform(i, InstanceTransform,
true))
191 Comp->AddInstance(InstanceTransform);
210 FTransform SpawnTransform = FTransform::Identity;
211 FActorSpawnParameters SpawnParams;
214 AInstancedActorRenderer::StaticClass(),
230 Comp->SetStaticMesh(ISM->GetStaticMesh());
231 const int32 NumberOfMaterials = ISM->GetNumMaterials();
232 for (int32 i = 0; i < NumberOfMaterials; i++)
234 Comp->SetMaterial(i, ISM->GetMaterial(i));
237 TArray<FTransform> InstanceTransforms;
238 for (int32 i = 0; i < ISM->GetInstanceCount(); i++)
240 FTransform InstanceTransform;
241 if (ISM->GetInstanceTransform(i, InstanceTransform,
true))
243 InstanceTransforms.Add(InstanceTransform);
247 for (
const FTransform&
Transform : InstanceTransforms)
274 UWorld* World = GetWorld();
275 if (World && !World->IsGameWorld())
277 TArray<AActor*> FoundActors;
278 UGameplayStatics::GetAllActorsOfClass(World, AInstancedActorRenderer::StaticClass(), FoundActors);
280 TArray<AInstancedActorRenderer*> RendererActors;
281 for (AActor* Actor : FoundActors)
285 RendererActors.AddUnique(Renderer);
288 return RendererActors;
302 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
305 total += Comp->GetInstanceCount();
319 if (Renderer && Renderer->SpawnInstanceBackToActor(ISM, Index, OnlyTree))
344 if (!params.
IsTree && OnlyTrees)
349 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
350 if (Comp && Comp == ISM)
352 TArray<int32> OverlappingInstances = Comp->GetInstancesOverlappingBox(AreaBox);
355 OverlappingInstances.Sort([](int32 A, int32 B)
360 for (int32 InstanceIndex : OverlappingInstances)
362 Comp->RemoveInstance(InstanceIndex);
374 UInstancedStaticMeshComponent* Comp = Renderer->GetInstancedStaticMeshComponent();
377 Comp->SetVisibility(Visible);
385 AGeoReferencingSystem* GeoReferencingSystem = AGeoReferencingSystem::GetGeoReferencingSystem(GetWorld());
386 TArray<TArray<FString>> Rows;
390 if (Renderer && Renderer->GetInstancedActorParameters().IsTree)
392 UInstancedStaticMeshComponent* ISM = Renderer->GetInstancedStaticMeshComponent();
395 const int32 InstanceCount = ISM->GetInstanceCount();
396 const FString MeshName = Renderer->GetStaticMesh() ? Renderer->GetStaticMesh()->GetName() : TEXT(
"Unknown");
398 for (int32 i = 0; i < InstanceCount; ++i)
401 if (!ISM->GetInstanceTransform(i,
Transform,
true))
continue;
403 const FVector Location =
Transform.GetLocation();
404 const FRotator Rotation =
Transform.Rotator();
406 FString LatitudeStr = TEXT(
""), LongitudeStr = TEXT(
""), AltitudeStr = TEXT(
"");
408 if (GeoReferencingSystem)
411 LatitudeStr = FString::Printf(TEXT(
"%.8f"), GeographicCoordinates.Latitude);
412 LongitudeStr = FString::Printf(TEXT(
"%.8f"), GeographicCoordinates.Longitude);
413 AltitudeStr = FString::Printf(TEXT(
"%.8f"), GeographicCoordinates.Altitude);
418 Row.Add(FString::Printf(TEXT(
"%.2f"), Location.X));
419 Row.Add(FString::Printf(TEXT(
"%.2f"), Location.Y));
420 Row.Add(FString::Printf(TEXT(
"%.2f"), Location.Z));
422 if (GeoReferencingSystem)
424 Row.Add(LatitudeStr);
425 Row.Add(LongitudeStr);
426 Row.Add(AltitudeStr);
447 FString MapName = GetWorld()->GetMapName();
448 FString FileName = MapName + TEXT(
"_TreeLocations");
454 TArray<FString> Header = { TEXT(
"name"), TEXT(
"x"), TEXT(
"y"), TEXT(
"z") };
455 if (GeoReferencingSystem)
457 Header.Append({ TEXT(
"latitude"), TEXT(
"longitude"), TEXT(
"altitude") });
462 for (
const TArray<FString>& Row : Rows)
void SetupFromInstancedActor(AInstancedActor *InstancedActor)
bool SpawnInstancesBackActors()
UInstancedStaticMeshComponent * GetInstancedStaticMeshComponent() const
bool UpdateTransformAutomatically() const
bool CanAddToInstancedRenderer()
UStaticMeshComponent * GetStaticMeshComponent() const
TArray< AInstancedActorRenderer * > InstancedRenderers
int32 GetTotalInstanceCount()
bool SpawnInstanceBackToActor(UInstancedStaticMeshComponent *ISM, int32 Index, bool OnlyTree)
void SetInstancedRendering(bool Visible)
void OnActorSpawned(AActor *Actor)
bool AppendOrCreateISM(UInstancedStaticMeshComponent *ISM)
FDelegateHandle ActorSpawnedDelegateHandle
bool AppendISM(UInstancedStaticMeshComponent *ISM)
TArray< AInstancedActorRenderer * > GetAllInstancedActorRendererActors() const
void DestroyOverlappingInstancesBox(UInstancedStaticMeshComponent *ISM, FBox AreaBox, bool OnlyTrees)
static AInstancedRendererManager * Instance
bool AddActorToInstancedRendering(AInstancedActor *InstancedActor)
virtual void BeginPlay() override
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
void SpawnAllInstancesBackToActors()
AInstancedRendererManager(const FObjectInitializer &ObjectInitializer)
static UCSVFile * CreateCSVFile(const FString &FileNameWithoutExtension, const FCSVFileSettings &Settings)
void WriteRow(const TArray< FString > &Cells)
static FGeographicCoordinates UnrealToGeographicCoordinates(AGeoReferencingSystem *GeoReferencingSystem, const FVector &Position)
FCSVFileWriteOptions FileWriteOption