// Fill out your copyright notice in the Description page of Project Settings. #include "UtilityLibrary.h" #include "GameFramework/PlayerController.h" #include "EnhancedInputSubsystems.h" #include "Kismet/KismetSystemLibrary.h" #include "Kismet/GameplayStatics.h" #define LOCTEXT_NAMESPACE "Luprex Utility" void UlxUtilityLibrary::CallFunctionByName(UObject *object, const FString &namepart1, const FString &namepart2, const FString &fallback, bool bFailIfNotFound) { FString fullname = namepart1 + namepart2; if (!IsValid(object)) { UE_LOG(LogBlueprint, Error, TEXT("In CallFunctionByName, object passed in is not valid.")); return; } UFunction* function = object->FindFunction(FName(*fullname)); if (function == nullptr) { function = object->FindFunction(FName(*fallback)); if (function == nullptr) { if (!bFailIfNotFound) { return; } UE_LOG(LogBlueprint, Error, TEXT("In CallFunctionByName, cannot find the named function or the fallback function")); return; } } if (function->ParmsSize != 0) { UE_LOG(LogBlueprint, Error, TEXT("CallFunctionByName can only call functions that have no parameters and no return values")); return; } object->ProcessEvent(function, nullptr); } FBox UlxUtilityLibrary::GetActorBounds(const AActor *target, bool bOnlyCollidingComponents, bool bIncludeFromChildActors) { FVector ActorOrigin; FVector BoxExtent; // First argument is bOnlyCollidingComponents - if you want to get the bounds for components that don't have collision enabled then set to false // Last argument is bIncludeFromChildActors. Usually this won't do anything but if we've child-ed an actor - like a gun child-ed to a character // then we wouldn't want the gun to be part of the bounds so set to false target->GetActorBounds(bOnlyCollidingComponents, ActorOrigin, BoxExtent, bIncludeFromChildActors); return FBox::BuildAABB(ActorOrigin, BoxExtent); } void UlxUtilityLibrary::AddMovementInputRightward(APawn *target, double ScaleValue, bool Force) { FRotator rotator = target->GetControlRotation(); rotator.Pitch = 0.0; rotator.Roll = 0.0; rotator.Yaw += 90.0; FVector vector = rotator.Vector(); target->AddMovementInput(vector, ScaleValue, Force); } void UlxUtilityLibrary::AddMovementInputForward(APawn *target, double ScaleValue, bool Force) { FRotator rotator = target->GetControlRotation(); rotator.Roll = 0.0; rotator.Pitch = 0.0; FVector vector = rotator.Vector(); target->AddMovementInput(vector, ScaleValue, Force); } UEnhancedInputLocalPlayerSubsystem *UlxUtilityLibrary::GetEnhancedInputLocalPlayerSubsystem(AController *Controller) { APlayerController *pc = Cast(Controller); if (pc != nullptr) { UEnhancedInputLocalPlayerSubsystem* subsys = ULocalPlayer::GetSubsystem(pc->GetLocalPlayer()); if (subsys != nullptr) { return subsys; } } return nullptr; } // bool UlxUtilityLibrary::LineTraceMultipleLines(const AActor* ReferenceActor, const FVector &Offset, // const TArray &TraceStartAndTraceEnd, ETraceTypeQuery TraceChannel, // bool bTraceComplex, const TArray& ActorsToIgnore, EDrawDebugTrace::Type DrawDebugType, FHitResult& OutHit, bool bIgnoreReferenceActor, // FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime) // { // OutHit.Init(); // OutHit.Distance = FLT_MAX; // FTransform ReferenceTransform = ReferenceActor->GetActorTransform(); // for (const FlxTraceStartTraceEnd &Points : TraceStartAndTraceEnd) { // FHitResult OneResult; // FVector TraceStart = ReferenceTransform.TransformPosition(Points.TraceStart + Offset); // FVector TraceEnd = ReferenceTransform.TransformPosition(Points.TraceEnd + Offset); // bool Found = UKismetSystemLibrary::LineTraceSingle(ReferenceActor, TraceStart, TraceEnd, TraceChannel, bTraceComplex, // ActorsToIgnore, DrawDebugType, OneResult, bIgnoreReferenceActor, TraceColor, TraceHitColor, DrawTime); // if (Found && (OneResult.Distance < OutHit.Distance)) // { // OutHit = OneResult; // } // } // if (OutHit.Distance == FLT_MAX) { // OutHit.Distance = 0.0; // return false; // } else { // return true; // } // } bool UlxUtilityLibrary::LineTraceThroughMousePointer(const APlayerController* PlayerController, EMouseSpecificationType MouseSpecification, FVector2D ManualMouseXY, double MaxDistanceFromCamera, ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn, const TArray& ActorsToIgnore, AActor *& Actor, FHitResult& HitResult) { const FLinearColor TraceColor = FLinearColor::Red; const FLinearColor TraceHitColor = FLinearColor::Green; const double DrawTime = 1.0; // Zero out the return values. Actor = nullptr; HitResult.Init(); // Sanity check the distance. if (MaxDistanceFromCamera <= 0.0) { return false; } // Make sure there's a player pawn. AActor *PlayerPawn = PlayerController->GetPawn(); if (!PlayerPawn) return false; // Get the Mouse XY. FVector2D MouseXY; switch (MouseSpecification) { case EMouseSpecificationType::GetMouseAutomatically: { double X, Y; if (!PlayerController->GetMousePosition(X, Y)) return false; MouseXY = FVector2D(X, Y); break; } case EMouseSpecificationType::SpecifyMouseInPixels: { MouseXY = ManualMouseXY; break; } case EMouseSpecificationType::SpecifyMouseAsZeroToOne: { int32 VX, VY; PlayerController->GetViewportSize(VX, VY); if ((VX == 0) || (VY == 0)) return false; MouseXY = ManualMouseXY * FVector2D(VX, VY); break; } } // Calculate the trace start and trace end positions in world space. FVector WorldStart, WorldDirection, WorldEnd; if (!UGameplayStatics::DeprojectScreenToWorld(PlayerController, MouseXY, WorldStart, WorldDirection)) { return false; } WorldEnd = WorldStart + (WorldDirection * MaxDistanceFromCamera); // Find the hit. if (UKismetSystemLibrary::LineTraceSingle(PlayerPawn, WorldStart, WorldEnd, TraceChannel, bTraceComplex, ActorsToIgnore, DrawDebugType, HitResult, bIgnorePlayerPawn, TraceColor, TraceHitColor, DrawTime)) { Actor = HitResult.GetActor(); return true; } // Fail. Actor = nullptr; HitResult.Init(); return false; }