13#include "Components/StaticMeshComponent.h" 
   14#include "UObject/ConstructorHelpers.h" 
   15#include "Kismet/GameplayStatics.h" 
   16#include "Materials/Material.h" 
   17#include "TimerManager.h" 
   18#include "Engine/World.h" 
   23    : Super(ObjectInitializer)
 
   25    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT(
"SceneRoot"));
 
   26    RootComponent->SetMobility(EComponentMobility::Static);
 
   27    PrimaryActorTick.bCanEverTick = 
false;
 
   30    static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMesh(TEXT(
"/Engine/BasicShapes/Cube.Cube"));
 
   31    if (DefaultMesh.Succeeded())
 
   50        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Instance already exists. Destroying this actor.."));
 
   55    UWorld* World = GetWorld();
 
   73    World->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([
this] {
 
   94    Super::EndPlay(EndPlayReason);
 
  105    UWorld* World = GetWorld();
 
  122        if (Entry.InstancedStaticMeshComponent)
 
  124            Entry.InstancedStaticMeshComponent->ClearInstances();
 
  125            Entry.InstancedStaticMeshComponent->UnregisterComponent();
 
  126            Entry.InstancedStaticMeshComponent->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
 
  127            Entry.InstancedStaticMeshComponent->DestroyComponent();
 
  128            Entry.InstancedStaticMeshComponent = 
nullptr;
 
  131        Entry.Materials.Empty();
 
  143        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Actor is null!"));
 
  151        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s is set to update transform automatically."), *InstancedActor->GetName());
 
  157    if (!StaticMeshComponent)
 
  160        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent is null!"), *InstancedActor->GetName());
 
  165    UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
 
  169        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: AInstancedActor %s UStaticMeshComponent mesh is null!"), *InstancedActor->GetName());
 
  174    int32 ComponentIndex = 9999;
 
  182        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: ComponentIndex is not valid!"));
 
  187    UInstancedStaticMeshComponent* InstancedStaticMeshComponent = 
InstanceEntries[ComponentIndex].InstancedStaticMeshComponent;
 
  188    if (!InstancedStaticMeshComponent)
 
  191        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: UInstancedStaticMeshComponent is nullptr!"));
 
  197    FTransform ActorTransform = StaticMeshComponent->GetComponentTransform();
 
  198    InstancedStaticMeshComponent->AddInstance(ActorTransform);
 
  200    int32 InstanceIndex = InstancedStaticMeshComponent->GetNumRenderInstances() - 1;
 
  203    InstancedActor->
InstanceAdded(ComponentIndex, InstanceIndex);
 
  213    if (InstancedActor == 
nullptr || StaticMeshComponent == 
nullptr)
 
  216        UE_LOG(LogTemp, Warning, TEXT(
"StaticInstancedRenderer.cpp: StaticMeshComponent or InstancedActor is null!"));
 
  221    UStaticMesh* Mesh = StaticMeshComponent->GetStaticMesh();
 
  226        for (int32 Index = 0; Index < Num; ++Index)
 
  236    const int32 NumberOfMaterials = StaticMeshComponent->GetNumMaterials();
 
  238    TArray<UMaterialInterface*> MeshMaterials;
 
  239    MeshMaterials.Reserve(NumberOfMaterials);
 
  241    for (int32 i = 0; i < NumberOfMaterials; i++)
 
  243        MeshMaterials.Add(StaticMeshComponent->GetMaterial(i));
 
  247    for (int32 Index = 0; Index < Size; ++Index)
 
  251            bool bMaterialsMatch = 
true;
 
  253            for (int32 MaterialIndex = 0; MaterialIndex < 
InstanceEntries[Index].Materials.Num(); ++MaterialIndex)
 
  255                UMaterialInterface* UniqueMeshMaterial = 
InstanceEntries[Index].Materials[MaterialIndex];
 
  256                UMaterialInterface* MeshMaterial = MeshMaterials[MaterialIndex];
 
  257                if (UniqueMeshMaterial != MeshMaterial)
 
  259                    bMaterialsMatch = 
false;
 
  275    UInstancedStaticMeshComponent* InstancedStaticMeshComponent = NewObject<UInstancedStaticMeshComponent>(
this);
 
  277    UClass* ClassPtr = InstancedActor->GetClass();
 
  279    FString Name = IInteractable::Execute_GetInteractableName(InstancedActor).ToString();
 
  283        Name = ClassPtr->GetAuthoredName();
 
  284        if (Name.EndsWith(TEXT(
"_C")))
 
  286            Name = Name.LeftChop(2);
 
  288        if (Name.StartsWith(TEXT(
"BP_")))
 
  290            Name = Name.RightChop(3);
 
  292        Name.ReplaceInline(TEXT(
"_"), TEXT(
" "));
 
  293        Name.ReplaceInline(TEXT(
"Instanced"), TEXT(
" "));
 
  297    FString Guid = FGuid::NewGuid().ToString().Left(4);
 
  299    Name = FString::Printf(TEXT(
"%s(_%s_)"), *Name, *Guid);
 
  301    InstancedStaticMeshComponent->Rename(*Name);
 
  304    InstancedStaticMeshComponent->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
 
  305    AddInstanceComponent(InstancedStaticMeshComponent);
 
  307    InstancedStaticMeshComponent->bEditableWhenInherited = 
false;
 
  308    InstancedStaticMeshComponent->RegisterComponent();
 
  309    InstancedStaticMeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
 
  310    InstancedStaticMeshComponent->CreatePhysicsState(
false);
 
  311    InstancedStaticMeshComponent->SetSimulatePhysics(
false);
 
  312    InstancedStaticMeshComponent->SetStaticMesh(Mesh);
 
  313    InstancedStaticMeshComponent->SetMobility(EComponentMobility::Static);
 
  314    InstancedStaticMeshComponent->SetHiddenInGame(
false);
 
  315    InstancedStaticMeshComponent->SetVisibility(
true);
 
  316    InstancedStaticMeshComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform);
 
  329    GetWorld()->GetTimerManager().SetTimer(Handle, FTimerDelegate::CreateLambda([
this, InstancedStaticMeshComponent, AllowWorldPositionOffsetDisable] {
 
  332            InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(false);
 
  333            InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(false);
 
  342    InstancedStaticMeshComponent->SetRenderCustomDepth(
true);
 
  343    InstancedStaticMeshComponent->SetCustomDepthStencilValue(StaticMeshComponent->CustomDepthStencilValue);
 
  347    InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = EShadowCacheInvalidationBehavior::Rigid;
 
  353    InstanceEntry.
Mesh = Mesh;
 
  361    const int32 MaterialCount = MeshMaterials.Num();
 
  362    for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex)
 
  364        UMaterialInterface* MaterialInterface = InstanceEntry.
Materials[MaterialIndex];
 
  366        if (MaterialInterface)
 
  368            InstancedStaticMeshComponent->SetMaterial(MaterialIndex, MaterialInterface);
 
  372            UMaterial* Material = Cast<UMaterial>(MaterialInterface);
 
  375                if (!Material->bUsedWithInstancedStaticMeshes)
 
  377                    UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Material '%s' bUsedWithInstancedStaticMeshes is not set to true!"), *Material->GetName());
 
  418        if (InstanceNumber >= 0 && InstanceNumber < Entry.InstancedStaticMeshComponent->GetInstanceCount())
 
  431        if (Entry.InstancedStaticMeshComponent)
 
  433            Entry.InstancedStaticMeshComponent->SetVisibility(
Rendering);
 
  438    UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Rendering: %s"), (
Rendering ? TEXT(
"true") : TEXT(
"false")));
 
  447        UE_LOG(LogTemp, Warning, TEXT(
"InstancedRenderer.cpp: Index %d is not valid!"), Index);
 
  472    bool ShouldRenderWPO = IsWinter || IsWindy;
 
  486        if (Entry.InstancedStaticMeshComponent)
 
  488            Entry.InstancedStaticMeshComponent->SetRenderCustomDepth(Enabled);
 
  504        if (Entry.InstancedStaticMeshComponent)
 
  515        if (Entry.InstancedStaticMeshComponent)
 
  517            Entry.InstancedStaticMeshComponent->ShadowCacheInvalidationBehavior = ShadowCacheInvalidationBehaviour;
 
  526        if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
 
  528            Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffset(RenderWPO);
 
  529            Entry.InstancedStaticMeshComponent->SetEvaluateWorldPositionOffsetInRayTracing(RenderWPO);
 
  536    UMaterialInterface* DefaultMaterial = 
nullptr;
 
  537    if (SetUnrealDefaultMaterial)
 
  539        DefaultMaterial = UMaterial::GetDefaultMaterial(EMaterialDomain(0));
 
  544        if (Entry.AllowWorldPositionOffsetDisable && Entry.InstancedStaticMeshComponent)
 
  546            if (SetUnrealDefaultMaterial)
 
  548                for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
 
  550                    UMaterialInterface* CurrentMaterial = Entry.InstancedStaticMeshComponent->GetMaterial(i);
 
  551                    Entry.Materials.Add(CurrentMaterial);
 
  553                for (int32 i = 0; i < Entry.InstancedStaticMeshComponent->GetNumMaterials(); ++i)
 
  555                    Entry.InstancedStaticMeshComponent->SetMaterial(i, DefaultMaterial);
 
  560                if (Entry.Materials.Num() > 0)
 
  562                    for (int32 i = 0; i < Entry.Materials.Num(); ++i)
 
  564                        UMaterialInterface* OriginalMaterial = Entry.Materials[i];
 
  565                        Entry.InstancedStaticMeshComponent->SetMaterial(i, OriginalMaterial);
 
  578        auto& ISMComponent = Entry.InstancedStaticMeshComponent;
 
  582            if (!Entry.UsingProxy)
 
  584                ISMComponent->SetStaticMesh(
CubeMesh.Get());
 
  585                Entry.UsingProxy = 
true;
 
  589                ISMComponent->SetStaticMesh(Entry.Mesh.Get());
 
  590                Entry.UsingProxy = 
false;
 
  599    UWorld* World = GetWorld();
 
  608        UInstancedStaticMeshComponent* ISMComponent = Entry.InstancedStaticMeshComponent;
 
  614        ISMComponent->SetVisibility(
false);
 
  617        TArray<FTransform> Transforms;
 
  619        const int32 InstanceCount = ISMComponent->GetInstanceCount();
 
  621        for (int32 i = 0; i < InstanceCount; i++)
 
  624            ISMComponent->GetInstanceTransform(i, 
Transform);
 
  629        UClass* Class = Entry.ActorClass;
 
  630        for (
const FTransform& 
Transform : Transforms)
 
  632            AActor* SpawnedActor = World->SpawnActorDeferred<AActor>(Class, 
Transform);
 
  639        ISMComponent->DestroyComponent();
 
  648    UWorld* World = GetWorld();
 
  657        UInstancedStaticMeshComponent* ISMComponent = Entry.InstancedStaticMeshComponent;
 
  663        UClass* Class = Entry.ActorClass;
 
  665        AActor* SpawnedActor = World->SpawnActorDeferred<AActor>(Class, 
Transform);
 
  677            ISMComponent->SetCullDistances(Min, Max);
 
  687    if (!ISM || Index < 0 || Index >= ISM->GetInstanceCount())
 
  692    UWorld* World = GetWorld();
 
  695    FTransform InstanceTransform;
 
  696    ISM->GetInstanceTransform(Index, InstanceTransform);
 
  703    if (!Entry || !World)
 
  708    if (OnlyTree && !Entry->
IsTree)
 
  720    AActor* SpawnedActor = World->SpawnActorDeferred<AActor>(ActorClass, InstanceTransform);
 
  729        SpawnedActor->FinishSpawning(InstanceTransform);
 
  732        return ISM->RemoveInstance(Index);
 
  745    if (!Entry || (!Entry->
IsTree && OnlyTrees))
 
  753        TArray<int32> OverlappingInstances = Comp->GetInstancesOverlappingBox(AreaBox);
 
  754        for (int32 InstanceIndex : OverlappingInstances)
 
  756            Comp->RemoveInstance(InstanceIndex);
 
int32 GetInstanceEndCullDistance() const
bool UpdateTransformAutomatically() const
bool AddToInstancedRenderer
void InstanceAdded(int32 CompIndex, int32 InstanceNum)
bool HasAlternativeMaterial() const
int32 GetInstanceStartCullDistance() const
UStaticMeshComponent * GetStaticMeshComponent() const
bool GetAllowWorldPositionOffsetDisable() const
bool AddActorToInstancedRendering(AInstancedActor *InstancedActor)
void RemoveInstance(int32 ComponentIndex, int32 InstanceNumber)
bool FindOrAddUniqueMesh(UStaticMeshComponent *StaticMeshComponent, AInstancedActor *InstancedActor, int32 &InstanceNum)
void OnWeatherParametersChanged(FWeatherParameters WeatherParameters)
void SpawnAllInstancesBackActors()
void SetShadowCacheBehaviour(EShadowCacheInvalidationBehavior ShadowCacheInvalidationBehaviour)
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
void UpdateInstanceTransform(int32 ComponentIndex, int32 InstanceNumber, const FTransform &NewTransform)
void SetInstancedRendering(bool ShouldRender)
virtual void BeginPlay() override
void OnGraphicsSettingsChanged(FGlobalGraphicsSettings GraphicsSettings)
bool SpawnInstanceBackToActor(UInstancedStaticMeshComponent *ISM, int32 Index, bool OnlyTree)
void UpdateRenderDistances()
TArray< FInstanceEntry > InstanceEntries
void SetWorldPositionOffsetDistance(int32 NewWPODistance)
void SetRenderWorldPositionOffet(bool RenderWPO)
FWeatherParameters CurrentWeatherParameters
TWeakObjectPtr< UStaticMesh > CubeMesh
int32 WorldPositionOffsetDistance
void DestroyOverlappingInstancesBox(UInstancedStaticMeshComponent *ISM, FBox AreaBox, bool OnlyTrees)
void SetRenderCustomDepth(bool Enabled)
AInstancedRenderer(const FObjectInitializer &ObjectInitializer)
void DebugMaterialImpact(bool SetUnrealDefaultMaterial)
void SetComponentIndexVisibility(int32 Index, bool Visible)
static AInstancedRenderer * Instance
const FWeatherParameters & GetCurrentWeather() const
FLevelEventDelegate_WeatherChanged OnWeatherChanged
int32 GetWorldPositionOffsetRenderDistance() const
FGraphicsSettingsDelegate OnGraphicsSettingsChanged
static UAgrarsenseSettings * GetAgrarsenseSettings()
static AWeather * GetWeatherActor(const UObject *WorldContextObject)
int32 WorldPositionOffsetDistance
EShadowCacheInvalidationBehavior FoliageShadowCacheInvalidationBehaviour
TWeakObjectPtr< UStaticMesh > Mesh
TArray< UMaterialInterface * > Materials
int32 CustomDepthStencilValue
bool AllowWorldPositionOffsetDisable
TSubclassOf< AActor > ActorClass
UInstancedStaticMeshComponent * InstancedStaticMeshComponent