235 lines
6.6 KiB
C++
235 lines
6.6 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "VisionConeComponent.h"
|
|
|
|
#include "Kismet/KismetSystemLibrary.h"
|
|
#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h"
|
|
#include "ProjectT/System/Core/Interfaces/AISettings.h"
|
|
#include "ProjectT/System/Core/Managers/CoreCheatManager.h"
|
|
|
|
UVisionConeComponent::UVisionConeComponent(const FObjectInitializer& ObjectInitializer) :
|
|
Super(ObjectInitializer),
|
|
bDebugIsEnabled(false),
|
|
bUpdateEveryFrame(true),
|
|
SightRange(500.f),
|
|
SightAngle(90.f),
|
|
TriangleCount(10),
|
|
VisionRangeTraceChannel(ECC_GameTraceChannel2), // NOTE : Vision
|
|
TraceStartLocation(FVector::ZeroVector),
|
|
VisionMaterial(nullptr),
|
|
VisionParamName(TEXT("BaseColor")),
|
|
VisionGaugeName(TEXT("Amount")),
|
|
VisionRangeName(TEXT("MaxRange")),
|
|
DefaultColor(FLinearColor(0.f, 1.f, 0.f, 0.3f)),
|
|
HitColor(FLinearColor(1.f, 0.f, 0.f, 0.3f)),
|
|
MeshOffset(50.f),
|
|
bAllowDraw(false),
|
|
bDrawing(false),
|
|
bUpdatedOnce(false)
|
|
{
|
|
PrimaryComponentTick.bCanEverTick = true;
|
|
PrimaryComponentTick.bStartWithTickEnabled = false;
|
|
BodyInstance.SetCollisionProfileName(TEXT("NoCollision"));
|
|
BodyInstance.SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
SetCanEverAffectNavigation(false);
|
|
}
|
|
|
|
void UVisionConeComponent::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
if(IsValid(VisionMaterial))
|
|
{
|
|
VisionDynamicMaterial = CreateAndSetMaterialInstanceDynamicFromMaterial(0, VisionMaterial);
|
|
}
|
|
|
|
InitializeMeshGeometry();
|
|
VisionRangeTypeQuery = UEngineTypes::ConvertToTraceType(VisionRangeTraceChannel);
|
|
bDrawing ? SetComponentTickEnabled(true) : SetComponentTickEnabled(false);
|
|
|
|
VisionDynamicMaterial->SetScalarParameterValue(VisionRangeName, SightRange);
|
|
}
|
|
|
|
void UVisionConeComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
{
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
void UVisionConeComponent::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
InitializeMeshGeometry();
|
|
}
|
|
#endif
|
|
|
|
void UVisionConeComponent::InitializeMeshGeometry()
|
|
{
|
|
DivideAngleSize = SightAngle / TriangleCount;
|
|
|
|
MeshGeometryData.VertexCount = TriangleCount + 2;
|
|
MeshGeometryData.Vertices.SetNum(MeshGeometryData.VertexCount);
|
|
MeshGeometryData.Vertices[0] = -FVector(0, 0, MeshOffset);
|
|
|
|
MeshGeometryData.IndexCount = (MeshGeometryData.VertexCount - 2) * 3;
|
|
MeshGeometryData.Indices.SetNum(MeshGeometryData.IndexCount);
|
|
|
|
for(int32 Index = 0; Index < MeshGeometryData.Vertices.Num() - 1; ++Index)
|
|
{
|
|
if(Index < MeshGeometryData.VertexCount - 2)
|
|
{
|
|
MeshGeometryData.Indices[Index * 3 + 2] = 0;
|
|
MeshGeometryData.Indices[Index * 3 + 1] = Index + 1;
|
|
MeshGeometryData.Indices[Index * 3] = Index + 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UVisionConeComponent::DrawLineOfSight(const FRotator& InViewRotation)
|
|
{
|
|
TArray<FVector> ViewPoints;
|
|
|
|
for(int32 Index = 0; Index < TriangleCount + 1; ++Index)
|
|
{
|
|
float Angle = InViewRotation.Yaw - (SightAngle / 2.0f) + (DivideAngleSize * Index);
|
|
FSightTraceInfo SightTraceInfo = GetSightTraceInfo(Angle);
|
|
ViewPoints.Add(SightTraceInfo.Point);
|
|
}
|
|
|
|
if(PrevViewPoints.Num() == ViewPoints.Num() && PrevViewPoints == ViewPoints)
|
|
return;
|
|
|
|
for(int32 Index = 0; Index < ViewPoints.Num(); ++Index)
|
|
{
|
|
MeshGeometryData.Vertices[Index + 1] = GetComponentTransform().InverseTransformPosition(ViewPoints[Index] - FVector(0, 0, MeshOffset));
|
|
}
|
|
|
|
if(GetProcMeshSection(0) == nullptr)
|
|
{
|
|
CreateMeshSection_LinearColor(0, MeshGeometryData.Vertices, MeshGeometryData.Indices, MeshGeometryData.Normals, MeshGeometryData.UV, MeshGeometryData.VertexColors, MeshGeometryData.Tangents, false);
|
|
}
|
|
else
|
|
{
|
|
UpdateMeshSection_LinearColor(0, MeshGeometryData.Vertices, MeshGeometryData.Normals, MeshGeometryData.UV, MeshGeometryData.VertexColors, MeshGeometryData.Tangents);
|
|
}
|
|
|
|
PrevViewPoints = ViewPoints;
|
|
}
|
|
|
|
void UVisionConeComponent::UpdateMaterialState(const FLinearColor& InColor)
|
|
{
|
|
// if (!NMT_ENSURE(VisionDynamicMaterial))
|
|
// return;
|
|
|
|
if(VisionDynamicMaterial == nullptr)
|
|
return;
|
|
|
|
if(CurrentColor == InColor)
|
|
return;
|
|
|
|
VisionDynamicMaterial->SetVectorParameterValue(VisionParamName, InColor);
|
|
CurrentColor = InColor;
|
|
}
|
|
|
|
FSightTraceInfo UVisionConeComponent::GetSightTraceInfo(float InAngle) const
|
|
{
|
|
FHitResult OutHit;
|
|
FVector Dir = FRotator(0.f, InAngle, 0.f).Vector();
|
|
FVector Start;
|
|
GetOwner()->GetClass()->ImplementsInterface(UAISettings::StaticClass()) ? Start = IAISettings::Execute_GetViewTransform(GetOwner()).GetLocation() : Start = GetComponentLocation();
|
|
|
|
FVector End = (Dir * SightRange) + Start;
|
|
|
|
#if WITH_EDITOR
|
|
EDrawDebugTrace::Type DrawDebugType = bDebugIsEnabled ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
|
|
TArray<AActor*> ActorsToIgnore;
|
|
|
|
if(UKismetSystemLibrary::LineTraceSingle(this, Start, End, VisionRangeTypeQuery, false, ActorsToIgnore, DrawDebugType, OutHit, true))
|
|
{
|
|
return FSightTraceInfo(OutHit.Location, OutHit.Distance, InAngle);
|
|
}
|
|
#else
|
|
if (GetWorld()->LineTraceSingleByChannel(OutHit, Start, End, VisionRangeTraceChannel))
|
|
{
|
|
return FSightTraceInfo(OutHit.Location, OutHit.Distance, InAngle);
|
|
}
|
|
#endif
|
|
|
|
|
|
return FSightTraceInfo(OutHit.TraceEnd, SightRange, InAngle);
|
|
}
|
|
|
|
void UVisionConeComponent::SetupSightSettings(const float InSightRange, const float InSightAngle)
|
|
{
|
|
SightRange = InSightRange;
|
|
SightAngle = InSightAngle;
|
|
}
|
|
|
|
void UVisionConeComponent::UpdateVisionColor(const bool InbHit)
|
|
{
|
|
InbHit ? UpdateMaterialState(HitColor) : UpdateMaterialState(DefaultColor);
|
|
}
|
|
|
|
void UVisionConeComponent::UpdateVision(const FRotator& InViewRotation)
|
|
{
|
|
if(bUpdateEveryFrame)
|
|
{
|
|
DrawLineOfSight(InViewRotation);
|
|
}
|
|
else
|
|
{
|
|
if(!bUpdatedOnce)
|
|
{
|
|
DrawLineOfSight(InViewRotation);
|
|
bUpdatedOnce = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UVisionConeComponent::UpdateVisionGauge(const float InGauge) const
|
|
{
|
|
VisionDynamicMaterial->SetScalarParameterValue(VisionGaugeName, InGauge);
|
|
}
|
|
|
|
void UVisionConeComponent::ToggleDraw(const bool InbDraw)
|
|
{
|
|
UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this);
|
|
bool bDraw = InbDraw | CCM->GetDebugStatus().bDebugVision;
|
|
if(IsMeshSectionVisible(0) != bDraw)
|
|
{
|
|
if(bDraw)
|
|
{
|
|
bAllowDraw = true;
|
|
SetMeshSectionVisible(0, true);
|
|
SetComponentTickEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
bAllowDraw = false;
|
|
SetMeshSectionVisible(0, false);
|
|
SetComponentTickEnabled(false);
|
|
}
|
|
|
|
bDrawing = bDraw;
|
|
}
|
|
}
|
|
|
|
bool UVisionConeComponent::IsAllowedDrawing() const
|
|
{
|
|
return bAllowDraw;
|
|
}
|
|
|
|
void UVisionConeComponent::EnableVision()
|
|
{
|
|
SetComponentTickEnabled(true);
|
|
SetMeshSectionVisible(0, true);
|
|
}
|
|
|
|
void UVisionConeComponent::DisableVision()
|
|
{
|
|
SetMeshSectionVisible(0, false);
|
|
SetComponentTickEnabled(false);
|
|
}
|