2025-05-13 15:21:02 +07:00
|
|
|
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "Data/OLSAnimationData.h"
|
|
|
|
|
|
|
|
|
|
#include "Data/OLSEnumLibrary.h"
|
|
|
|
|
|
2025-08-05 12:37:14 +07:00
|
|
|
void FOLSMovementDirectionThresholds::UpdateThresholds(const float fl, const float fr, const float bl, const float br,
|
|
|
|
|
FOLSMovementDirectionThresholds& outMovementThresholds)
|
|
|
|
|
{
|
|
|
|
|
outMovementThresholds.FL = fl;
|
|
|
|
|
outMovementThresholds.FR = fr;
|
|
|
|
|
outMovementThresholds.BL = bl;
|
|
|
|
|
outMovementThresholds.BR = br;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-01 12:43:20 +07:00
|
|
|
void FOLSFeetPositionData::DetermineIfRightFootIsFront()
|
|
|
|
|
{
|
|
|
|
|
const FVector rightFootLocal = RootTransform.InverseTransformPosition(RightFootLocation);
|
|
|
|
|
const FVector leftFootLocal = RootTransform.InverseTransformPosition(LeftFootLocation);
|
|
|
|
|
|
|
|
|
|
bIsRightFootFront = rightFootLocal.X > leftFootLocal.X;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-29 10:17:08 +07:00
|
|
|
bool FOLSFeetPositionData::IsRightFootFront() const
|
2025-08-01 12:43:20 +07:00
|
|
|
{
|
|
|
|
|
const FVector rightFootLocal = RootTransform.InverseTransformPosition(RightFootLocation);
|
|
|
|
|
const FVector leftFootLocal = RootTransform.InverseTransformPosition(LeftFootLocation);
|
|
|
|
|
|
|
|
|
|
return rightFootLocal.X > leftFootLocal.X;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 15:21:02 +07:00
|
|
|
UAnimSequence* FOLSTurnInPlaceAnimSet::GetTurnInPlaceAnimationByDirection(const float direction) const
|
|
|
|
|
{
|
|
|
|
|
if (FMath::Abs(direction) < 130.f)
|
|
|
|
|
{
|
|
|
|
|
return (direction > 0) ? TurnInPlace_90_R : TurnInPlace_90_L;
|
|
|
|
|
}
|
|
|
|
|
return (direction > 0) ? TurnInPlace_180_R : TurnInPlace_180_L;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FOLSIdleAnimSet::HasAnyIdleBreaks() const
|
|
|
|
|
{
|
|
|
|
|
return !IdleBreaks.IsEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAnimSet::GetIdleAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return Idle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAnimSet::GetRandomIdleBreakAnimation() const
|
|
|
|
|
{
|
|
|
|
|
if (!HasAnyIdleBreaks())
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int32 idleBreaksNum = IdleBreaks.Num();
|
|
|
|
|
return IdleBreaks[FMath::RandRange(0, idleBreaksNum - 1)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAndTurnInPlaceAnimSet::GetIdleExitAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAnimSet.IdleExit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAndTurnInPlaceAnimSet::GetIdleAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAnimSet.GetIdleAnimation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAndTurnInPlaceAnimSet::GetRandomIdleBreakAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAnimSet.GetRandomIdleBreakAnimation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSIdleAndTurnInPlaceAnimSet::GetTurnInPlaceAnimation(const float direction) const
|
|
|
|
|
{
|
|
|
|
|
return TurnInPlaceAnimSet.GetTurnInPlaceAnimationByDirection(direction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FOLSIdleAndTurnInPlaceAnimSet::CanPlayIdleBreakAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAnimSet.HasAnyIdleBreaks();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 17:06:58 +07:00
|
|
|
class UAnimSequence* FOLSMovementAnimSet_FeetPosition::GetForwardLeftOrRightFoot(const bool isRightFootFarFromTarget) const
|
2025-05-13 15:21:02 +07:00
|
|
|
{
|
2025-07-31 17:06:58 +07:00
|
|
|
return (isRightFootFarFromTarget ? RightFoot : LeftFoot);
|
2025-05-13 15:21:02 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-29 10:17:08 +07:00
|
|
|
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetForwardLeftOrRightFoot(const bool isRightFootFront) const
|
2025-05-13 15:21:02 +07:00
|
|
|
{
|
2025-08-29 10:17:08 +07:00
|
|
|
return Forward.GetForwardLeftOrRightFoot(isRightFootFront);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetForward90LeftOrRightByAngle(const float angle) const
|
|
|
|
|
{
|
|
|
|
|
return (angle > 0.f) ? Forward90R : Forward90L;
|
2025-05-13 15:21:02 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetForward180LeftOrRightByAngle(const float angle) const
|
|
|
|
|
{
|
2025-07-31 17:06:58 +07:00
|
|
|
return (angle > 0.f) ? Forward180R : Forward180L;
|
2025-05-13 15:21:02 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-29 10:17:08 +07:00
|
|
|
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetMovementAnimationByAngle(const float angle, const bool isRightFootFront) const
|
2025-05-13 15:21:02 +07:00
|
|
|
{
|
|
|
|
|
TObjectPtr<UAnimSequence> result = nullptr;
|
2025-08-29 10:17:08 +07:00
|
|
|
|
|
|
|
|
const float absAngle = FMath::Abs(angle);
|
2025-05-13 15:21:02 +07:00
|
|
|
|
2025-08-29 10:17:08 +07:00
|
|
|
if (angle >= -45.f && angle <= 45.f)
|
|
|
|
|
{
|
|
|
|
|
result = GetForwardLeftOrRightFoot(isRightFootFront);
|
|
|
|
|
}
|
|
|
|
|
else if (absAngle > 45.f && absAngle <= 135.f)
|
|
|
|
|
{
|
|
|
|
|
result = GetForward90LeftOrRightByAngle(angle);
|
|
|
|
|
}
|
|
|
|
|
else if (absAngle > 135.f && absAngle <= 180.f)
|
2025-05-13 15:21:02 +07:00
|
|
|
{
|
|
|
|
|
result = GetForward180LeftOrRightByAngle(angle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 17:06:58 +07:00
|
|
|
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_Pivot::GetLeftOrRightByAngle(const float angle,
|
|
|
|
|
const bool isRightFootFarFromTarget) const
|
2025-07-25 11:59:13 +07:00
|
|
|
{
|
2025-07-31 17:06:58 +07:00
|
|
|
return (angle > 0.f
|
|
|
|
|
? Pivot180R.GetForwardLeftOrRightFoot(isRightFootFarFromTarget)
|
|
|
|
|
: Pivot180L.GetForwardLeftOrRightFoot(isRightFootFarFromTarget));
|
2025-07-25 11:59:13 +07:00
|
|
|
}
|
|
|
|
|
|
2025-07-31 17:06:58 +07:00
|
|
|
UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StopCycle::GetLeftOrRightAnim(const bool isRightFootPlanted) const
|
2025-05-13 15:21:02 +07:00
|
|
|
{
|
2025-07-31 17:06:58 +07:00
|
|
|
return Stop.GetForwardLeftOrRightFoot(isRightFootPlanted);
|
2025-05-13 15:21:02 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-05 10:24:11 +07:00
|
|
|
class UAnimSequence* FOLSMovementAnimSet_CameraFacing_Directional_Cycle::GetMovementAnimByCardinalDirection(
|
|
|
|
|
const EOLSMovementDirection& direction) const
|
|
|
|
|
{
|
|
|
|
|
TObjectPtr<UAnimSequence> result = nullptr;
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case EOLSMovementDirection::EForward:
|
|
|
|
|
result = Forward;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::EBackward:
|
|
|
|
|
result = Backward;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ELeftLeft:
|
|
|
|
|
result = LeftLeft;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ELeftRight:
|
|
|
|
|
result = LeftRight;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ERightRight:
|
|
|
|
|
result = RightRight;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ERightLeft:
|
|
|
|
|
result = RightLeft;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 15:21:02 +07:00
|
|
|
void FOLSGaitAnimSet::GetPlayRateByLocomotionState(const EOLSLocomotionStatePlayRate& state, FVector2D& outPlayRate) const
|
|
|
|
|
{
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case EOLSLocomotionStatePlayRate::EStart:
|
|
|
|
|
outPlayRate = PlayRate_Start;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSLocomotionStatePlayRate::ECycle:
|
|
|
|
|
outPlayRate = PlayRate_Cycle;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSLocomotionStatePlayRate::EPivot:
|
|
|
|
|
outPlayRate = PlayRate_Pivot;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-05 10:24:11 +07:00
|
|
|
void FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimSetByCardinalDirection(
|
|
|
|
|
const EOLSMovementDirection& direction,
|
|
|
|
|
FOLSMovementAnimSet_FeetPosition& outAnimSet) const
|
2025-07-31 17:06:58 +07:00
|
|
|
{
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
2025-08-05 10:24:11 +07:00
|
|
|
case EOLSMovementDirection::EForward:
|
2025-07-31 17:06:58 +07:00
|
|
|
outAnimSet = Forward;
|
|
|
|
|
break;
|
2025-08-05 10:24:11 +07:00
|
|
|
case EOLSMovementDirection::EBackward:
|
2025-07-31 17:06:58 +07:00
|
|
|
outAnimSet = Backward;
|
|
|
|
|
break;
|
2025-08-05 10:24:11 +07:00
|
|
|
case EOLSMovementDirection::ELeftLeft:
|
|
|
|
|
outAnimSet = LeftLeft;
|
2025-07-31 17:06:58 +07:00
|
|
|
break;
|
2025-08-05 10:24:11 +07:00
|
|
|
case EOLSMovementDirection::ELeftRight:
|
|
|
|
|
outAnimSet = LeftRight;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ERightRight:
|
|
|
|
|
outAnimSet = RightRight;
|
|
|
|
|
break;
|
|
|
|
|
case EOLSMovementDirection::ERightLeft:
|
|
|
|
|
outAnimSet = RightLeft;
|
2025-07-31 17:06:58 +07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-05 10:24:11 +07:00
|
|
|
UAnimSequence* FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimByCardinalDirection(
|
|
|
|
|
const EOLSMovementDirection& direction,
|
|
|
|
|
const bool isRightFootFarFromTarget) const
|
2025-07-31 17:06:58 +07:00
|
|
|
{
|
|
|
|
|
FOLSMovementAnimSet_FeetPosition animSet;
|
|
|
|
|
GetMovementAnimSetByCardinalDirection(direction, animSet);
|
|
|
|
|
|
|
|
|
|
return animSet.GetForwardLeftOrRightFoot(isRightFootFarFromTarget);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-13 15:21:02 +07:00
|
|
|
UAnimSequence* FOLSStanceAnimSets::GetIdleAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAndTurnInPlaceAnimSet.GetIdleAnimation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSStanceAnimSets::GetIdleExitAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAndTurnInPlaceAnimSet.GetIdleExitAnimation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSStanceAnimSets::GetRandomIdleBreakAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return IdleAndTurnInPlaceAnimSet.GetRandomIdleBreakAnimation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UAnimSequence* FOLSStanceAnimSets::GetTurnInPlaceAnimation(const float direction) const
|
|
|
|
|
{
|
|
|
|
|
return IdleAndTurnInPlaceAnimSet.GetTurnInPlaceAnimation(direction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FOLSStanceAnimSets::CanPlayIdleBreakAnimation() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FOLSGaitAnimSets& FOLSStanceAnimSets::GetGaitAnimSetByGait(const EOLSGait& gait) const
|
|
|
|
|
{
|
|
|
|
|
return WalkAnimSets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FOLSGaitAnimSets& FOLSStanceAnimSets_Standing::GetGaitAnimSetByGait(const EOLSGait& gait) const
|
|
|
|
|
{
|
|
|
|
|
switch (gait)
|
|
|
|
|
{
|
|
|
|
|
case EOLSGait::EWalk:
|
|
|
|
|
return WalkAnimSets;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EOLSGait::EJog:
|
|
|
|
|
return JogAnimSets;
|
|
|
|
|
|
|
|
|
|
case EOLSGait::ESprint:
|
|
|
|
|
return SprintAnimSets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FOLSStanceAnimSets::GetGaitAnimSetByGait(gait);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOLSGaitAnimSets FOLSGaitAnimSets::EmptyAnimSet = FOLSGaitAnimSets();
|
|
|
|
|
|