264 lines
7.4 KiB
C++
264 lines
7.4 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "CoffeeMachineController.h"
|
|
|
|
#include "HoverableBoxComponent.h"
|
|
#include "Faye/Base/FayePlayerController.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
|
|
|
|
UCoffeeMachineController::UCoffeeMachineController()
|
|
{
|
|
PrimaryComponentTick.bCanEverTick = true;
|
|
}
|
|
|
|
void UCoffeeMachineController::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
{
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
|
|
if (!bCoffeeMakingActive) return;
|
|
|
|
if (InputType == EInputControllerType::Mouse)
|
|
{
|
|
PerformMouseHover();
|
|
|
|
if (CurrentSelectedMeshComponent)
|
|
{
|
|
MoveHeldObject();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UCoffeeMachineController::ToggleCoffeeMaking(bool bActive)
|
|
{
|
|
bCoffeeMakingActive = bActive;
|
|
PlayerController->ToggleCoffeeMaking(bActive);
|
|
|
|
if (bCoffeeMakingActive)
|
|
{
|
|
PlayerController->OnCoffeeMakingAction_GrabStarted.AddUniqueDynamic(this, &UCoffeeMachineController::OnInputGrab);
|
|
PlayerController->OnCoffeeMakingAction_GrabRelease.AddUniqueDynamic(this, &UCoffeeMachineController::OnInputRelease);
|
|
}
|
|
else
|
|
{
|
|
PlayerController->OnCoffeeMakingAction_GrabStarted.RemoveDynamic(this, &UCoffeeMachineController::OnInputGrab);
|
|
PlayerController->OnCoffeeMakingAction_GrabRelease.RemoveDynamic(this, &UCoffeeMachineController::OnInputRelease);
|
|
}
|
|
}
|
|
|
|
void UCoffeeMachineController::SetCoffeeMakingStage(ECoffeeMachineMakingState NewStage)
|
|
{
|
|
CurrentCoffeeMakingStage = NewStage;
|
|
}
|
|
|
|
void UCoffeeMachineController::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
PlayerController = Cast<AFayePlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
|
|
}
|
|
|
|
void UCoffeeMachineController::PerformMouseHover()
|
|
{
|
|
float MouseX, MouseY;
|
|
if (!PlayerController->GetMousePosition(MouseX, MouseY)) return;
|
|
|
|
FVector WorldOrigin, WorldDirection;
|
|
if (!PlayerController->DeprojectScreenPositionToWorld(MouseX, MouseY, WorldOrigin, WorldDirection)) return;
|
|
|
|
FVector TraceEnd = WorldOrigin + (WorldDirection * 300.f);
|
|
|
|
TArray<FHitResult> HitResults;
|
|
FCollisionQueryParams Params;
|
|
Params.AddIgnoredComponent(CurrentSelectedBoxComponent);
|
|
const bool bHit = GetWorld()->LineTraceMultiByChannel(HitResults, WorldOrigin, TraceEnd, ECC_GameTraceChannel1, Params);
|
|
|
|
|
|
|
|
HoverBox(bHit? Cast<UHoverableBoxComponent>(HitResults[0].Component) : nullptr);
|
|
}
|
|
|
|
void UCoffeeMachineController::MoveHeldObject()
|
|
{
|
|
float MouseX, MouseY;
|
|
if (!PlayerController->GetMousePosition(MouseX, MouseY)) return;
|
|
|
|
FVector WorldOrigin, WorldDirection;
|
|
if (!PlayerController->DeprojectScreenPositionToWorld(MouseX, MouseY, WorldOrigin, WorldDirection)) return;
|
|
|
|
APlayerCameraManager* CameraManager = PlayerController->PlayerCameraManager;
|
|
FVector CameraForward = CameraManager->GetActorForwardVector();
|
|
FPlane MovementPlane(CurrentSelectedMeshComponent->GetComponentLocation(), CameraForward);
|
|
|
|
FVector IntersectPoint = FMath::RayPlaneIntersection(WorldOrigin, WorldDirection, MovementPlane);
|
|
|
|
switch (CurrentGrabbedObjectMovementMode)
|
|
{
|
|
case ECoffeeMachinePropMovementMode::PlaneYZ:
|
|
break;
|
|
case ECoffeeMachinePropMovementMode::ZOnly:
|
|
{
|
|
IntersectPoint.X = CurrentGrabbedObjectStartPos.X;
|
|
IntersectPoint.Y = CurrentGrabbedObjectStartPos.Y;
|
|
|
|
IntersectPoint.Z = FMath::Clamp(IntersectPoint.Z, CurrentGrabbedObjectStartPos.Z - 14.f, CurrentGrabbedObjectStartPos.Z);
|
|
|
|
// if (GEngine)
|
|
// {
|
|
// GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Red, FString::Printf(TEXT("Intersection point: %s"), *IntersectPoint.ToString()));
|
|
// }
|
|
break;
|
|
}
|
|
}
|
|
|
|
CurrentSelectedMeshComponent->SetWorldLocation(IntersectPoint);
|
|
}
|
|
|
|
void UCoffeeMachineController::HoverBox(UHoverableBoxComponent* InBox)
|
|
{
|
|
if (InBox == CurrentHoverableComponent)
|
|
{
|
|
if (CanHover(InBox))
|
|
return;
|
|
}
|
|
|
|
if (CurrentHoverableComponent)
|
|
{
|
|
CurrentHoverableComponent->OnUnhovered.Broadcast();
|
|
CurrentHoverableComponent = nullptr;
|
|
return;
|
|
}
|
|
|
|
if (CanHover(InBox))
|
|
{
|
|
CurrentHoverableComponent = InBox;
|
|
CurrentHoverableComponent->OnHovered.Broadcast();
|
|
}
|
|
}
|
|
|
|
bool UCoffeeMachineController::GrabObject(UHoverableBoxComponent* InBox)
|
|
{
|
|
if (CurrentCoffeeMakingStage != ECoffeeMachineMakingState::Start &&
|
|
CurrentCoffeeMakingStage != ECoffeeMachineMakingState::PortafilterPressing) return false;
|
|
|
|
if (InBox && InBox->GetAttachParent() && CanGrab(InBox))
|
|
{
|
|
CurrentSelectedBoxComponent = InBox;
|
|
CurrentSelectedMeshComponent = Cast<UStaticMeshComponent>(InBox->GetAttachParent());
|
|
CurrentSelectedBoxComponent->OnSelected.Broadcast();
|
|
|
|
CurrentGrabbedObjectStartPos = CurrentSelectedMeshComponent->GetComponentLocation();
|
|
|
|
if (InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::Start)
|
|
{
|
|
SetCoffeeMakingStage(ECoffeeMachineMakingState::PortafilterDragging);
|
|
CurrentGrabbedObjectMovementMode = ECoffeeMachinePropMovementMode::PlaneYZ;
|
|
}
|
|
else if (InBox->ComponentHasTag(OBJECT_TYPE_TAMPER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::PortafilterPressing)
|
|
{
|
|
CurrentGrabbedObjectMovementMode = ECoffeeMachinePropMovementMode::ZOnly;
|
|
CurrentGrabbedObjectStartPos = TamperLiftStartingPos;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UCoffeeMachineController::ReleaseObject()
|
|
{
|
|
OnObjectReleased.Broadcast();
|
|
|
|
if (CurrentSelectedBoxComponent)
|
|
{
|
|
CurrentSelectedBoxComponent->OnUnselected.Broadcast();
|
|
}
|
|
|
|
CurrentSelectedMeshComponent = nullptr;
|
|
CurrentSelectedBoxComponent = nullptr;
|
|
}
|
|
|
|
bool UCoffeeMachineController::CanGrab(const UHoverableBoxComponent* InBox) const
|
|
{
|
|
return InBox &&
|
|
((InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::Start) ||
|
|
(InBox->ComponentHasTag(OBJECT_TYPE_TAMPER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::PortafilterPressing));
|
|
}
|
|
|
|
bool UCoffeeMachineController::CanHover(const UHoverableBoxComponent* InBox) const
|
|
{
|
|
if (!InBox) return false;
|
|
|
|
switch (CurrentCoffeeMakingStage)
|
|
{
|
|
case ECoffeeMachineMakingState::Start:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && !InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::PortafilterDragging:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_GRINDER)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::PortafilterFilling:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_GRINDER_BUTTON)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::PortafilterPressing:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_TAMPER)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::CoffeeLoaded:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON) && !InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
|
|
|
// Cannot press button if cup not placed
|
|
if (InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON) && !bCupPlaced) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::CoffeeFilling:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::CoffeeReady:
|
|
{
|
|
if (!InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
|
|
|
break;
|
|
}
|
|
case ECoffeeMachineMakingState::WaitingAction:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void UCoffeeMachineController::OnInputGrab()
|
|
{
|
|
if (!GrabObject(CurrentHoverableComponent))
|
|
{
|
|
OnObjectClicked.Broadcast();
|
|
}
|
|
}
|
|
|
|
void UCoffeeMachineController::OnInputRelease()
|
|
{
|
|
ReleaseObject();
|
|
}
|
|
|
|
|
|
|
|
|