Skip to content
Snippets Groups Projects
Commit d5954d5a authored by David Gilbert's avatar David Gilbert :bug:
Browse files

Merge branch 'IntenSelect5.3' into 'dev/5.3'

parents ec58d5eb 8c628451
No related branches found
No related tags found
No related merge requests found
Showing
with 798 additions and 0 deletions
File added
No preview for this file type
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
File added
No preview for this file type
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectable.h"
#include "Interaction/Interactables/IntenSelect/IntenSelectableScoring.h"
#include "Interaction/Interactables/IntenSelect/IntenSelectableSinglePointScoring.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Misc/MessageDialog.h"
#include "Pawn/IntenSelectComponent.h"
UIntenSelectable::UIntenSelectable() { PrimaryComponentTick.bCanEverTick = true; }
TPair<FHitResult, float> UIntenSelectable::GetBestPointScorePair(const FVector& ConeOrigin,
const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance,
const float ConeAngle, const float LastValue,
const float DeltaTime) const
{
checkf(ScoringBehaviour, TEXT("%s"), *GetOwner()->GetName()) return ScoringBehaviour->GetBestPointScorePair(
ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, LastValue, DeltaTime);
}
void UIntenSelectable::HandleOnSelectStartEvents(const UIntenSelectComponent* IntenSelect, const FHitResult& HitResult)
{
for (const UHoverBehaviour* b : OnSelectBehaviours)
{
b->OnHoverStartEvent.Broadcast(IntenSelect, HitResult);
}
}
void UIntenSelectable::HandleOnSelectEndEvents(const UIntenSelectComponent* IntenSelect)
{
for (const UHoverBehaviour* b : OnSelectBehaviours)
{
b->OnHoverEndEvent.Broadcast(IntenSelect);
}
}
void UIntenSelectable::HandleOnClickStartEvents(UIntenSelectComponent* IntenSelect)
{
for (const UActionBehaviour* b : OnClickBehaviours)
{
FInputActionValue v{};
const UInputAction* a{};
b->OnActionBeginEvent.Broadcast(IntenSelect, a, v);
}
}
void UIntenSelectable::HandleOnClickEndEvents(UIntenSelectComponent* IntenSelect, FInputActionValue& InputValue)
{
for (const UActionBehaviour* b : OnClickBehaviours)
{
const UInputAction* a{};
b->OnActionEndEvent.Broadcast(IntenSelect, a, InputValue);
}
}
void UIntenSelectable::InitDefaultBehaviourReferences()
{
// Scoring
if (UIntenSelectableScoring* AttachedScoring =
Cast<UIntenSelectableScoring>(GetOwner()->GetComponentByClass(UIntenSelectableScoring::StaticClass())))
{
ScoringBehaviour = AttachedScoring;
}
else
{
ScoringBehaviour = NewObject<UIntenSelectableSinglePointScoring>(
this, UIntenSelectableSinglePointScoring::StaticClass(), "Default Scoring");
ScoringBehaviour->SetWorldLocation(GetOwner()->GetActorLocation());
ScoringBehaviour->AttachToComponent(GetOwner()->GetRootComponent(),
FAttachmentTransformRules::SnapToTargetNotIncludingScale);
}
// Selecting
TInlineComponentArray<UHoverBehaviour*> AttachedSelectionBehaviours;
GetOwner()->GetComponents(AttachedSelectionBehaviours, true);
this->OnSelectBehaviours = AttachedSelectionBehaviours;
// Clicking
TInlineComponentArray<UActionBehaviour*> AttachedClickBehaviours;
GetOwner()->GetComponents(AttachedClickBehaviours, true);
this->OnClickBehaviours = AttachedClickBehaviours;
}
void UIntenSelectable::ShowErrorAndQuit(const FString& Message) const
{
UE_LOG(LogTemp, Error, TEXT("%s"), *Message)
#if WITH_EDITOR
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(FString("RUNTIME ERROR")));
#endif
UKismetSystemLibrary::QuitGame(this, nullptr, EQuitPreference::Quit, false);
}
void UIntenSelectable::BeginPlay()
{
Super::BeginPlay();
TInlineComponentArray<UIntenSelectable*> AttachedIntenSelectables;
GetOwner()->GetComponents(AttachedIntenSelectables, false);
if (AttachedIntenSelectables.Num() > 1)
{
if (!ScoringBehaviour)
{
ShowErrorAndQuit(
"Please assign the Scoring Behaviour manually when using more than one IntenSelectable Component!");
}
}
else
{
InitDefaultBehaviourReferences();
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectableCircleScoring.h"
#include "DrawDebugHelpers.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values for this component's properties
UIntenSelectableCircleScoring::UIntenSelectableCircleScoring() { PrimaryComponentTick.bCanEverTick = true; }
TPair<FHitResult, float>
UIntenSelectableCircleScoring::GetBestPointScorePair(const FVector& ConeOrigin, const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance, const float ConeAngle,
const float LastValue, const float DeltaTime)
{
const FVector Point = GetClosestSelectionPointTo(ConeOrigin, ConeForwardDirection);
float Score =
GetScore(ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, Point, LastValue, DeltaTime);
FHitResult Result = FHitResult{GetOwner(), nullptr, Point, FVector::ForwardVector};
return TPair<FHitResult, float>{Result, Score};
}
FVector UIntenSelectableCircleScoring::GetClosestSelectionPointTo(const FVector& Point, const FVector& Direction) const
{
const FVector CenterWorld = this->GetComponentLocation();
const FVector CircleNormalWorld =
this->GetComponentTransform().TransformPositionNoScale(FVector::ForwardVector) - CenterWorld;
float t;
FVector Intersect;
if (!UKismetMathLibrary::LinePlaneIntersection_OriginNormal(Point, Point + Direction * 100000, CenterWorld,
CircleNormalWorld, t, Intersect))
{
return CenterWorld;
}
const FVector CenterToPoint = Intersect - CenterWorld;
FVector Result;
if (OnlyOutline)
{
Result = (CenterToPoint.GetSafeNormal() * Radius) + CenterWorld;
}
else
{
const float DistanceToCenter = CenterToPoint.Size();
if (DistanceToCenter >= Radius)
{
Result = (CenterToPoint.GetSafeNormal() * Radius) + CenterWorld;
}
else
{
Result = Intersect;
}
}
FVector Y = CenterToPoint.GetSafeNormal();
FVector Z = FVector::CrossProduct(Y, CircleNormalWorld.GetSafeNormal());
// Y = FVector(0, 0, 1);
// Z = FVector(1, 0, 0);
DrawDebugCircle(GetWorld(), CenterWorld, Radius, 80, FColor::Green, false, -1, 0, 1, Y, Z, false);
return Result;
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectableCubeScoring.h"
#include "DrawDebugHelpers.h"
#include "Intersection/IntrRay3AxisAlignedBox3.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values for this component's properties
UIntenSelectableCubeScoring::UIntenSelectableCubeScoring()
{
PrimaryComponentTick.bCanEverTick = true;
SetRelativeScale3D(FVector::One() * 100);
}
TPair<FHitResult, float>
UIntenSelectableCubeScoring::GetBestPointScorePair(const FVector& ConeOrigin, const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance, const float ConeAngle,
const float LastValue, const float DeltaTime)
{
FVector Point = GetClosestSelectionPointTo(ConeOrigin, ConeForwardDirection);
float Score = Super::GetScore(ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, Point,
LastValue, DeltaTime);
FHitResult Result = FHitResult{GetOwner(), nullptr, Point, FVector::ForwardVector};
return TPair<FHitResult, float>{Result, Score};
}
FVector UIntenSelectableCubeScoring::GetClosestPointToRectangle(const FVector& StartPoint, const FVector& Direction,
const FVector& Corner00, const FVector& Corner01,
const FVector& Corner10, const FVector& Corner11) const
{
const float X = FVector::Distance(Corner00, Corner10);
const float Y = FVector::Distance(Corner00, Corner01);
const FVector PlaneNormal = FVector::CrossProduct(Corner10 - Corner00, Corner01 - Corner00).GetSafeNormal();
FVector Intersection;
float T;
UKismetMathLibrary::LinePlaneIntersection_OriginNormal(StartPoint, StartPoint + Direction * 10000, Corner00,
PlaneNormal, T, Intersection);
FVector LocalIntersection = this->GetComponentTransform().InverseTransformPosition(Intersection);
if (LocalIntersection.Y > X / 2)
{
LocalIntersection.Y = X / 2;
}
else if (LocalIntersection.Y < -X / 2)
{
LocalIntersection.Y = -X / 2;
}
if (LocalIntersection.Z > Y / 2)
{
LocalIntersection.Z = Y / 2;
}
else if (LocalIntersection.Z < -Y / 2)
{
LocalIntersection.Z = -Y / 2;
}
/*
if(OnlyOutline)
{
const float DistToBottom = LocalIntersection.Z + (YLength / 2);
const float DistToLeft = LocalIntersection.Y + (XLength / 2);
if(LocalIntersection.Z < 0)
{
if(LocalIntersection.Y < 0)
{
//Bottom and left
if(DistToLeft < DistToBottom)
{
//snap left
LocalIntersection.Y = -(XLength / 2);
}else
{
//snap bottom
LocalIntersection.Z = -(YLength / 2);
}
}else
{
//bottom and right
if(XLength - DistToLeft < DistToBottom)
{
//snap right
LocalIntersection.Y = XLength / 2;
}else
{
//snap bottom
LocalIntersection.Z = -(YLength / 2);
}
}
}else
{
if(LocalIntersection.Y < 0)
{
//top and left
if(DistToLeft < YLength - DistToBottom)
{
//snap left
LocalIntersection.Y = -(XLength / 2);
}else
{
//snap top
LocalIntersection.Z = (YLength / 2);
}
}else
{
//top and right
if(XLength - DistToLeft < YLength - DistToBottom)
{
//snap right
LocalIntersection.Y = XLength / 2;
}else
{
//snap top
LocalIntersection.Z = (YLength / 2);
}
}
}
}
*/
return this->GetComponentTransform().TransformPosition(LocalIntersection);
}
bool UIntenSelectableCubeScoring::LineToLineIntersection(const FVector& FromA, const FVector& FromB, const FVector& ToA,
const FVector& ToB, FVector& OutIntersection)
{
const FVector Da = ToA - FromA;
const FVector DB = ToB - FromB;
const FVector DC = FromB - FromA;
const FVector CrossDaDb = FVector::CrossProduct(Da, DB);
const float Prod = CrossDaDb.X * CrossDaDb.X + CrossDaDb.Y * CrossDaDb.Y + CrossDaDb.Z * CrossDaDb.Z;
const float Res = FVector::DotProduct(FVector::CrossProduct(DC, DB), FVector::CrossProduct(Da, DB) / Prod);
if (Res >= -0.02f && Res <= 1.02f)
{
OutIntersection = FromA + Da * FVector(Res, Res, Res);
return true;
}
return false;
}
FVector UIntenSelectableCubeScoring::GetClosestSelectionPointTo(const FVector& RayOrigin, const FVector& RayDirection)
{
auto Scale = GetRelativeTransform().GetScale3D();
const FVector X = this->GetForwardVector() * Scale.X;
const FVector Y = this->GetRightVector() * Scale.Y;
const FVector Z = this->GetUpVector() * Scale.Z;
TArray<FPlane> CubeSides;
// bottom
const FVector BottomWorld = this->GetComponentTransform().TransformPositionNoScale(-Z / 2);
CubeSides.Add(FPlane{BottomWorld, -this->GetUpVector()});
// top
const FVector TopWorld = this->GetComponentTransform().TransformPositionNoScale(Z / 2);
CubeSides.Add(FPlane{TopWorld, this->GetUpVector()});
// left
const FVector LeftWorld = this->GetComponentTransform().TransformPositionNoScale(-Y / 2);
CubeSides.Add(FPlane{LeftWorld, -this->GetRightVector()});
// right
const FVector RightWorld = this->GetComponentTransform().TransformPositionNoScale(Y / 2);
CubeSides.Add(FPlane{RightWorld, this->GetRightVector()});
// front
const FVector FrontWorld = this->GetComponentTransform().TransformPositionNoScale(-X / 2);
CubeSides.Add(FPlane{FrontWorld, -this->GetForwardVector()});
// back
const FVector BackWorld = this->GetComponentTransform().TransformPositionNoScale(X / 2);
CubeSides.Add(FPlane{BackWorld, this->GetForwardVector()});
/*
const TRay3<float> Ray{Point, Direction, false};
const TAxisAlignedBox3<float> Box;
float OutT;
if(TIntrRay3AxisAlignedBox3<float>::FindIntersection(Ray, Box, OutT))
{
}*/
float MinDistance = TNumericLimits<float>::Max();
FVector ClosestPoint = GetComponentLocation();
bool IsSet = false;
for (FPlane Plane : CubeSides)
{
const FVector PlaneToRayOrigin = RayOrigin - Plane.GetOrigin();
if (FVector::DotProduct(PlaneToRayOrigin.GetSafeNormal(), Plane.GetNormal()) < 0 && BackFaceCulling)
{
if (DrawDebug)
{
DrawDebugSolidPlane(GetWorld(), Plane, GetComponentLocation(), 20, FColor::Red.WithAlpha(9), false, -1,
0);
}
continue;
}
else
{
if (DrawDebug)
{
DrawDebugSolidPlane(GetWorld(), Plane, GetComponentLocation(), 20, FColor::Green.WithAlpha(9), false,
-1, 0);
}
}
FVector CurrentPoint = FMath::RayPlaneIntersection(RayOrigin, RayDirection, Plane);
FVector CurrentPointLocal = GetComponentTransform().InverseTransformPositionNoScale(CurrentPoint);
Scale = GetRelativeTransform().GetScale3D();
CurrentPointLocal.X = FMath::Clamp(CurrentPointLocal.X, -Scale.X / 2, Scale.X / 2);
CurrentPointLocal.Y = FMath::Clamp(CurrentPointLocal.Y, -Scale.Y / 2, Scale.Y / 2);
CurrentPointLocal.Z = FMath::Clamp(CurrentPointLocal.Z, -Scale.Z / 2, Scale.Z / 2);
if (OnlyOutline)
{
const float XSnapDist = (Scale.X / 2) - FMath::Abs(CurrentPointLocal.X);
const float YSnapDist = (Scale.Y / 2) - FMath::Abs(CurrentPointLocal.Y);
const float ZSnapDist = (Scale.Z / 2) - FMath::Abs(CurrentPointLocal.Z);
bool SnapX = true;
bool SnapY = true;
bool SnapZ = true;
if (FVector::Parallel(Plane.GetNormal(), GetRightVector()))
{
if (XSnapDist < ZSnapDist)
{
SnapZ = false;
}
else
{
SnapX = false;
}
}
else if (FVector::Parallel(Plane.GetNormal(), GetUpVector()))
{
if (XSnapDist < YSnapDist)
{
SnapY = false;
}
else
{
SnapX = false;
}
}
else if (FVector::Parallel(Plane.GetNormal(), GetForwardVector()))
{
if (YSnapDist < ZSnapDist)
{
SnapZ = false;
}
else
{
SnapY = false;
}
}
if (SnapX)
{
if (CurrentPointLocal.X > 0)
{
CurrentPointLocal.X = Scale.X / 2;
}
else
{
CurrentPointLocal.X = -Scale.X / 2;
}
}
if (SnapY)
{
if (CurrentPointLocal.Y > 0)
{
CurrentPointLocal.Y = Scale.Y / 2;
}
else
{
CurrentPointLocal.Y = -Scale.Y / 2;
}
}
if (SnapZ)
{
if (CurrentPointLocal.Z > 0)
{
CurrentPointLocal.Z = Scale.Z / 2;
}
else
{
CurrentPointLocal.Z = -Scale.Z / 2;
}
}
}
CurrentPoint = GetComponentTransform().TransformPositionNoScale(CurrentPointLocal);
const float Distance = FMath::PointDistToLine(CurrentPoint, RayDirection, RayOrigin);
// DrawDebugPoint(GetWorld(), CurrentPoint, 10, FColor::Black.WithAlpha(1), false, -1, 0);
// GEngine->AddOnScreenDebugMessage(INDEX_NONE, -1, FColor::Red, FString::SanitizeFloat(Distance));
if (Distance < 0.001)
{
if (MinDistance < 0.001)
{
const float DistToPlayerOld =
IsSet ? FVector::Distance(RayOrigin, ClosestPoint) : TNumericLimits<float>::Max();
const float DistToPlayerNew = FVector::Distance(RayOrigin, CurrentPoint);
if (DistToPlayerNew < DistToPlayerOld)
{
MinDistance = Distance;
ClosestPoint = CurrentPoint;
IsSet = true;
}
}
else
{
MinDistance = Distance;
ClosestPoint = CurrentPoint;
IsSet = true;
}
}
else
{
if (Distance < MinDistance)
{
MinDistance = Distance;
ClosestPoint = CurrentPoint;
IsSet = true;
}
}
}
if (DrawDebug)
DrawDebugBox(GetWorld(), GetComponentLocation(), FVector(Scale.X, Scale.Y, Scale.Z) / 2,
GetComponentRotation().Quaternion(), FColor::Green, false, -1, 0, 2);
return ClosestPoint;
}
void UIntenSelectableCubeScoring::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectableCylinderScoring.h"
#include "DrawDebugHelpers.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values for this component's properties
UIntenSelectableCylinderScoring::UIntenSelectableCylinderScoring() { PrimaryComponentTick.bCanEverTick = true; }
TPair<FHitResult, float>
UIntenSelectableCylinderScoring::GetBestPointScorePair(const FVector& ConeOrigin, const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance, const float ConeAngle,
const float LastValue, const float DeltaTime)
{
FVector Point = GetClosestSelectionPointTo(ConeOrigin, ConeForwardDirection);
float Score =
GetScore(ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, Point, LastValue, DeltaTime);
FHitResult Result = FHitResult{GetOwner(), nullptr, Point, FVector::ForwardVector};
return TPair<FHitResult, float>{Result, Score};
}
bool UIntenSelectableCylinderScoring::LineToLineIntersection(const FVector& FromA, const FVector& FromB,
const FVector& ToA, const FVector& ToB,
FVector& OutIntersection)
{
const FVector Da = ToA - FromA;
const FVector DB = ToB - FromB;
const FVector DC = FromB - FromA;
const FVector CrossDaDb = FVector::CrossProduct(Da, DB);
const float Prod = CrossDaDb.X * CrossDaDb.X + CrossDaDb.Y * CrossDaDb.Y + CrossDaDb.Z * CrossDaDb.Z;
const float Res = FVector::DotProduct(FVector::CrossProduct(DC, DB), FVector::CrossProduct(Da, DB) / Prod);
if (Res >= -0.02f && Res <= 1.02f)
{
OutIntersection = FromA + Da * FVector(Res, Res, Res);
return true;
}
return false;
}
FVector UIntenSelectableCylinderScoring::GetClosestSelectionPointTo(const FVector& Point,
const FVector& Direction) const
{
const FVector CylinderStartWorld = this->GetComponentTransform().TransformPosition(LinePoints[0]);
const FVector CylinderEndWorld = this->GetComponentTransform().TransformPosition(LinePoints[1]);
const FVector CylinderDir = CylinderEndWorld - CylinderStartWorld;
const FVector CrossProd = UKismetMathLibrary::Cross_VectorVector(CylinderDir, Direction); // v
const FVector LineDifference = CylinderStartWorld - Point; // u
// Project v onto u =>
const FVector Proj = LineDifference.ProjectOnTo(CrossProd);
const float ProjLength = Proj.Size();
const FVector OffsetPoint = Point + Proj;
const FVector FromA = OffsetPoint;
const FVector FromB = CylinderStartWorld;
const FVector ToA = OffsetPoint + Direction * 10000;
const FVector ToB = CylinderEndWorld;
FVector Result;
LineToLineIntersection(FromA, FromB, ToA, ToB, Result);
const FVector LineDirRes = Result - CylinderStartWorld;
if (LineDirRes.Size() > CylinderDir.Size())
{
Result = CylinderEndWorld;
}
if (!LineDirRes.GetSafeNormal().Equals(CylinderDir.GetSafeNormal()))
{
Result = CylinderStartWorld;
}
const FVector ToSphere = Result - Point;
const FVector Projection = ToSphere.ProjectOnTo(Direction);
const FVector ProjectionToSphere = ToSphere - Projection;
if (ProjLength >= Radius)
{
FVector ShiftResult = ProjectionToSphere.GetSafeNormal() * Radius;
ShiftResult -= ShiftResult.ProjectOnTo(CylinderDir);
return Result - ShiftResult;
}
else
{
FVector ShiftResult = ProjectionToSphere.GetSafeNormal() * ProjLength;
ShiftResult -= ShiftResult.ProjectOnTo(CylinderDir);
return Result - ShiftResult;
}
}
void UIntenSelectableCylinderScoring::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (DrawDebug)
{
const FVector StartWorld = this->GetComponentTransform().TransformPosition(LinePoints[0]);
const FVector EndWorld = this->GetComponentTransform().TransformPosition(LinePoints[1]);
DrawDebugCylinder(GetWorld(), StartWorld, EndWorld, Radius, 20, FColor::Green, false, 0, 0, 2);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectableLineScoring.h"
#include "DrawDebugHelpers.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values for this component's properties
UIntenSelectableLineScoring::UIntenSelectableLineScoring()
{
PrimaryComponentTick.bCanEverTick = true;
if (this->LinePoints.Num() == 2)
{
const FVector Average = (this->LinePoints[0] + this->LinePoints[1]) / 2;
this->SetWorldLocation(this->GetComponentTransform().TransformPositionNoScale(Average));
this->LinePoints[0] -= Average;
this->LinePoints[1] -= Average;
}
}
TPair<FHitResult, float>
UIntenSelectableLineScoring::GetBestPointScorePair(const FVector& ConeOrigin, const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance, const float ConeAngle,
const float LastValue, const float DeltaTime)
{
FVector Point = GetClosestSelectionPointTo(ConeOrigin, ConeForwardDirection);
float Score =
GetScore(ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, Point, LastValue, DeltaTime);
FHitResult Result = FHitResult{GetOwner(), nullptr, Point, FVector::ForwardVector};
return TPair<FHitResult, float>{Result, Score};
}
bool UIntenSelectableLineScoring::LineToLineIntersection(const FVector& FromA, const FVector& FromB, const FVector& ToA,
const FVector& ToB, FVector& OutIntersection)
{
const FVector Da = ToA - FromA;
const FVector DB = ToB - FromB;
const FVector DC = FromB - FromA;
const FVector CrossDaDb = FVector::CrossProduct(Da, DB);
const float Prod = CrossDaDb.X * CrossDaDb.X + CrossDaDb.Y * CrossDaDb.Y + CrossDaDb.Z * CrossDaDb.Z;
const float Res = FVector::DotProduct(FVector::CrossProduct(DC, DB), FVector::CrossProduct(Da, DB) / Prod);
if (Res >= -0.02f && Res <= 1.02f)
{
OutIntersection = FromA + Da * FVector(Res, Res, Res);
return true;
}
return false;
}
FVector UIntenSelectableLineScoring::GetClosestSelectionPointTo(const FVector& Point, const FVector& Direction) const
{
const FVector StartWorld = this->GetComponentTransform().TransformPosition(LinePoints[0]);
const FVector EndWorld = this->GetComponentTransform().TransformPosition(LinePoints[1]);
const FVector LineDir = EndWorld - StartWorld;
const FVector CrossProd = UKismetMathLibrary::Cross_VectorVector(LineDir, Direction); // v
const FVector LineDifference = StartWorld - Point; // u
// Project v onto u =>
const FVector Proj = LineDifference.ProjectOnTo(CrossProd);
const FVector OffsetPoint = Point + Proj;
const FVector FromA = OffsetPoint;
const FVector FromB = StartWorld;
const FVector ToA = OffsetPoint + Direction * 10000;
const FVector ToB = EndWorld;
FVector Result;
LineToLineIntersection(FromA, FromB, ToA, ToB, Result);
const FVector LineDirRes = Result - StartWorld;
if (LineDirRes.Size() > LineDir.Size())
{
Result = EndWorld;
}
if (!LineDirRes.GetSafeNormal().Equals(LineDir.GetSafeNormal()))
{
Result = StartWorld;
}
return Result;
}
void UIntenSelectableLineScoring::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (DrawDebug)
{
const FVector StartWorld = this->GetComponentTransform().TransformPosition(LinePoints[0]);
const FVector EndWorld = this->GetComponentTransform().TransformPosition(LinePoints[1]);
DrawDebugLine(GetWorld(), StartWorld, EndWorld, FColor::Green, false, -1, 0, 2);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/IntenSelect/IntenSelectableMultiPointScoring.h"
#include "Kismet/KismetMathLibrary.h"
#include "Net/Core/PushModel/PushModel.h"
// Sets default values for this component's properties
UIntenSelectableMultiPointScoring::UIntenSelectableMultiPointScoring()
{
PrimaryComponentTick.bCanEverTick = true;
PointsToSelect = TArray<FVector>{FVector::UpVector * 100, FVector::DownVector * 100, FVector::RightVector * 100,
FVector::LeftVector * 100};
}
TPair<FHitResult, float>
UIntenSelectableMultiPointScoring::GetBestPointScorePair(const FVector& ConeOrigin, const FVector& ConeForwardDirection,
const float ConeBackwardShiftDistance, const float ConeAngle,
const float LastValue, const float DeltaTime)
{
FVector Point = GetClosestSelectionPointTo(ConeOrigin, ConeForwardDirection);
float Score = Super::GetScore(ConeOrigin, ConeForwardDirection, ConeBackwardShiftDistance, ConeAngle, Point,
LastValue, DeltaTime);
FHitResult Result = FHitResult{GetOwner(), nullptr, Point, FVector::ForwardVector};
return TPair<FHitResult, float>{Result, Score};
}
void UIntenSelectableMultiPointScoring::UpdatePoints() {}
FVector UIntenSelectableMultiPointScoring::GetClosestSelectionPointTo(const FVector& Point,
const FVector& Direction) const
{
if (PointsToSelect.Num() == 0)
{
return this->GetComponentLocation();
}
FVector ClosestPoint = this->GetComponentTransform().TransformPositionNoScale(PointsToSelect[0]);
float MinDistance = UKismetMathLibrary::GetPointDistanceToLine(ClosestPoint, Point, Direction);
for (const FVector P : PointsToSelect)
{
const FVector PointToCheck = this->GetComponentTransform().TransformPositionNoScale(P);
const float Dist = UKismetMathLibrary::GetPointDistanceToLine(PointToCheck, Point, Direction);
if (Dist < MinDistance)
{
MinDistance = Dist;
ClosestPoint = PointToCheck;
}
}
return ClosestPoint;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment