<commit_before>// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

#include "Computatorium.h"
#include "ComputatoriumCharacter.h"
#include "Fetchable.h"
#include "Receptor.h"
#include "PlayerButton.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Runtime/Engine/Classes/Components/DecalComponent.h"
#include "Kismet/HeadMountedDisplayFunctionLibrary.h"

// Print to screen debug
// GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Setting new target fetchable!"));
#include "EngineGlobals.h"
#include "Runtime/Engine/Classes/Engine/Engine.h"

AComputatoriumCharacter::AComputatoriumCharacter() {
	// Set size for player capsule
	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

	// Don't rotate character to camera direction
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false; 
	bUseControllerRotationRoll = false;

	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Rotate character to moving direction 
	GetCharacterMovement()->RotationRate = FRotator(0.f, 640.f, 0.f);
	GetCharacterMovement()->bConstrainToPlane = true;
	GetCharacterMovement()->bSnapToPlaneAtStart = true;

	// Create a camera boom...
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	CameraBoom->bAbsoluteRotation = true; // Don't want arm to rotate when character does
	CameraBoom->TargetArmLength = 800.f;
	CameraBoom->RelativeRotation = FRotator(-60.f, 0.f, 0.f);
	CameraBoom->bDoCollisionTest = false; // Don't want to pull camera in when it collides with level

    // Create a camera...
	TopDownCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
	TopDownCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
	TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

	// Create a decal in the world to show the cursor's location
	CursorToWorld = CreateDefaultSubobject<UDecalComponent>("CursorToWorld");
	CursorToWorld->SetupAttachment(RootComponent);
	static ConstructorHelpers::FObjectFinder<UMaterial> DecalMaterialAsset(TEXT("Material'/Game/Blueprints/M_Cursor_Decal.M_Cursor_Decal'"));
	if (DecalMaterialAsset.Succeeded())
	{
		CursorToWorld->SetDecalMaterial(DecalMaterialAsset.Object);
	}
	CursorToWorld->DecalSize = FVector(16.0f, 32.0f, 32.0f);
	CursorToWorld->SetRelativeRotation(FRotator(90.0f, 0.0f, 0.0f).Quaternion());

	// Activate ticking in order to update the cursor every frame.
	PrimaryActorTick.bCanEverTick = true;
	PrimaryActorTick.bStartWithTickEnabled = true;
    
	// Register OnHit delegate
//   OnActorHit.AddDynamic(this, &AComputatoriumCharacter::OnHit);
	// Register OnOverlap delegates
//	GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AComputatoriumCharacter::OnBeginOverlap);
//	GetCapsuleComponent()->OnComponentEndOverlap.AddDynamic(this, &AComputatoriumCharacter::OnEndOverlap);
}

void AComputatoriumCharacter::Tick(float DeltaSeconds) {
    Super::Tick(DeltaSeconds);

	if (CursorToWorld != nullptr)
	{
		if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
		{
			if (UWorld* World = GetWorld())
			{
				FHitResult HitResult;
				FCollisionQueryParams Params;
				FVector StartLocation = TopDownCameraComponent->GetComponentLocation();
				FVector EndLocation = TopDownCameraComponent->GetComponentRotation().Vector() * 2000.0f;
				Params.AddIgnoredActor(this);
				World->LineTraceSingleByChannel(HitResult, StartLocation, EndLocation, ECC_Visibility, Params);
				FQuat SurfaceRotation = HitResult.ImpactNormal.ToOrientationRotator().Quaternion();
				CursorToWorld->SetWorldLocationAndRotation(HitResult.Location, SurfaceRotation);
			}
		}
		else if (APlayerController* PC = Cast<APlayerController>(GetController()))
		{
			FHitResult TraceHitResult;
			PC->GetHitResultUnderCursor(ECC_Visibility, true, TraceHitResult);
			FVector CursorFV = TraceHitResult.ImpactNormal;
			FRotator CursorR = CursorFV.Rotation();
			CursorToWorld->SetWorldLocation(TraceHitResult.Location);
			CursorToWorld->SetWorldRotation(CursorR);
		}
	}

	// Check if player needs to bind to fetchable object
	if (TargetFetchable != nullptr) {
		GetOverlappingActors(OverlappingFetchables, AFetchable::StaticClass());

		// Loop through overlapping fetchables and check if any are our target fetchable
		for(auto OverlappingFetchable : OverlappingFetchables) {
			if (OverlappingFetchable == TargetFetchable && CanBindFetchable(TargetFetchable)) {
				this->BindFetchable(TargetFetchable);
			}
		}
	}

	// Check if player needs to deposit the fetchable object to receptor
	if (TargetReceptor != nullptr) {
	    GetOverlappingActors(OverlappingReceptors, AReceptor::StaticClass());

		// Loop through overlapping receptors and check if any are our target receptor
		for(auto OverlappingReceptor : OverlappingReceptors) {
			if (OverlappingReceptor == TargetReceptor && TargetReceptor->CanBindFetchable(BoundFetchable)) {
				TargetReceptor->BindFetchable(BoundFetchable);
			}
		}
	}

	// Check if player needs to click any buttons
	if (TargetButton != nullptr) {
		GetOverlappingActors(OverlappingButtons, APlayerButton::StaticClass());

		// Loop through overlapping buttons and check if any are our target button
		for (auto OverlappingButton : OverlappingButtons) {
			if (OverlappingButton == TargetButton) {
				TargetButton->Click();
				TargetButton = nullptr;
			}
		}
	}
}

