Files
UnrealEngineUWP/Engine/Plugins/Runtime/GameplayStateTree/Source/GameplayStateTreeModule/Private/Tasks/StateTreeMoveToTask.cpp
mikko mononen ef148ecd80 StateTree: StateTree UI spring clean.
- Added icons and icon colors for ST nodes
- Implemented icons for some common ST nodes
- Small update to ST logic icons
- Added icons to the task list in State treeview row, adjusted task list BG color to make icons visible
- Fixed ST editor tabs icons and names (e.g. there were two tabs that had the same label)
- Moved ST node picker to separate class
- Moved category array customization to common helper function
- Added node icons to the ST node picker
- Add node button is not node selector too (simila to Niagara)
- Consolidated the add button style across all lists
- Cleaned up the node customization
  - Moved type selector, debug, and property controls into one menu at right
  - The combined menu can be also summoned using right click
  - Renaming now has to be triggered via the menu
  - Replacing node happens via menu
  - Most of the row was left "clickable" to later use it for selection
  - Improved the visualization and controls for the expression indentation
- Cleaned up state customization
  - Moved parameters to own category (similar to the tree params)
  - Moved event to the enter conditions category
- Cleaned up transition customization
  - Improved the transition display
  - Consolidated add button styles

#jira UE-180608
#rb Juan.Portillo, Mieszko.Zielinski

[CL 33030431 by mikko mononen in ue5-main branch]
2024-04-17 03:01:36 -04:00

