// Fill out your copyright notice in the Description page of Project Settings. #include "DrawDebugHelpers.h" #include "Engine/World.h" #include "GameFramework/PlayerController.h" #include "PhysicsEngine/PhysicsHandleComponent.h" #include "Grabber.h" #define OUT //mark for outparameters (only for reading purposes) // Sets default values for this component's properties UGrabber::UGrabber() { // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features // off to improve performance if you don't need them. PrimaryComponentTick.bCanEverTick = true; } // Called when the game starts void UGrabber::BeginPlay() { Super::BeginPlay(); FindPhysicsHandle(); //Check for physics Handle Component SetupInputComponent(); } void UGrabber::FindPhysicsHandle() { PhysicsHandle = GetOwner()->FindComponentByClass(); //<> for function templates if(!PhysicsHandle) // same as if(PhysicsHandle == nullptr) { UE_LOG(LogTemp, Error, TEXT("No Physics handle component found on: %s !"), *GetOwner()->GetName()); } } void UGrabber::SetupInputComponent() { InputComponent = GetOwner()->FindComponentByClass(); if(InputComponent) { //UE_LOG(LogTemp, Warning, TEXT("Input Component found on: %s !"), *GetOwner()->GetName()); InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab); // User Input zu einem funktionsaufruf binden // Name der funktion beim keypress gleich name vom action in projectsettings , IE = InputEvent InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::GrabRelease); } else { UE_LOG(LogTemp, Error, TEXT("Input Component MISSING on: %s !"), *GetOwner()->GetName()); } } void UGrabber::Grab() { //only Raycast, when key is pressed and Try and reach any actor with physics body collision set. FHitResult HitResult = GetFirstPhysicsBodyInReach(); UPrimitiveComponent* ComponentToGrab = HitResult.GetComponent(); AActor* ActorHit = HitResult.GetActor(); //if we hit something, attach physics handle if(ActorHit) //if an actor is hit, then attach PhysicsHandle { if(!PhysicsHandle){return;} PhysicsHandle->GrabComponentAtLocation ( ComponentToGrab, NAME_None, GetLineTraceEnd() ); } } void UGrabber::GrabRelease() { //Remove, release physicshandle if(!PhysicsHandle){return;} PhysicsHandle->ReleaseComponent(); } // Called every frame void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if(!PhysicsHandle){return;} //If PhysicsBody attached if(PhysicsHandle->GrabbedComponent) { //move object we are holding PhysicsHandle->SetTargetLocation(GetLineTraceEnd()); } } FHitResult UGrabber::GetFirstPhysicsBodyInReach() const { FHitResult Hit; //Raycast out to a certain distance (Reach) FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner()); //fname, ComplexCollision=false, ignore hit on owner(origin point) GetWorld()->LineTraceSingleByObjectType( OUT Hit, GetPlayerWorldPosition(), //PlayerViewPointLocation GetLineTraceEnd(), FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody), //:: to accsess an enum TraceParams ); return Hit; } FVector UGrabber::GetPlayerWorldPosition() const { //Get Player Viewport FVector PlayerViewPointLocation; FRotator PlayerViewPointRotation; GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint( OUT PlayerViewPointLocation, OUT PlayerViewPointRotation ); return PlayerViewPointLocation; } FVector UGrabber::GetLineTraceEnd() const //Players Reach { //Get Player Viewport FVector PlayerViewPointLocation; FRotator PlayerViewPointRotation; GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint( OUT PlayerViewPointLocation, OUT PlayerViewPointRotation ); return PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach; } //comments //Logging out to test // UE_LOG(LogTemp, Warning, TEXT("Location: %s, Rotation= %s"), // *PlayerViewPointLocation.ToString(), // *PlayerViewPointRotation.ToString() // ); /* //Get Player Viewport FVector PlayerViewPointLocation; FRotator PlayerViewPointRotation; GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint( OUT PlayerViewPointLocation, OUT PlayerViewPointRotation ); //GetPhysicsbodyInReach //Draw a Line from the Player showing the Reach FVector LineTraceEnd = PlayerViewPointLocation + PlayerViewPointRotation.Vector() * Reach; // DEBUG // DrawDebugLine( // GetWorld(), // PlayerViewPointLocation, // LineTraceEnd, // FColor(0, 255 , 0) //red, green, blue, // false, // 0.f, // 0, // 5.f // ); */ //return name of hit actor //See what it hits // if(Hit.GetActor()) // UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *Hit.GetActor()->GetName()); //or /* AActor* ActorHit = Hit.GetActor(); //Log out to Test if(Hit.GetActor()) { UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *ActorHit->GetName()); } */