Files
UnrealEngineUWP/Engine/Plugins/Runtime/GameplayInteractions/Source/GameplayInteractionsModule/Private/ContextualAnimStateTreeTask.cpp
Yoan StAmant 726e6251f3 GameplayInteractions plugin
- base class for StateTree tasks (GameplayInteractionStateTreeTask)
- GameplayInteractions StateTree schema
   - supports StateTree common Tasks, Evaluators and Conditions + GameplayInteraction Tasks
   - requires two named external data items (Interactable actor and SmartObject claimed handle)
- GameplayInteraction specific SmartObjectBehaviorDefinition to execute a StateTree
- First pass of ContextualAnimStateTreeTask to play a scene from a ContextualAnimation scene asset
#rnx
#rb mikko.mononen
#preflight 627510442e58cb727d38e384

[CL 20074106 by Yoan StAmant in ue5-main branch]
2022-05-06 08:23:48 -04:00

95 lines
4.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ContextualAnimStateTreeTask.h"
#include "ContextualAnimManager.h"
#include "ContextualAnimSceneAsset.h"
#include "ContextualAnimTypes.h"
#include "StateTreeExecutionContext.h"
#include "Animation/AnimMontage.h"
#include "GameFramework/Character.h"
#include "StateTreeLinker.h"
struct FDataRegistryLookup;
struct FDataRegistryId;
struct FMassEntityHandle;
bool FContextualAnimStateTreeTask::Link(FStateTreeLinker& Linker)
{
Linker.LinkInstanceDataProperty(ContextualAnimAssetHandle, STATETREE_INSTANCEDATA_PROPERTY(InstanceDataType, ContextualAnimAsset));
Linker.LinkInstanceDataProperty(InteractableObjectHandle, STATETREE_INSTANCEDATA_PROPERTY(InstanceDataType, InteractableObject));
Linker.LinkInstanceDataProperty(DurationHandle, STATETREE_INSTANCEDATA_PROPERTY(InstanceDataType, Duration));
Linker.LinkInstanceDataProperty(ComputedDurationHandle, STATETREE_INSTANCEDATA_PROPERTY(InstanceDataType, ComputedDuration));
Linker.LinkInstanceDataProperty(TimeHandle, STATETREE_INSTANCEDATA_PROPERTY(InstanceDataType, Time));
Linker.LinkExternalData(InteractorActorHandle);
return true;
}
EStateTreeRunStatus FContextualAnimStateTreeTask::EnterState(FStateTreeExecutionContext& Context, const EStateTreeStateChangeType ChangeType, const FStateTreeTransitionResult& Transition) const
{
float& Time = Context.GetInstanceData(TimeHandle);
Time = 0.f;
float& ComputedDuration = Context.GetInstanceData(ComputedDurationHandle);
ComputedDuration = Context.GetInstanceData(DurationHandle);
AActor* InteractableObject = Context.GetInstanceData(InteractableObjectHandle);
AActor* Interactor = Context.GetExternalDataPtr(InteractorActorHandle);
const UContextualAnimSceneAsset* ContextualAnimAsset = Context.GetInstanceData(ContextualAnimAssetHandle);
FContextualAnimQueryResult ContextualAnimQueryResult;
// If we have a target use that to find the best contextual anim to play
if (ContextualAnimAsset != nullptr && InteractableObject != nullptr && Interactor != nullptr)
{
const FTransform& InteractableObjectTransform = InteractableObject->GetTransform();
const FTransform& InteractorTransform = Interactor->GetTransform();
FContextualAnimQueryParams ContextualAnimQueryParams;
ContextualAnimQueryParams.bComplexQuery = true;
ContextualAnimQueryParams.bFindAnimStartTime = true;
ContextualAnimQueryParams.QueryTransform = InteractorTransform;
// If we don't find a good sync point, grab the closest one.
if (!ContextualAnimAsset->Query(InteractorRole, ContextualAnimQueryResult, ContextualAnimQueryParams, InteractableObjectTransform))
{
ContextualAnimQueryParams.bComplexQuery = false;
ContextualAnimAsset->Query(InteractorRole, ContextualAnimQueryResult, ContextualAnimQueryParams, InteractableObjectTransform);
}
}
const UAnimMontage* Montage = ContextualAnimQueryResult.Animation.Get();
if (Montage != nullptr)
{
UContextualAnimManager* ContextualAnimManager = UContextualAnimManager::Get(Context.GetWorld());
FContextualAnimStartSceneParams StartSceneParams;
StartSceneParams.RoleToActorMap.Add(InteractorRole, Interactor);
StartSceneParams.RoleToActorMap.Add(InteractableObjectRole, InteractableObject);
UContextualAnimSceneInstance* SceneInstance = ContextualAnimManager->TryStartScene(*ContextualAnimAsset, StartSceneParams);
if (SceneInstance == nullptr)
{
return EStateTreeRunStatus::Failed;
}
// @todo: listen anim completed event
}
if (Montage == nullptr)
{
return EStateTreeRunStatus::Failed;
}
// Grab the task duration from the montage.
ComputedDuration = Montage->GetPlayLength();
return EStateTreeRunStatus::Running;
}
EStateTreeRunStatus FContextualAnimStateTreeTask::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const
{
const float ComputedDuration = Context.GetInstanceData(ComputedDurationHandle);
float& Time = Context.GetInstanceData(TimeHandle);
Time += DeltaTime;
return ComputedDuration <= 0.0f ? EStateTreeRunStatus::Running : (Time < ComputedDuration ? EStateTreeRunStatus::Running : EStateTreeRunStatus::Succeeded);
}