157 lines
5.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Tasks/StateTreeMoveToTask.h"
#include "AIController.h"
#include "Navigation/PathFollowingComponent.h"
#include "StateTreeExecutionContext.h"
#include "StateTreeLinker.h"
#include "Tasks/AITask_MoveTo.h"
#include "VisualLogger/VisualLogger.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(StateTreeMoveToTask)
#define LOCTEXT_NAMESPACE "GameplayStateTree"
EStateTreeRunStatus FStateTreeMoveToTask::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const
{
FInstanceDataType& InstanceData = Context.GetInstanceData(*this);
if (!InstanceData.AIController)
{
UE_VLOG(Context.GetOwner(), LogStateTree, Error, TEXT("FStateTreeMoveToTask failed since AIController is missing."));
return EStateTreeRunStatus::Failed;
}
InstanceData.TaskOwner = TScriptInterface<IGameplayTaskOwnerInterface>(InstanceData.AIController->FindComponentByInterface(UGameplayTaskOwnerInterface::StaticClass()));
if (!InstanceData.TaskOwner)
{
InstanceData.TaskOwner = InstanceData.AIController;
}
return PerformMoveTask(Context, *InstanceData.AIController);
}
EStateTreeRunStatus FStateTreeMoveToTask::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const
{
FInstanceDataType& InstanceData = Context.GetInstanceData(*this);
if (InstanceData.MoveToTask)
{
if (InstanceData.MoveToTask->GetState() == EGameplayTaskState::Finished)
{
return InstanceData.MoveToTask->WasMoveSuccessful() ? EStateTreeRunStatus::Succeeded : EStateTreeRunStatus::Failed;
}
if (InstanceData.bTrackMovingGoal && !InstanceData.TargetActor)
{
const FVector CurrentDestination = InstanceData.MoveToTask->GetMoveRequestRef().GetDestination();
if (FVector::DistSquared(CurrentDestination, InstanceData.Destination) > (InstanceData.DestinationMoveTolerance * InstanceData.DestinationMoveTolerance))
{
UE_VLOG(Context.GetOwner(), LogStateTree, Log, TEXT("FStateTreeMoveToTask destination has moved enough. Restarting task."));
return PerformMoveTask(Context, *InstanceData.AIController);
}
}
return EStateTreeRunStatus::Running;
}
return EStateTreeRunStatus::Failed;
}
void FStateTreeMoveToTask::ExitState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const
{
FInstanceDataType& InstanceData = Context.GetInstanceData(*this);
if (InstanceData.MoveToTask && InstanceData.MoveToTask->GetState() != EGameplayTaskState::Finished)
{
UE_VLOG(Context.GetOwner(), LogStateTree, Log, TEXT("FStateTreeMoveToTask aborting move to because state finished."));
InstanceData.MoveToTask->ExternalCancel();
}
}
UAITask_MoveTo* FStateTreeMoveToTask::PrepareMoveToTask(FStateTreeExecutionContext& Context, AAIController& Controller, UAITask_MoveTo* ExistingTask, FAIMoveRequest& MoveRequest) const
{
FInstanceDataType& InstanceData = Context.GetInstanceData(*this);
UAITask_MoveTo* MoveTask = ExistingTask ? ExistingTask : UAITask::NewAITask<UAITask_MoveTo>(Controller, *InstanceData.TaskOwner);
if (MoveTask)
{
MoveTask->SetUp(&Controller, MoveRequest);
}
return MoveTask;
}
EStateTreeRunStatus FStateTreeMoveToTask::PerformMoveTask(FStateTreeExecutionContext& Context, AAIController& Controller) const
{
FInstanceDataType& InstanceData = Context.GetInstanceData(*this);
FAIMoveRequest MoveReq;
MoveReq.SetNavigationFilter(InstanceData.FilterClass ? InstanceData.FilterClass : Controller.GetDefaultNavigationFilterClass())
.SetAllowPartialPath(InstanceData.bAllowPartialPath)
.SetAcceptanceRadius(InstanceData.AcceptableRadius)
.SetCanStrafe(InstanceData.bAllowStrafe)
.SetReachTestIncludesAgentRadius(InstanceData.bReachTestIncludesAgentRadius)
.SetReachTestIncludesGoalRadius(InstanceData.bReachTestIncludesGoalRadius)
.SetRequireNavigableEndLocation(InstanceData.bRequireNavigableEndLocation)
.SetProjectGoalLocation(InstanceData.bProjectGoalLocation)
.SetUsePathfinding(true);
if (InstanceData.TargetActor)
{
if (InstanceData.bTrackMovingGoal)
{
MoveReq.SetGoalActor(InstanceData.TargetActor);
}
else
{
MoveReq.SetGoalLocation(InstanceData.TargetActor->GetActorLocation());
}
}
else
{
MoveReq.SetGoalLocation(InstanceData.Destination);
}
if (MoveReq.IsValid())
{
InstanceData.MoveToTask = PrepareMoveToTask(Context, Controller, InstanceData.MoveToTask, MoveReq);
if (InstanceData.MoveToTask)
{
if (InstanceData.MoveToTask->IsActive())
{
InstanceData.MoveToTask->ConditionalPerformMove();
}
else
{
InstanceData.MoveToTask->ReadyForActivation();
}
if (InstanceData.MoveToTask->GetState() == EGameplayTaskState::Finished)
{
return InstanceData.MoveToTask->WasMoveSuccessful() ? EStateTreeRunStatus::Succeeded : EStateTreeRunStatus::Failed;
}
return EStateTreeRunStatus::Running;
}
}
UE_VLOG(Context.GetOwner(), LogStateTree, Error, TEXT("FStateTreeMoveToTask failed because it doesn't have a destination."));
return EStateTreeRunStatus::Failed;
}
#if WITH_EDITOR
FText FStateTreeMoveToTask::GetDescription(const FGuid& ID, FStateTreeDataView InstanceDataView, const IStateTreeBindingLookup& BindingLookup, EStateTreeNodeFormatting Formatting) const
{
const FInstanceDataType* InstanceData = InstanceDataView.GetPtr<FInstanceDataType>();
check(InstanceData);
FText TargetValue = BindingLookup.GetBindingSourceDisplayName(FStateTreePropertyPath(ID, GET_MEMBER_NAME_CHECKED(FInstanceDataType, TargetActor)), Formatting);
if (TargetValue.IsEmpty())
{
TargetValue = BindingLookup.GetBindingSourceDisplayName(FStateTreePropertyPath(ID, GET_MEMBER_NAME_CHECKED(FInstanceDataType, Destination)), Formatting);
}
if (Formatting == EStateTreeNodeFormatting::RichText)
{
return FText::Format(LOCTEXT("MoveToRich", "<b>Move To</> {0}"), TargetValue);
}
return FText::Format(LOCTEXT("MoveTo", "Move To {0}"), TargetValue);
}
#endif // WITH_EDITOR
#undef LOCTEXT_NAMESPACE