Refactored camera direction

This commit is contained in:
mrlee207 2025-08-05 10:24:11 +07:00
parent 43c3d02f0a
commit c90b733a3d
13 changed files with 345 additions and 180 deletions

View File

@ -244,7 +244,7 @@ void UOLSBaseLayerAnimInstance::NativeThreadSafeUpdateVelocityData(const float d
const bool wasMovingLastUpdate = !LocalVelocity2D.IsNearlyZero(1.e-4f); const bool wasMovingLastUpdate = !LocalVelocity2D.IsNearlyZero(1.e-4f);
if (wasMovingLastUpdate) if (wasMovingLastUpdate)
{ {
StopLocalVelocityCardinalDirection = LocalVelocityDirection; StopLocalVelocityDirection = LocalVelocityDirection;
} }
WorldVelocity = OwningPawnVelocity; WorldVelocity = OwningPawnVelocity;
@ -255,16 +255,13 @@ void UOLSBaseLayerAnimInstance::NativeThreadSafeUpdateVelocityData(const float d
LocalVelocityDirectionAngle = UKismetAnimationLibrary::CalculateDirection(worldVelocity2D, WorldRotation); LocalVelocityDirectionAngle = UKismetAnimationLibrary::CalculateDirection(worldVelocity2D, WorldRotation);
LocalVelocityDirectionAngleWithOffset = LocalVelocityDirectionAngle - RootYawOffset; LocalVelocityDirectionAngleWithOffset = LocalVelocityDirectionAngle - RootYawOffset;
LocalVelocityDirection = UOLSLocomotionBPLibrary::SelectCardinalDirectionFromAngle(LocalVelocityDirectionAngleWithOffset, GetMovementDirectionThresholds(LocalVelocityDirection, MovementDirectionThresholds);
CardinalDirectionDeadZone,
LocalVelocityDirection,
wasMovingLastUpdate);
LocalVelocityDirectionNoOffset = UOLSLocomotionBPLibrary::SelectCardinalDirectionFromAngle( LocalVelocityDirection = UOLSLocomotionBPLibrary::SelectMovementDirectionFromAngle(
LocalVelocityDirectionAngle, LocalVelocityDirectionAngleWithOffset, RotationMode, Gait, MovementDirectionBias, MovementDirectionThresholds);
CardinalDirectionDeadZone,
LocalVelocityDirection, LocalVelocityDirectionNoOffset = UOLSLocomotionBPLibrary::SelectMovementDirectionFromAngle(
wasMovingLastUpdate); LocalVelocityDirectionAngle, RotationMode, Gait, MovementDirectionBias, MovementDirectionThresholds);
bHasVelocity = (LocalVelocity2D.SizeSquared2D() > KINDA_SMALL_NUMBER); bHasVelocity = (LocalVelocity2D.SizeSquared2D() > KINDA_SMALL_NUMBER);
@ -281,14 +278,21 @@ void UOLSBaseLayerAnimInstance::NativeThreadSafeUpdateAccelerationData(const flo
bHasAcceleration = (LocalAcceleration2D.SizeSquared2D() > KINDA_SMALL_NUMBER); bHasAcceleration = (LocalAcceleration2D.SizeSquared2D() > KINDA_SMALL_NUMBER);
PivotDirection2D = PivotDirection2D =
UKismetMathLibrary::Normal(UKismetMathLibrary::VLerp(PivotDirection2D, UKismetMathLibrary::Normal(worldAcceleration2D), .5f)); UKismetMathLibrary::Normal(
UKismetMathLibrary::VLerp(PivotDirection2D, UKismetMathLibrary::Normal(worldAcceleration2D), .5f));
GetMovementDirectionThresholds(CardinalDirectionFromAcceleration, MovementDirectionThresholds);
CardinalDirectionFromAcceleration = (IsLookingOrAimingDirection() CardinalDirectionFromAcceleration = (IsLookingOrAimingDirection()
? UOLSLocomotionBPLibrary::GetOppositeCardinalDirectional( ? UOLSLocomotionBPLibrary::GetOppositeMovementDirection(
UOLSLocomotionBPLibrary::SelectCardinalDirectionFromAngle( UOLSLocomotionBPLibrary::SelectMovementDirectionFromAngle(
UKismetAnimationLibrary::CalculateDirection(PivotDirection2D, WorldRotation), UKismetAnimationLibrary::CalculateDirection(
CardinalDirectionDeadZone, EOLSCardinalDirection::EForward)) PivotDirection2D, WorldRotation),
: EOLSCardinalDirection::EBackward); RotationMode, Gait,
MovementDirectionBias,
MovementDirectionThresholds),
MovementDirectionBias)
: EOLSMovementDirection::EBackward);
if (HasAcceleration()) if (HasAcceleration())
{ {
@ -498,10 +502,16 @@ bool UOLSBaseLayerAnimInstance::ShouldDistanceMatchStop() const
bool UOLSBaseLayerAnimInstance::IsMovingPerpendicularToInitialPivot() const bool UOLSBaseLayerAnimInstance::IsMovingPerpendicularToInitialPivot() const
{ {
const bool isPivotFwdOrBwd = (PivotInitialDirection == EOLSCardinalDirection::EForward || PivotInitialDirection == EOLSCardinalDirection::EBackward); const bool isPivotFwdOrBwd = (PivotInitialDirection == EOLSMovementDirection::EForward || PivotInitialDirection ==
const bool isVelocityFwdOrBwd = (LocalVelocityDirection == EOLSCardinalDirection::EForward || LocalVelocityDirection == EOLSCardinalDirection::EBackward); EOLSMovementDirection::EBackward);
const bool isPivotLeftOrRight = (PivotInitialDirection == EOLSCardinalDirection::ELeft || PivotInitialDirection == EOLSCardinalDirection::ERight); const bool isVelocityFwdOrBwd = (LocalVelocityDirection == EOLSMovementDirection::EForward || LocalVelocityDirection
const bool isVelocityLeftOrRight = (LocalVelocityDirection == EOLSCardinalDirection::ELeft || LocalVelocityDirection == EOLSCardinalDirection::ERight); == EOLSMovementDirection::EBackward);
const bool isPivotLeftOrRight = (PivotInitialDirection == EOLSMovementDirection::ELeftLeft || PivotInitialDirection
== EOLSMovementDirection::ELeftRight || PivotInitialDirection == EOLSMovementDirection::ERightLeft ||
PivotInitialDirection == EOLSMovementDirection::ERightRight);
const bool isVelocityLeftOrRight = (LocalVelocityDirection == EOLSMovementDirection::ELeftLeft ||
LocalVelocityDirection == EOLSMovementDirection::ELeftRight || LocalVelocityDirection ==
EOLSMovementDirection::ERightLeft || LocalVelocityDirection == EOLSMovementDirection::ERightRight);
return (isPivotFwdOrBwd && !isVelocityFwdOrBwd) || (isPivotLeftOrRight && !isVelocityLeftOrRight); return (isPivotFwdOrBwd && !isVelocityFwdOrBwd) || (isPivotLeftOrRight && !isVelocityLeftOrRight);
} }
@ -611,3 +621,45 @@ UOLSLocomotionComponent* UOLSBaseLayerAnimInstance::ThreadSafeGetLocomotionCompo
{ {
return LocomotionComponent; return LocomotionComponent;
} }
void UOLSBaseLayerAnimInstance::GetMovementDirectionThresholds(const EOLSMovementDirection& movementDirection, FOLSMovementDirectionThresholds& outMovementThresholds)
{
if (movementDirection == EOLSMovementDirection::EForward || movementDirection == EOLSMovementDirection::EBackward)
{
outMovementThresholds.FL = -60.f;
outMovementThresholds.FR = 60.f;
outMovementThresholds.BL = -120.f;
outMovementThresholds.BR = 120.f;
return;
}
if (movementDirection == EOLSMovementDirection::ELeftLeft || movementDirection ==
EOLSMovementDirection::ELeftRight || movementDirection == EOLSMovementDirection::ERightLeft ||
movementDirection == EOLSMovementDirection::ERightRight)
{
if (bIsPivoting)
{
outMovementThresholds.FL = -60.f;
outMovementThresholds.FR = 60.f;
outMovementThresholds.BL = -120.f;
outMovementThresholds.BR = 120.f;
}
else
{
if (bIsLooping && IsAimingDirection())
{
outMovementThresholds.FL = -60.f;
outMovementThresholds.FR = 60.f;
outMovementThresholds.BL = -140.f;
outMovementThresholds.BR = 140.f;
}
else
{
outMovementThresholds.FL = -40.f;
outMovementThresholds.FR = 40.f;
outMovementThresholds.BL = -120.f;
outMovementThresholds.BR = 120.f;
}
}
}
}

View File

@ -131,13 +131,12 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectTurnInPlaceAnimation(
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStartCycleAnimation(const bool isCrouching, UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStartCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const const float angle) const
{ {
if (isAiming) if (isAiming)
{ {
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.GetStartCycleFromHipDirection(hipDirection). return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.StartCycle.
GetMovementAnimByCardinalDirection( GetMovementAnimByCardinalDirection(
velocityDirection, FeetPositionData.IsRightFootIsFront()); velocityDirection, FeetPositionData.IsRightFootIsFront());
} }
@ -150,14 +149,12 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStartCycleAnimation(const
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectCycleAnimation(const bool isCrouching, UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection) const
const EOLSHipDirection hipDirection) const
{ {
if (isAiming) if (isAiming)
{ {
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.GetCycleFromHipDirection(hipDirection). return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.Cycle.GetMovementAnimByCardinalDirection(
GetMovementAnimByCardinalDirection( velocityDirection);
velocityDirection, FeetPositionData.IsRightFootIsFront());
} }
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Cycle; return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_ForwardFacing.Cycle;
@ -166,14 +163,12 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectCycleAnimation(const bool
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectPivotAnimation(const bool isCrouching, UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectPivotAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const const float angle) const
{ {
if (isAiming) if (isAiming)
{ {
return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.GetPivotFromHipDirection(hipDirection). return GetGaitAnimSets(isCrouching, gait).GaitAnimSet_CameraFacing.Pivot.GetMovementAnimByCardinalDirection(
GetMovementAnimByCardinalDirection(
velocityDirection, FeetPositionData.IsRightFootIsFront()); velocityDirection, FeetPositionData.IsRightFootIsFront());
} }
@ -184,13 +179,12 @@ UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectPivotAnimation(const bool
UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStopCycleAnimation(const bool isCrouching, UAnimSequence* UOLSBaseLinkedLayerAnimInstance::SelectStopCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection) const
const EOLSHipDirection hipDirection) const
{ {
if (isAiming) if (isAiming)
{ {
return GetGaitAnimSets(isCrouching, gait). return GetGaitAnimSets(isCrouching, gait).
GaitAnimSet_CameraFacing.GetStopCycleFromHipDirection(hipDirection).GetMovementAnimByCardinalDirection( GaitAnimSet_CameraFacing.StopCycle.GetMovementAnimByCardinalDirection(
velocityDirection, FeetPositionData.IsRightFootIsFront()); velocityDirection, FeetPositionData.IsRightFootIsFront());
} }

View File

@ -92,22 +92,24 @@ UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetForward180LeftOr
} }
class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetMovementAnimationByAngle( class UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StartCycle::GetMovementAnimationByAngle(
const EOLSCardinalDirection direction, const float angle, const bool isRightFootFarFromTarget) const const EOLSMovementDirection direction, const float angle, const bool isRightFootFarFromTarget) const
{ {
TObjectPtr<UAnimSequence> result = nullptr; TObjectPtr<UAnimSequence> result = nullptr;
switch (direction) switch (direction)
{ {
case EOLSCardinalDirection::EForward: case EOLSMovementDirection::EForward:
result = GetForwardLeftOrRightFoot(isRightFootFarFromTarget); result = GetForwardLeftOrRightFoot(isRightFootFarFromTarget);
break; break;
case EOLSCardinalDirection::ELeft: case EOLSMovementDirection::ELeftLeft:
case EOLSMovementDirection::ELeftRight:
result = Forward90L; result = Forward90L;
break; break;
case EOLSCardinalDirection::ERight: case EOLSMovementDirection::ERightLeft:
case EOLSMovementDirection::ERightRight:
result = Forward90R; result = Forward90R;
break; break;
case EOLSCardinalDirection::EBackward: case EOLSMovementDirection::EBackward:
result = GetForward180LeftOrRightByAngle(angle); result = GetForward180LeftOrRightByAngle(angle);
break; break;
} }
@ -128,6 +130,35 @@ UAnimSequence* FOLSMovementAnimSet_ForwardFacing_StopCycle::GetLeftOrRightAnim(c
return Stop.GetForwardLeftOrRightFoot(isRightFootPlanted); return Stop.GetForwardLeftOrRightFoot(isRightFootPlanted);
} }
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;
}
void FOLSGaitAnimSet::GetPlayRateByLocomotionState(const EOLSLocomotionStatePlayRate& state, FVector2D& outPlayRate) const void FOLSGaitAnimSet::GetPlayRateByLocomotionState(const EOLSLocomotionStatePlayRate& state, FVector2D& outPlayRate) const
{ {
switch (state) switch (state)
@ -144,27 +175,35 @@ void FOLSGaitAnimSet::GetPlayRateByLocomotionState(const EOLSLocomotionStatePlay
} }
} }
void FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimSetByCardinalDirection(const EOLSCardinalDirection& direction, void FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimSetByCardinalDirection(
const EOLSMovementDirection& direction,
FOLSMovementAnimSet_FeetPosition& outAnimSet) const FOLSMovementAnimSet_FeetPosition& outAnimSet) const
{ {
switch (direction) switch (direction)
{ {
case EOLSCardinalDirection::EForward: case EOLSMovementDirection::EForward:
outAnimSet = Forward; outAnimSet = Forward;
break; break;
case EOLSCardinalDirection::EBackward: case EOLSMovementDirection::EBackward:
outAnimSet = Backward; outAnimSet = Backward;
break; break;
case EOLSCardinalDirection::ERight: case EOLSMovementDirection::ELeftLeft:
outAnimSet = Right; outAnimSet = LeftLeft;
break; break;
case EOLSCardinalDirection::ELeft: case EOLSMovementDirection::ELeftRight:
outAnimSet = Left; outAnimSet = LeftRight;
break;
case EOLSMovementDirection::ERightRight:
outAnimSet = RightRight;
break;
case EOLSMovementDirection::ERightLeft:
outAnimSet = RightLeft;
break; break;
} }
} }
UAnimSequence* FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimByCardinalDirection(const EOLSCardinalDirection& direction, UAnimSequence* FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimByCardinalDirection(
const EOLSMovementDirection& direction,
const bool isRightFootFarFromTarget) const const bool isRightFootFarFromTarget) const
{ {
FOLSMovementAnimSet_FeetPosition animSet; FOLSMovementAnimSet_FeetPosition animSet;
@ -173,26 +212,6 @@ UAnimSequence* FOLSMovementAnimSet_CameraFacing_Directional::GetMovementAnimByCa
return animSet.GetForwardLeftOrRightFoot(isRightFootFarFromTarget); return animSet.GetForwardLeftOrRightFoot(isRightFootFarFromTarget);
} }
const FOLSMovementAnimSet_CameraFacing_Directional& FOLSGaitAnimSet_CameraFacing::GetStartCycleFromHipDirection(const EOLSHipDirection hipDirection) const
{
return (hipDirection == EOLSHipDirection::EForward) ? StartCycle_HipForward : StartCycle_HipBackward;
}
const FOLSMovementAnimSet_CameraFacing_Directional& FOLSGaitAnimSet_CameraFacing::GetCycleFromHipDirection(const EOLSHipDirection hipDirection) const
{
return (hipDirection == EOLSHipDirection::EForward) ? Cycle_HipForward : Cycle_HipBackward;
}
const FOLSMovementAnimSet_CameraFacing_Directional& FOLSGaitAnimSet_CameraFacing::GetPivotFromHipDirection(const EOLSHipDirection hipDirection) const
{
return (hipDirection == EOLSHipDirection::EForward) ? Pivot_HipForward : Pivot_HipBackward;
}
const FOLSMovementAnimSet_CameraFacing_Directional& FOLSGaitAnimSet_CameraFacing::GetStopCycleFromHipDirection(const EOLSHipDirection hipDirection) const
{
return (hipDirection == EOLSHipDirection::EForward) ? StopCycle_HipForward : StopCycle_HipBackward;
}
UAnimSequence* FOLSStanceAnimSets::GetIdleAnimation() const UAnimSequence* FOLSStanceAnimSets::GetIdleAnimation() const
{ {
return IdleAndTurnInPlaceAnimSet.GetIdleAnimation(); return IdleAndTurnInPlaceAnimSet.GetIdleAnimation();

View File

@ -5,60 +5,103 @@
DEFINE_LOG_CATEGORY_STATIC(LogOLSLocomotionLibrary, Verbose, All); DEFINE_LOG_CATEGORY_STATIC(LogOLSLocomotionLibrary, Verbose, All);
EOLSCardinalDirection UOLSLocomotionBPLibrary::SelectCardinalDirectionFromAngle(float angle, EOLSMovementDirection UOLSLocomotionBPLibrary::SelectMovementDirectionFromAngle(float angle,
float deadZone, const EOLSRotationMode& rotationMode,
EOLSCardinalDirection currentDirection, const EOLSGait& gait,
bool useCurrentDirection /* = false */) const EOLSMovementDirectionBias& movementDirectionBias,
const FOLSMovementDirectionThresholds& movementDirectionThreshold)
{ {
EOLSMovementDirection result = EOLSMovementDirection::EForward;
const float absAngle = FMath::Abs(angle); if (rotationMode == EOLSRotationMode::EVelocityDirection || gait == EOLSGait::ESprint)
float fwdDeadZone = deadZone;
float bwdDeadZone = deadZone;
if (useCurrentDirection)
{ {
if (currentDirection == EOLSCardinalDirection::EForward) return result;
{
fwdDeadZone *= 2.f;
}
else if (currentDirection == EOLSCardinalDirection::EBackward)
{
bwdDeadZone *= 2.f;
}
} }
if(absAngle <= (45 + fwdDeadZone)) const bool isAngleForwardDirection = FMath::IsWithinInclusive(angle,
movementDirectionThreshold.FL,
movementDirectionThreshold.FR);
const bool isAngleLeftDirection = FMath::IsWithinInclusive(angle,
movementDirectionThreshold.BL,
movementDirectionThreshold.FL);
const bool isAngleRightDirection = FMath::IsWithinInclusive(angle,
movementDirectionThreshold.FR,
movementDirectionThreshold.BR);
if (isAngleForwardDirection)
{ {
return EOLSCardinalDirection::EForward; result = EOLSMovementDirection::EForward;
} }
else if (absAngle >= (135 - bwdDeadZone)) else if (isAngleLeftDirection)
{ {
return EOLSCardinalDirection::EBackward; switch (movementDirectionBias)
{
case EOLSMovementDirectionBias::ELeftFoot_F:
result = EOLSMovementDirection::ELeftLeft;
break;
case EOLSMovementDirectionBias::ERightFoot_F:
result = EOLSMovementDirection::ELeftRight;
break;
} }
else if (angle > 0) }
else if (isAngleRightDirection)
{ {
return EOLSCardinalDirection::ERight; switch (movementDirectionBias)
{
case EOLSMovementDirectionBias::ELeftFoot_F:
result = EOLSMovementDirection::ERightLeft;
break;
case EOLSMovementDirectionBias::ERightFoot_F:
result = EOLSMovementDirection::ERightRight;
break;
}
}
else
{
result = EOLSMovementDirection::EBackward;
} }
return EOLSCardinalDirection::ELeft; return result;
} }
EOLSCardinalDirection UOLSLocomotionBPLibrary::GetOppositeCardinalDirectional(EOLSCardinalDirection currentDirection) EOLSMovementDirection UOLSLocomotionBPLibrary::GetOppositeMovementDirection(
const EOLSMovementDirection& currentDirection,
const EOLSMovementDirectionBias& movementDirectionBias)
{ {
switch (currentDirection) EOLSMovementDirection result = EOLSMovementDirection::EForward;
if (currentDirection == EOLSMovementDirection::EForward)
{ {
case EOLSCardinalDirection::EForward: {return EOLSCardinalDirection::EBackward;} result = EOLSMovementDirection::EBackward;
case EOLSCardinalDirection::EBackward: {return EOLSCardinalDirection::EForward;} }
case EOLSCardinalDirection::ELeft: {return EOLSCardinalDirection::ERight;} else if (currentDirection == EOLSMovementDirection::ELeftLeft || currentDirection == EOLSMovementDirection::ELeftRight)
case EOLSCardinalDirection::ERight: {return EOLSCardinalDirection::ELeft;} {
switch (movementDirectionBias)
{
case EOLSMovementDirectionBias::ELeftFoot_F:
result = EOLSMovementDirection::ERightLeft;
break;
case EOLSMovementDirectionBias::ERightFoot_F:
result = EOLSMovementDirection::ERightRight;
break;
}
}
else if (currentDirection == EOLSMovementDirection::ERightLeft || currentDirection == EOLSMovementDirection::ERightRight)
{
switch (movementDirectionBias)
{
case EOLSMovementDirectionBias::ELeftFoot_F:
result = EOLSMovementDirection::ELeftLeft;
break;
case EOLSMovementDirectionBias::ERightFoot_F:
result = EOLSMovementDirection::ELeftRight;
break;
}
}
else
{
result = EOLSMovementDirection::EBackward;
} }
return EOLSCardinalDirection::EForward; return result;
}
EOLSHipDirection UOLSLocomotionBPLibrary::GetOppositeHipDirection(EOLSHipDirection currentHipDirection)
{
return (currentHipDirection == EOLSHipDirection::EForward ? EOLSHipDirection::EBackward : EOLSHipDirection::EForward);
} }
void UOLSLocomotionBPLibrary::TryLinkAnimLayer(USkeletalMeshComponent* mesh, void UOLSLocomotionBPLibrary::TryLinkAnimLayer(USkeletalMeshComponent* mesh,

View File

@ -160,6 +160,11 @@ protected:
UFUNCTION(BlueprintCallable, Category = "Components", meta = (BlueprintThreadSafe)) UFUNCTION(BlueprintCallable, Category = "Components", meta = (BlueprintThreadSafe))
class UOLSLocomotionComponent* ThreadSafeGetLocomotionComponent() const; class UOLSLocomotionComponent* ThreadSafeGetLocomotionComponent() const;
protected:
UFUNCTION(BlueprintCallable, Category = "Movement Direciton", meta = (BlueprintThreadSafe))
void GetMovementDirectionThresholds(const EOLSMovementDirection& movementDirection, FOLSMovementDirectionThresholds& outMovementThresholds);
protected: protected:
UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|LocationData") UPROPERTY(BlueprintReadOnly, Category = "PawnInfo|LocationData")
@ -235,10 +240,10 @@ protected:
float LocalVelocityDirectionAngleWithOffset = 0.f; float LocalVelocityDirectionAngleWithOffset = 0.f;
UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData")
EOLSCardinalDirection LocalVelocityDirection = EOLSCardinalDirection::EForward; EOLSMovementDirection LocalVelocityDirection = EOLSMovementDirection::EForward;
UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData")
EOLSCardinalDirection LocalVelocityDirectionNoOffset = EOLSCardinalDirection::EForward; EOLSMovementDirection LocalVelocityDirectionNoOffset = EOLSMovementDirection::EForward;
UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData") UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|VelocityData")
uint8 bHasVelocity : 1; uint8 bHasVelocity : 1;
@ -261,7 +266,7 @@ protected:
float LocalAccelerationDirection = 0.f; float LocalAccelerationDirection = 0.f;
UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData") UPROPERTY(BlueprintReadOnly, Category = "ThreadSafe|AccelerationData")
EOLSCardinalDirection CardinalDirectionFromAcceleration = EOLSCardinalDirection::EForward; EOLSMovementDirection CardinalDirectionFromAcceleration = EOLSMovementDirection::EForward;
protected: protected:
@ -345,23 +350,29 @@ protected:
protected: protected:
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
uint8 bIsPivoting : 1 = false;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
uint8 bIsLooping : 1 = false;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
float PivotInitialVelocityDirection = 0.f; float PivotInitialVelocityDirection = 0.f;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
EOLSCardinalDirection PivotInitialDirection = EOLSCardinalDirection::EForward; EOLSMovementDirection PivotInitialDirection = EOLSMovementDirection::EForward;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
float LastPivotTime = 0.f; float LastPivotTime = 0.f;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
EOLSCardinalDirection StartDirection = EOLSCardinalDirection::EForward; EOLSMovementDirection StartDirection = EOLSMovementDirection::EForward;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
EOLSGait StopInitialGait = EOLSGait::EWalk; EOLSGait StopInitialGait = EOLSGait::EWalk;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
EOLSCardinalDirection StopLocalVelocityCardinalDirection = EOLSCardinalDirection::EForward; EOLSMovementDirection StopLocalVelocityDirection = EOLSMovementDirection::EForward;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
uint8 bHasGaitChanged : 1 = false; uint8 bHasGaitChanged : 1 = false;
@ -378,6 +389,9 @@ protected:
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
EOLSRotationMode LastRotationMode = EOLSRotationMode::EVelocityDirection; EOLSRotationMode LastRotationMode = EOLSRotationMode::EVelocityDirection;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
FOLSMovementDirectionThresholds MovementDirectionThresholds;
UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData") UPROPERTY(BlueprintReadWrite, Category = "ThreadSafe|LocomotionSMData")
TObjectPtr<class UAnimInstance> LastLinkedLayer = nullptr; TObjectPtr<class UAnimInstance> LastLinkedLayer = nullptr;
@ -423,6 +437,9 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|VelocityData") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|VelocityData")
float CardinalDirectionDeadZone = 10.f; float CardinalDirectionDeadZone = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings|MovementDirection")
EOLSMovementDirectionBias MovementDirectionBias = EOLSMovementDirectionBias::ELeftFoot_F;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Settings|GameplayTagBindings")
FGameplayTag ADSGameplayTag = FGameplayTag::EmptyTag; FGameplayTag ADSGameplayTag = FGameplayTag::EmptyTag;

View File

@ -65,31 +65,27 @@ protected:
class UAnimSequence* SelectStartCycleAnimation(const bool isCrouching, class UAnimSequence* SelectStartCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const; const float angle) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors") UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors")
class UAnimSequence* SelectCycleAnimation(const bool isCrouching, class UAnimSequence* SelectCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection) const;
const EOLSHipDirection hipDirection) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors") UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors")
class UAnimSequence* SelectPivotAnimation(const bool isCrouching, class UAnimSequence* SelectPivotAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection,
const EOLSHipDirection hipDirection,
const float angle) const; const float angle) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors") UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors")
class UAnimSequence* SelectStopCycleAnimation(const bool isCrouching, class UAnimSequence* SelectStopCycleAnimation(const bool isCrouching,
const bool isAiming, const bool isAiming,
const EOLSGait gait, const EOLSGait gait,
const EOLSCardinalDirection velocityDirection, const EOLSMovementDirection velocityDirection) const;
const EOLSHipDirection hipDirection) const;
UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors") UFUNCTION(BlueprintCallable, meta = (BlueprintThreadSafe), Category = "ThreadSafe|Selectors")
FVector2D SelectPlayRateByLocomotionState(const bool isCrouching, const bool isAiming, const EOLSGait gait, FVector2D SelectPlayRateByLocomotionState(const bool isCrouching, const bool isAiming, const EOLSGait gait,

View File

@ -9,6 +9,44 @@
#include "UObject/Object.h" #include "UObject/Object.h"
#include "OLSAnimationData.generated.h" #include "OLSAnimationData.generated.h"
UENUM(BlueprintType)
enum class EOLSMovementDirection : uint8
{
EForward UMETA(DisplayName = "F"),
EBackward UMETA(DisplayName = "B"),
ELeftLeft UMETA(DisplayName = "LL"),
ELeftRight UMETA(DisplayName = "LR"),
ERightLeft UMETA(DisplayName = "RL"),
ERightRight UMETA(DisplayName = "RR")
};
UENUM(BlueprintType)
enum class EOLSMovementDirectionBias : uint8
{
ELeftFoot_F UMETA(DisplayName = "Left Foot Forward"),
ERightFoot_F UMETA(DisplayName = "Right Foot Forward"),
};
USTRUCT(BlueprintType)
struct FOLSMovementDirectionThresholds
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float FL = -60.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float FR = 60.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float BL = -120.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float BR = 120.f;
};
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
struct FOLSFeetPositionSettings struct FOLSFeetPositionSettings
{ {
@ -150,7 +188,7 @@ public:
class UAnimSequence* GetForwardLeftOrRightFoot(const bool isRightFootFarFromTarget) const; class UAnimSequence* GetForwardLeftOrRightFoot(const bool isRightFootFarFromTarget) const;
class UAnimSequence* GetForward180LeftOrRightByAngle(const float angle) const; class UAnimSequence* GetForward180LeftOrRightByAngle(const float angle) const;
class UAnimSequence* GetMovementAnimationByAngle(const EOLSCardinalDirection direction, class UAnimSequence* GetMovementAnimationByAngle(const EOLSMovementDirection direction,
const float angle, const float angle,
const bool isRightFootFarFromTarget) const; const bool isRightFootFarFromTarget) const;
@ -207,6 +245,36 @@ public:
}; };
#pragma endregion #pragma endregion
USTRUCT(BlueprintType)
struct FOLSMovementAnimSet_CameraFacing_Directional_Cycle
{
GENERATED_BODY()
public:
class UAnimSequence* GetMovementAnimByCardinalDirection(const EOLSMovementDirection& direction) const;
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "F"))
TObjectPtr<class UAnimSequence> Forward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "B"))
TObjectPtr<class UAnimSequence> Backward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "LL"))
TObjectPtr<class UAnimSequence> LeftLeft;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "LR"))
TObjectPtr<class UAnimSequence> LeftRight;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "RL"))
TObjectPtr<class UAnimSequence> RightLeft;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "RR"))
TObjectPtr<class UAnimSequence> RightRight;
};
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
struct FOLSMovementAnimSet_CameraFacing_Directional struct FOLSMovementAnimSet_CameraFacing_Directional
{ {
@ -214,25 +282,31 @@ struct FOLSMovementAnimSet_CameraFacing_Directional
protected: protected:
void GetMovementAnimSetByCardinalDirection(const EOLSCardinalDirection& direction, FOLSMovementAnimSet_FeetPosition& outAnimSet) const; void GetMovementAnimSetByCardinalDirection(const EOLSMovementDirection& direction, FOLSMovementAnimSet_FeetPosition& outAnimSet) const;
public: public:
class UAnimSequence* GetMovementAnimByCardinalDirection(const EOLSCardinalDirection& direction, const bool isRightFootFarFromTarget) const; class UAnimSequence* GetMovementAnimByCardinalDirection(const EOLSMovementDirection& direction, const bool isRightFootFarFromTarget) const;
public: public:
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "F"))
FOLSMovementAnimSet_FeetPosition Forward; FOLSMovementAnimSet_FeetPosition Forward;
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "B"))
FOLSMovementAnimSet_FeetPosition Backward; FOLSMovementAnimSet_FeetPosition Backward;
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "LL"))
FOLSMovementAnimSet_FeetPosition Right; FOLSMovementAnimSet_FeetPosition LeftLeft;
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "LR"))
FOLSMovementAnimSet_FeetPosition Left; FOLSMovementAnimSet_FeetPosition LeftRight;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "RL"))
FOLSMovementAnimSet_FeetPosition RightLeft;
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (DisplayName = "RR"))
FOLSMovementAnimSet_FeetPosition RightRight;
}; };
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
@ -294,36 +368,17 @@ struct FOLSGaitAnimSet_CameraFacing : public FOLSGaitAnimSet
public: public:
const FOLSMovementAnimSet_CameraFacing_Directional& GetStartCycleFromHipDirection(const EOLSHipDirection hipDirection) const; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
const FOLSMovementAnimSet_CameraFacing_Directional& GetCycleFromHipDirection(const EOLSHipDirection hipDirection) const; FOLSMovementAnimSet_CameraFacing_Directional StartCycle;
const FOLSMovementAnimSet_CameraFacing_Directional& GetPivotFromHipDirection(const EOLSHipDirection hipDirection) const;
const FOLSMovementAnimSet_CameraFacing_Directional& GetStopCycleFromHipDirection(const EOLSHipDirection hipDirection) const;
public: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
FOLSMovementAnimSet_CameraFacing_Directional_Cycle Cycle;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
FOLSMovementAnimSet_CameraFacing_Directional StartCycle_HipForward; FOLSMovementAnimSet_CameraFacing_Directional Pivot;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set")
FOLSMovementAnimSet_CameraFacing_Directional Cycle_HipForward; FOLSMovementAnimSet_CameraFacing_Directional StopCycle;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
FOLSMovementAnimSet_CameraFacing_Directional Pivot_HipForward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Forward")
FOLSMovementAnimSet_CameraFacing_Directional StopCycle_HipForward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
FOLSMovementAnimSet_CameraFacing_Directional StartCycle_HipBackward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
FOLSMovementAnimSet_CameraFacing_Directional Cycle_HipBackward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
FOLSMovementAnimSet_CameraFacing_Directional Pivot_HipBackward;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gait Anim Set | Hip Backward")
FOLSMovementAnimSet_CameraFacing_Directional StopCycle_HipBackward;
}; };
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
@ -379,9 +434,6 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
FOLSGaitAnimSets WalkAnimSets; FOLSGaitAnimSets WalkAnimSets;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stance Anim Sets")
uint8 bUseFeetPosition : 1 = false;
}; };
USTRUCT(BlueprintType) USTRUCT(BlueprintType)