void AComputatoriumCharacter::BindFetchable(AFetchable *Fetchable) {
	Fetchable->BindToActor(this, GetMesh());
}

bool AComputatoriumCharacter::CanBindFetchable(AFetchable* Fetchable) {
	// If we aren't holding a fetchable we can pick one up
	return (BoundFetchable == nullptr);
}

void AComputatoriumCharacter::PostUnbindFetchable(AFetchable *Fetchable) {
	// Enable navigation affect
	Fetchable->HitBox->SetCanEverAffectNavigation(true);
<commit_msg>Fix annoying runaround issue when placing fetchables<commit_after>// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

#include "Computatorium.h"
#include "ComputatoriumCharacter.h"
#include "Fetchable.h"
#include "Receptor.h"
#include "PlayerButton.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Runtime/Engine/Classes/Components/DecalComponent.h"
#include "Kismet/HeadMountedDisplayFunctionLibrary.h"

// Print to screen debug
// GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Setting new target fetchable!"));
#include "EngineGlobals.h"
#include "Runtime/Engine/Classes/Engine/Engine.h"

AComputatoriumCharacter::AComputatoriumCharacter() {
	// Set size for player capsule
	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

	// Don't rotate character to camera direction
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false; 
	bUseControllerRotationRoll = false;

	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Rotate character to moving direction 
	GetCharacterMovement()->RotationRate = FRotator(0.f, 640.f, 0.f);
	GetCharacterMovement()->bConstrainToPlane = true;
	GetCharacterMovement()->bSnapToPlaneAtStart = true;

	// Create a camera boom...
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	CameraBoom->bAbsoluteRotation = true; // Don't want arm to rotate when character does
	CameraBoom->TargetArmLength = 800.f;
	CameraBoom->RelativeRotation = FRotator(-60.f, 0.f, 0.f);
	CameraBoom->bDoCollisionTest = false; // Don't want to pull camera in when it collides with level

    // Create a camera...
	TopDownCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
	TopDownCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
	TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

	// Create a decal in the world to show the cursor's location
	CursorToWorld = CreateDefaultSubobject<UDecalComponent>("CursorToWorld");
	CursorToWorld->SetupAttachment(RootComponent);
	static ConstructorHelpers::FObjectFinder<UMaterial> DecalMaterialAsset(TEXT("Material'/Game/Blueprints/M_Cursor_Decal.M_Cursor_Decal'"));
	if (DecalMaterialAsset.Succeeded())
	{
		CursorToWorld->SetDecalMaterial(DecalMaterialAsset.Object);
	}
	CursorToWorld->DecalSize = FVector(16.0f, 32.0f, 32.0f);
	CursorToWorld->SetRelativeRotation(FRotator(90.0f, 0.0f, 0.0f).Quaternion());

	// Activate ticking in order to update the cursor every frame.
	PrimaryActorTick.bCanEverTick = true;
	PrimaryActorTick.bStartWithTickEnabled = true;
    
	// Register OnHit delegate
//   OnActorHit.AddDynamic(this, &AComputatoriumCharacter::OnHit);
	// Register OnOverlap delegates
//	GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AComputatoriumCharacter::OnBeginOverlap);
//	GetCapsuleComponent()->OnComponentEndOverlap.AddDynamic(this, &AComputatoriumCharacter::OnEndOverlap);
}

void AComputatoriumCharacter::Tick(float DeltaSeconds) {
    Super::Tick(DeltaSeconds);

	if (CursorToWorld != nullptr)
	{
		if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
		{
			if (UWorld* World = GetWorld())
			{
				FHitResult HitResult;
				FCollisionQueryParams Params;
				FVector StartLocation = TopDownCameraComponent->GetComponentLocation();
				FVector EndLocation = TopDownCameraComponent->GetComponentRotation().Vector() * 2000.0f;
				Params.AddIgnoredActor(this);
				World->LineTraceSingleByChannel(HitResult, StartLocation, EndLocation, ECC_Visibility, Params);
				FQuat SurfaceRotation = HitResult.ImpactNormal.ToOrientationRotator().Quaternion();
				CursorToWorld->SetWorldLocationAndRotation(HitResult.Location, SurfaceRotation);
			}
		}
		else if (APlayerController* PC = Cast<APlayerController>(GetController()))
		{
			FHitResult TraceHitResult;
			PC->GetHitResultUnderCursor(ECC_Visibility, true, TraceHitResult);
			FVector CursorFV = TraceHitResult.ImpactNormal;
			FRotator CursorR = CursorFV.Rotation();
			CursorToWorld->SetWorldLocation(TraceHitResult.Location);
			CursorToWorld->SetWorldRotation(CursorR);
		}
	}

	// Check if player needs to bind to fetchable object
	if (TargetFetchable != nullptr) {
		GetOverlappingActors(OverlappingFetchables, AFetchable::StaticClass());

		// Loop through overlapping fetchables and check if any are our target fetchable
		for(auto OverlappingFetchable : OverlappingFetchables) {
			if (OverlappingFetchable == TargetFetchable && CanBindFetchable(TargetFetchable)) {
				this->BindFetchable(TargetFetchable);
			}
		}
	}

	// Check if player needs to deposit the fetchable object to receptor
	if (TargetReceptor != nullptr) {
	    GetOverlappingActors(OverlappingReceptors, AReceptor::StaticClass());

		// Loop through overlapping receptors and check if any are our target receptor
		for(auto OverlappingReceptor : OverlappingReceptors) {
			if (OverlappingReceptor == TargetReceptor && TargetReceptor->CanBindFetchable(BoundFetchable)) {
				TargetReceptor->BindFetchable(BoundFetchable);
			}
		}
	}

	// Check if player needs to click any buttons
	if (TargetButton != nullptr) {
		GetOverlappingActors(OverlappingButtons, APlayerButton::StaticClass());

		// Loop through overlapping buttons and check if any are our target button
		for (auto OverlappingButton : OverlappingButtons) {
			if (OverlappingButton == TargetButton) {
				TargetButton->Click();
				TargetButton = nullptr;
			}
		}
	}
}

void AComputatoriumCharacter::BindFetchable(AFetchable *Fetchable) {
	Fetchable->BindToActor(this, GetMesh());
}

bool AComputatoriumCharacter::CanBindFetchable(AFetchable* Fetchable) {
	// If we aren't holding a fetchable we can pick one up
	return (BoundFetchable == nullptr);
}

void AComputatoriumCharacter::PostUnbindFetchable(AFetchable *Fetchable) {
	// Enable navigation affect
	Fetchable->HitBox->SetCanEverAffectNavigation(true);

	// Stop player reacting to navigation affect being enabled
	this->GetController()->StopMovement();

{'fraction_non_alphanumeric': 0.1047705814146099, 'fraction_numerical': 0.007950969024349842, 'mean_word_length': 5.955645161290323, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2227650', 'n_tokens_mistral': 3881, 'n_tokens_neox': 3554, 'n_words': 755}