RealtimeStyleTransferRuntime/Source/LyraGame/UI/Weapons/LyraReticleWidgetBase.cpp

92 lines
3.0 KiB
C++
Raw Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraReticleWidgetBase.h"
#include "Weapons/LyraWeaponInstance.h"
#include "Weapons/LyraRangedWeaponInstance.h"
#include "Inventory/LyraInventoryItemInstance.h"
ULyraReticleWidgetBase::ULyraReticleWidgetBase(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void ULyraReticleWidgetBase::InitializeFromWeapon(ULyraWeaponInstance* InWeapon)
{
WeaponInstance = InWeapon;
InventoryInstance = nullptr;
if (WeaponInstance)
{
InventoryInstance = Cast<ULyraInventoryItemInstance>(WeaponInstance->GetInstigator());
}
OnWeaponInitialized();
}
float ULyraReticleWidgetBase::ComputeSpreadAngle() const
{
if (const ULyraRangedWeaponInstance* RangedWeapon = Cast<const ULyraRangedWeaponInstance>(WeaponInstance))
{
const float BaseSpreadAngle = RangedWeapon->GetCalculatedSpreadAngle();
const float SpreadAngleMultiplier = RangedWeapon->GetCalculatedSpreadAngleMultiplier();
const float ActualSpreadAngle = BaseSpreadAngle * SpreadAngleMultiplier;
return ActualSpreadAngle;
}
else
{
return 0.0f;
}
}
bool ULyraReticleWidgetBase::HasFirstShotAccuracy() const
{
if (const ULyraRangedWeaponInstance* RangedWeapon = Cast<const ULyraRangedWeaponInstance>(WeaponInstance))
{
return RangedWeapon->HasFirstShotAccuracy();
}
else
{
return false;
}
}
float ULyraReticleWidgetBase::ComputeMaxScreenspaceSpreadRadius() const
{
const float LongShotDistance = 10000.f;
APlayerController* PC = GetOwningPlayer();
if (PC && PC->PlayerCameraManager)
{
// A weapon's spread can be thought of as a cone shape. To find the screenspace spread for reticle visualization,
// we create a line on the edge of the cone at a long distance. The end of that point is on the edge of the cone's circle.
// We then project it back onto the screen. Its distance from screen center is the spread radius.
// This isn't perfect, due to there being some distance between the camera location and the gun muzzle.
const float SpreadRadiusRads = FMath::DegreesToRadians(ComputeSpreadAngle() * 0.5f);
const float SpreadRadiusAtDistance = FMath::Tan(SpreadRadiusRads) * LongShotDistance;
FVector CamPos;
FRotator CamOrient;
PC->PlayerCameraManager->GetCameraViewPoint(CamPos, CamOrient);
FVector CamForwDir = CamOrient.RotateVector(FVector::ForwardVector);
FVector CamUpDir = CamOrient.RotateVector(FVector::UpVector);
FVector OffsetTargetAtDistance = CamPos + (CamForwDir * LongShotDistance) + (CamUpDir * SpreadRadiusAtDistance);
FVector2D OffsetTargetInScreenspace;
if (PC->ProjectWorldLocationToScreen(OffsetTargetAtDistance, OffsetTargetInScreenspace, true))
{
int32 ViewportSizeX(0), ViewportSizeY(0);
PC->GetViewportSize(ViewportSizeX, ViewportSizeY);
const FVector2D ScreenSpaceCenter(FVector::FReal(ViewportSizeX) * 0.5f, FVector::FReal(ViewportSizeY) * 0.5f);
return (OffsetTargetInScreenspace - ScreenSpaceCenter).Length();
}
}
return 0.0f;
}