View File

@ -25,15 +25,6 @@ enum class EOLSHipDirection : uint8
EBackward UMETA(DisplayName = "Backward") EBackward UMETA(DisplayName = "Backward")
}; };
UENUM(BlueprintType)
enum class EOLSCardinalDirection : uint8
{
EForward UMETA(DisplayName = "Forward"),
EBackward UMETA(DisplayName = "Backward"),
ELeft UMETA(DisplayName = "Left"),
ERight UMETA(DisplayName = "Right")
};
UENUM(BlueprintType) UENUM(BlueprintType)
enum class EOLSLocomotionStatePlayRate : uint8 enum class EOLSLocomotionStatePlayRate : uint8
{ {

View File

@ -20,13 +20,14 @@ class OLSANIMATION_API UOLSLocomotionBPLibrary : public UBlueprintFunctionLibrar
public: public:
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe)) UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSCardinalDirection SelectCardinalDirectionFromAngle(float angle, float deadZone, EOLSCardinalDirection currentDirection, bool useCurrentDirection = false); static EOLSMovementDirection SelectMovementDirectionFromAngle(float angle,
const EOLSRotationMode& rotationMode,
const EOLSGait& gait,
const EOLSMovementDirectionBias& movementDirectionBias,
const FOLSMovementDirectionThresholds& movementDirectionThreshold);
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe)) UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSCardinalDirection GetOppositeCardinalDirectional(EOLSCardinalDirection currentDirection); static EOLSMovementDirection GetOppositeMovementDirection(const EOLSMovementDirection& currentDirection, const EOLSMovementDirectionBias& movementDirectionBias);
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "OLS|Function Library",meta=(BlueprintThreadSafe))
static EOLSHipDirection GetOppositeHipDirection(EOLSHipDirection currentHipDirection);
public: public: