Agrarsense
DeletionVolume.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
6#include "DeletionVolume.h"
7
12
13#include "Engine/OverlapResult.h"
14#include "Components/PrimitiveComponent.h"
15#include "Components/InstancedStaticMeshComponent.h"
16#include "Kismet/GameplayStatics.h"
17#include "Engine/World.h"
18
20{
21 PrimaryActorTick.bCanEverTick = false;
22
23 CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
24 CollisionBox->InitBoxExtent(FVector(200.0f, 200.0f, 200.0f));
25 CollisionBox->SetGenerateOverlapEvents(true);
26 RootComponent = CollisionBox;
27
28#if WITH_EDITOR
29 VisualizerComponent = CreateDefaultSubobject<UBoundsVisualizerComponent>(TEXT("BoundsVisualizerComponent"));
30 VisualizerComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
31 VisualizerComponent->SetGenerateOverlapEvents(false);
32 VisualizerComponent->SetupAttachment(RootComponent);
33 VisualizerComponent->SetVisibility(true);
34#endif
35}
36
38{
39 Super::BeginPlay();
40
42 {
43 VisualizerComponent->SetCubeMesh();
44 VisualizerComponent->SetVisibility(true);
45 }
46}
47
48void ADeletionVolume::EndPlay(const EEndPlayReason::Type EndPlayReason)
49{
50 Super::EndPlay(EndPlayReason);
51
52 if (CollisionBox)
53 {
54 CollisionBox->DestroyComponent();
55 CollisionBox = nullptr;
56 }
57
59 {
60 VisualizerComponent->DestroyComponent();
61 VisualizerComponent = nullptr;
62 }
63}
64
66{
67 if (IsValid(this))
68 {
69 if (CollisionBox)
70 {
71 CollisionBox->SetBoxExtent(Bounds);
72 }
73
75 {
76 VisualizerComponent->SetRelativeScale3D(Bounds);
77 }
78 }
79}
80
82{
83 if (!IsValid(this) || !CollisionBox)
84 {
85 return;
86 }
87
88 FVector BoxCenter = CollisionBox->GetComponentLocation();
89 FVector BoxExtent = CollisionBox->GetScaledBoxExtent();
90
91 TArray<FOverlapResult> Overlaps;
92
93 bool HasOverlaps = GetWorld()->OverlapMultiByChannel(
94 Overlaps,
95 BoxCenter,
96 FQuat::Identity,
97 ECC_WorldDynamic,
98 FCollisionShape::MakeBox(BoxExtent),
99 FCollisionQueryParams(NAME_None, false, this)
100 );
101
102 if (!HasOverlaps)
103 {
104 SimulatorLog::Log("No overlaps detected.");
105 Destroy();
106 return;
107 }
108
110
111 for (const FOverlapResult& Overlap : Overlaps)
112 {
113 if (UPrimitiveComponent* Component = Overlap.GetComponent())
114 {
115 UInstancedStaticMeshComponent* InstancedMesh = Cast<UInstancedStaticMeshComponent>(Component);
116 if (InstancedMesh && Renderer)
117 {
118 // If this overlapped InstancedStaticMeshComponent,
119 // remove overlapping instances through InstancedRenderer
120 FBox Box = FBox(BoxCenter - BoxExtent, BoxCenter + BoxExtent);
121 Renderer->DestroyOverlappingInstancesBox(InstancedMesh, Box, OnlyTrees);
122 }
123 else
124 {
125 if (AActor* Actor = Component->GetOwner())
126 {
127 if (AInstancedActor* InstancedActor = Cast<AInstancedActor>(Actor))
128 {
129 bool CanDelete = !OnlyTrees || (OnlyTrees && InstancedActor->IsTreeActor());
130 if (CanDelete)
131 {
132 InstancedActor->Destroy();
133 }
134 }
135 }
136 }
137 }
138 }
139
140 // Destroy this actor after deleting overlapping actors inside the bounds.
141 Destroy();
142}
void DestroyOverlappingActors(bool OnlyTrees)
UBoxComponent * CollisionBox
UBoundsVisualizerComponent * VisualizerComponent
void ChangeOverlapBounds(FVector Bounds)
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
virtual void BeginPlay() override
void DestroyOverlappingInstancesBox(UInstancedStaticMeshComponent *ISM, FBox AreaBox, bool OnlyTrees)
static void Log(const FString &Message, bool LogToTextFile=true, bool LogToROS=true)
static AInstancedRenderer * GetInstancedRenderer(const UObject *WorldContextObject)