Implemented OLSCameraMode.

Addressed @TODOs related to custom logs and OLSCameraMode
This commit is contained in:
LongLy 2025-01-20 14:08:07 -07:00
parent c0b033fb22
commit 57b53b9c0c
19 changed files with 1283 additions and 90 deletions

View File

@ -11,6 +11,7 @@
#include "AbilitySystemGlobals.h" #include "AbilitySystemGlobals.h"
#include "AbilitySystem/OLSGameplayEffectContext.h" #include "AbilitySystem/OLSGameplayEffectContext.h"
#include "AbilitySystem/Interfaces/OLSAbilitySourceInterface.h" #include "AbilitySystem/Interfaces/OLSAbilitySourceInterface.h"
#include "Camera/OLSCameraMode.h"
#include "Components/OLSHeroComponent.h" #include "Components/OLSHeroComponent.h"
#include "GameFramework/GameplayMessageSubsystem.h" #include "GameFramework/GameplayMessageSubsystem.h"
#include "Physics/OLSPhysicalMaterialWithTags.h" #include "Physics/OLSPhysicalMaterialWithTags.h"
@ -43,8 +44,7 @@ UOLSGameplayAbility::UOLSGameplayAbility(const FObjectInitializer& objectInitial
bShouldLogCancellation = false; bShouldLogCancellation = false;
// @TODO: Implement OLSCameraMode. ActiveCameraMode = nullptr;
// ActiveCameraMode = nullptr;
} }
bool UOLSGameplayAbility::CanActivateAbility(const FGameplayAbilitySpecHandle handle, bool UOLSGameplayAbility::CanActivateAbility(const FGameplayAbilitySpecHandle handle,
@ -122,8 +122,7 @@ void UOLSGameplayAbility::EndAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateEndAbility, bool bWasCancelled) bool bReplicateEndAbility, bool bWasCancelled)
{ {
// @TODO: Implement UOLSCameraMode. ClearCameraMode();
// ClearCameraMode();
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled); Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
} }
@ -450,6 +449,32 @@ bool UOLSGameplayAbility::ChangeActivationGroup(EOLSAbilityActivationGroup newGr
return true; return true;
} }
void UOLSGameplayAbility::SetCameraMode(TSubclassOf<UOLSCameraMode> cameraMode)
{
ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(SetCameraMode, );
if (UOLSHeroComponent* heroComponent = GetHeroComponentFromActorInfo())
{
heroComponent->SetAbilityCameraMode(cameraMode, CurrentSpecHandle);
ActiveCameraMode = cameraMode;
}
}
void UOLSGameplayAbility::ClearCameraMode()
{
ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(ClearCameraMode, );
if (ActiveCameraMode)
{
if (UOLSHeroComponent* heroComponent = GetHeroComponentFromActorInfo())
{
heroComponent->ClearAbilityCameraMode(CurrentSpecHandle);
}
ActiveCameraMode = nullptr;
}
}
EOLSAbilityActivationPolicy UOLSGameplayAbility::GetActivationPolicy() const EOLSAbilityActivationPolicy UOLSGameplayAbility::GetActivationPolicy() const
{ {
return ActivationPolicy; return ActivationPolicy;

View File

@ -302,8 +302,7 @@ void UOLSAbilitySystemComponent::TryActivateAbilitiesOnSpawn()
{ {
if (const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec.Ability)) if (const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec.Ability))
{ {
// @TODO: Implement UOLSGameplayAbility. abilityCDO->TryActivateAbilityOnSpawn(AbilityActorInfo.Get(), abilitySpec);
// abilityCDO->TryActivateAbilityOnSpawn(AbilityActorInfo.Get(), abilitySpec);
} }
} }
} }
@ -355,8 +354,7 @@ void UOLSAbilitySystemComponent::NotifyAbilityActivated(const FGameplayAbilitySp
if (UOLSGameplayAbility* olsAbility = Cast<UOLSGameplayAbility>(ability)) if (UOLSGameplayAbility* olsAbility = Cast<UOLSGameplayAbility>(ability))
{ {
// @TODO: Implement UOLSGameplayAbility. AddAbilityToActivationGroup(olsAbility->GetActivationGroup(), olsAbility);
// AddAbilityToActivationGroup(olsAbility->GetActivationGroup(), ability);
} }
} }
@ -378,15 +376,15 @@ void UOLSAbilitySystemComponent::NotifyAbilityFailed(const FGameplayAbilitySpecH
HandleAbilityFailed(ability, failureReason); HandleAbilityFailed(ability, failureReason);
} }
void UOLSAbilitySystemComponent::NotifyAbilityEnded(FGameplayAbilitySpecHandle handle, UGameplayAbility* Ability, void UOLSAbilitySystemComponent::NotifyAbilityEnded(FGameplayAbilitySpecHandle handle,
UGameplayAbility* ability,
bool wasCancelled) bool wasCancelled)
{ {
Super::NotifyAbilityEnded(handle, Ability, wasCancelled); Super::NotifyAbilityEnded(handle, ability, wasCancelled);
if (UOLSGameplayAbility* olsAbility = Cast<UOLSGameplayAbility>(Ability)) if (UOLSGameplayAbility* olsAbility = Cast<UOLSGameplayAbility>(ability))
{ {
// @TODO: Implement UOLSGameplayAbility. RemoveAbilityFromActivationGroup(olsAbility->GetActivationGroup(), olsAbility);
// RemoveAbilityFromActivationGroup(olsAbility->GetActivationGroup(), olsAbility);
} }
} }
@ -432,8 +430,7 @@ void UOLSAbilitySystemComponent::HandleAbilityFailed(const UGameplayAbility* abi
{ {
if (const UOLSGameplayAbility* olsAbility = Cast<const UOLSGameplayAbility>(ability)) if (const UOLSGameplayAbility* olsAbility = Cast<const UOLSGameplayAbility>(ability))
{ {
// @TODO: Implement UOLSGameplayAbility. olsAbility->OnAbilityFailedToActivate(failureReason);
// olsAbility->OnAbilityFailedToActivate(failureReason);
} }
} }
@ -514,14 +511,13 @@ void UOLSAbilitySystemComponent::CancelAbilitiesByFunc(TShouldCancelAbilityFunc
void UOLSAbilitySystemComponent::CancelInputActivatedAbilities(bool shouldReplicateCancelAbility) void UOLSAbilitySystemComponent::CancelInputActivatedAbilities(bool shouldReplicateCancelAbility)
{ {
// @TODO: Implement UOLSGameplayAbility auto shouldCancelFunc = [this](const UOLSGameplayAbility* ability, FGameplayAbilitySpecHandle handle)
// auto shouldCancelFunc = [this](const UOLSGameplayAbility* ability, FGameplayAbilitySpecHandle handle) {
// { const EOLSAbilityActivationPolicy activationPolicy = ability->GetActivationPolicy();
// const ELyraAbilityActivationPolicy ActivationPolicy = ability->GetActivationPolicy(); return ((activationPolicy == EOLSAbilityActivationPolicy::OnInputTriggered) || (activationPolicy == EOLSAbilityActivationPolicy::WhileInputActive));
// return ((ActivationPolicy == ELyraAbilityActivationPolicy::OnInputTriggered) || (ActivationPolicy == ELyraAbilityActivationPolicy::WhileInputActive)); };
// };
// CancelAbilitiesByFunc(shouldCancelFunc, shouldReplicateCancelAbility);
// CancelAbilitiesByFunc(shouldCancelFunc, shouldReplicateCancelAbility);
} }
void UOLSAbilitySystemComponent::AbilityInputTagPressed(const FGameplayTag& inputTag) void UOLSAbilitySystemComponent::AbilityInputTagPressed(const FGameplayTag& inputTag)
@ -578,11 +574,10 @@ void UOLSAbilitySystemComponent::ProcessAbilityInput(float deltaTime, bool shoul
{ {
const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec->Ability); const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec->Ability);
// @TODO: Implement UOLSGameplayAbility. if (abilityCDO && abilityCDO->GetActivationPolicy() == EOLSAbilityActivationPolicy::WhileInputActive)
// if (abilityCDO && abilityCDO->GetActivationPolicy() == ELyraAbilityActivationPolicy::WhileInputActive) {
// { abilitiesToActivate.AddUnique(abilitySpec->Handle);
// AbilitiesToActivate.AddUnique(AbilitySpec->Handle); }
// }
} }
} }
} }
@ -607,11 +602,10 @@ void UOLSAbilitySystemComponent::ProcessAbilityInput(float deltaTime, bool shoul
{ {
const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec->Ability); const UOLSGameplayAbility* abilityCDO = Cast<UOLSGameplayAbility>(abilitySpec->Ability);
// @TODO: Implement UOLSGameplayAbility. if (abilityCDO && abilityCDO->GetActivationPolicy() == EOLSAbilityActivationPolicy::OnInputTriggered)
// if (abilityCDO && abilityCDO->GetActivationPolicy() == ELyraAbilityActivationPolicy::OnInputTriggered) {
// { abilitiesToActivate.AddUnique(abilitySpec->Handle);
// abilitiesToActivate.AddUnique(abilitySpec->Handle); }
// }
} }
} }
} }

View File

@ -0,0 +1,134 @@
// © 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 "Camera/Components/OLSCameraComponent.h"
#include "Camera/OLSCameraMode.h"
#include "Engine/Canvas.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSCameraComponent)
UOLSCameraComponent::UOLSCameraComponent(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{
CameraModeStack = nullptr;
FieldOfViewOffset = 0.0f;
}
UOLSCameraComponent* UOLSCameraComponent::FindCameraComponent(const AActor* Actor)
{
return (Actor ? Actor->FindComponentByClass<UOLSCameraComponent>() : nullptr);
}
AActor* UOLSCameraComponent::GetTargetActor() const
{
return GetOwner();
}
void UOLSCameraComponent::AddFieldOfViewOffset(float FovOffset)
{
FieldOfViewOffset += FovOffset;
}
void UOLSCameraComponent::DrawDebug(UCanvas* canvas) const
{
check(canvas);
FDisplayDebugManager& DisplayDebugManager = canvas->DisplayDebugManager;
DisplayDebugManager.SetFont(GEngine->GetSmallFont());
DisplayDebugManager.SetDrawColor(FColor::Yellow);
DisplayDebugManager.DrawString(FString::Printf(TEXT("LyraCameraComponent: %s"), *GetNameSafe(GetTargetActor())));
DisplayDebugManager.SetDrawColor(FColor::White);
DisplayDebugManager.DrawString(FString::Printf(TEXT(" Location: %s"), *GetComponentLocation().ToCompactString()));
DisplayDebugManager.DrawString(FString::Printf(TEXT(" Rotation: %s"), *GetComponentRotation().ToCompactString()));
DisplayDebugManager.DrawString(FString::Printf(TEXT(" FOV: %f"), FieldOfView));
check(CameraModeStack);
CameraModeStack->DrawDebug(canvas);
}
void UOLSCameraComponent::GetBlendInfo(float& outWeightOfTopLayer, FGameplayTag& outTagOfTopLayer) const
{
check(CameraModeStack);
CameraModeStack->GetBlendInfo(/*out*/ outWeightOfTopLayer, /*out*/ outTagOfTopLayer);
}
void UOLSCameraComponent::OnRegister()
{
Super::OnRegister();
if (!CameraModeStack)
{
CameraModeStack = NewObject<UOLSCameraModeStack>(this);
check(CameraModeStack);
}
}
void UOLSCameraComponent::GetCameraView(float deltaTime, FMinimalViewInfo& desiredView)
{
check(CameraModeStack);
UpdateCameraModes();
FOLSCameraModeView cameraModeView;
CameraModeStack->EvaluateStack(deltaTime, cameraModeView);
// Keep player controller in sync with the latest view.
if (APawn* targetPawn = Cast<APawn>(GetTargetActor()))
{
if (APlayerController* playerController = targetPawn->GetController<APlayerController>())
{
playerController->SetControlRotation(cameraModeView.ControlRotation);
}
}
// Apply any offset that was added to the field of view.
cameraModeView.FieldOfView += FieldOfViewOffset;
FieldOfViewOffset = 0.0f;
// Keep camera component in sync with the latest view.
SetWorldLocationAndRotation(cameraModeView.Location, cameraModeView.Rotation);
FieldOfView = cameraModeView.FieldOfView;
// Fill in desired view.
desiredView.Location = cameraModeView.Location;
desiredView.Rotation = cameraModeView.Rotation;
desiredView.FOV = cameraModeView.FieldOfView;
desiredView.OrthoWidth = OrthoWidth;
desiredView.OrthoNearClipPlane = OrthoNearClipPlane;
desiredView.OrthoFarClipPlane = OrthoFarClipPlane;
desiredView.AspectRatio = AspectRatio;
desiredView.bConstrainAspectRatio = bConstrainAspectRatio;
desiredView.bUseFieldOfViewForLOD = bUseFieldOfViewForLOD;
desiredView.ProjectionMode = ProjectionMode;
// See if the CameraActor wants to override the PostProcess settings used.
desiredView.PostProcessBlendWeight = PostProcessBlendWeight;
if (PostProcessBlendWeight > 0.0f)
{
desiredView.PostProcessSettings = PostProcessSettings;
}
if (IsXRHeadTrackedCamera())
{
// In XR much of the camera behavior above is irrellevant, but the post process settings are not.
Super::GetCameraView(deltaTime, desiredView);
}
}
void UOLSCameraComponent::UpdateCameraModes()
{
check(CameraModeStack);
if (CameraModeStack->IsStackActivate())
{
if (DetermineCameraModeDelegate.IsBound())
{
if (const TSubclassOf<UOLSCameraMode> cameraMode = DetermineCameraModeDelegate.Execute())
{
CameraModeStack->PushCameraMode(cameraMode);
}
}
}
}

View File

@ -0,0 +1,69 @@
// © 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 "Camera/Components/OLSUICameraManagerComponent.h"
#include "Camera/OLSPlayerCameraManager.h"
#include "GameFramework/HUD.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSUICameraManagerComponent)
UOLSUICameraManagerComponent* UOLSUICameraManagerComponent::GetComponent(APlayerController* playerController)
{
if (playerController)
{
if (AOLSPlayerCameraManager* playerCamera = Cast<AOLSPlayerCameraManager>(playerController->PlayerCameraManager))
{
return playerCamera->GetUICameraComponent();
}
}
return nullptr;
}
UOLSUICameraManagerComponent::UOLSUICameraManagerComponent()
{
bWantsInitializeComponent = true;
if (!HasAnyFlags(RF_ClassDefaultObject))
{
// Register "showdebug" hook.
if (!IsRunningDedicatedServer())
{
AHUD::OnShowDebugInfo.AddUObject(this, &ThisClass::OnShowDebugInfo);
}
}
}
bool UOLSUICameraManagerComponent::IsSettingViewTarget() const
{
return bShouldUpdatingViewTarget;
}
AActor* UOLSUICameraManagerComponent::GetViewTarget() const
{
return ViewTarget;
}
void UOLSUICameraManagerComponent::SetViewTarget(AActor* viewTarget, FViewTargetTransitionParams transitionParams)
{
TGuardValue<bool> UpdatingViewTargetGuard(bShouldUpdatingViewTarget, true);
ViewTarget = viewTarget;
CastChecked<AOLSPlayerCameraManager>(GetOwner())->SetViewTarget(ViewTarget, transitionParams);
}
bool UOLSUICameraManagerComponent::NeedsToUpdateViewTarget() const
{
return false;
}
void UOLSUICameraManagerComponent::UpdateViewTarget(FTViewTarget& outVT, float deltaTime)
{
}
void UOLSUICameraManagerComponent::OnShowDebugInfo(AHUD* hud, UCanvas* canvas,
const FDebugDisplayInfo& displayInfo,
float& yl, float& yPos)
{
}

View File

@ -0,0 +1,20 @@
// © 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 "Camera/Interfaces/OLSCameraAssistInterface.h"
// Add default functionality here for any IOLSCameraAssistInterface functions that are not pure virtual.
void IOLSCameraAssistInterface::GetIgnoredActorsForCameraPenetration(
TArray<const AActor*>& outActorsAllowPenetration) const
{
}
TOptional<AActor*> IOLSCameraAssistInterface::GetCameraPreventPenetrationTarget() const
{
return TOptional<AActor*>();
}
void IOLSCameraAssistInterface::OnCameraPenetratingTarget()
{
}

View File

@ -0,0 +1,495 @@
// © 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 "Camera/OLSCameraMode.h"
#include "Camera/OLSPlayerCameraManager.h"
#include "Camera/Components/OLSCameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Engine/Canvas.h"
#include "GameFramework/Character.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSCameraMode)
//////////////////////////////////////////////////////////////////////////
// FLyraCameraModeView
//////////////////////////////////////////////////////////////////////////
FOLSCameraModeView::FOLSCameraModeView()
: Location(ForceInit)
, Rotation(ForceInit)
, ControlRotation(ForceInit)
, FieldOfView(OLS_CAMERA_DEFAULT_FOV)
{
}
void FOLSCameraModeView::Blend(const FOLSCameraModeView& other, float otherWeight)
{
if (otherWeight <= 0.0f)
{
return;
}
else if (otherWeight >= 1.0f)
{
*this = other;
return;
}
Location = FMath::Lerp(Location, other.Location, otherWeight);
const FRotator deltaRotation = (other.Rotation - Rotation).GetNormalized();
Rotation = Rotation + (otherWeight * deltaRotation);
const FRotator deltaControlRotation = (other.ControlRotation - ControlRotation).GetNormalized();
ControlRotation = ControlRotation + (otherWeight * deltaControlRotation);
FieldOfView = FMath::Lerp(FieldOfView, other.FieldOfView, otherWeight);
}
//////////////////////////////////////////////////////////////////////////
// UOLSCameraMode
//////////////////////////////////////////////////////////////////////////
UOLSCameraMode::UOLSCameraMode()
{
FieldOfView = OLS_CAMERA_DEFAULT_FOV;
ViewPitchMin = OLS_CAMERA_DEFAULT_PITCH_MIN;
ViewPitchMax = OLS_CAMERA_DEFAULT_PITCH_MAX;
BlendTime = 0.5f;
BlendFunction = EOLSCameraModeBlendFunction::EaseOut;
BlendExponent = 4.0f;
BlendAlpha = 1.0f;
BlendWeight = 1.0f;
}
UOLSCameraComponent* UOLSCameraMode::GetOLSCameraComponent() const
{
return CastChecked<UOLSCameraComponent>(GetOuter());
}
UWorld* UOLSCameraMode::GetWorld() const
{
return HasAnyFlags(RF_ClassDefaultObject) ? nullptr : GetOuter()->GetWorld();
}
AActor* UOLSCameraMode::GetTargetActor() const
{
const UOLSCameraComponent* cameraComponent = GetOLSCameraComponent();
return cameraComponent->GetTargetActor();
}
const FOLSCameraModeView& UOLSCameraMode::GetCameraModeView() const
{
return View;
}
void UOLSCameraMode::OnActivation()
{
}
void UOLSCameraMode::OnDeactivation()
{
}
void UOLSCameraMode::UpdateCameraMode(float deltaTime)
{
UpdateView(deltaTime);
UpdateBlending(deltaTime);
}
float UOLSCameraMode::GetBlendTime() const
{
return BlendTime;
}
float UOLSCameraMode::GetBlendWeight() const
{
return BlendWeight;
}
void UOLSCameraMode::SetBlendWeight(float weight)
{
BlendWeight = FMath::Clamp(weight, 0.0f, 1.0f);
// Since we're setting the blend weight directly, we need to calculate the blend alpha to account for the blend function.
const float InvExponent = (BlendExponent > 0.0f) ? (1.0f / BlendExponent) : 1.0f;
switch (BlendFunction)
{
case EOLSCameraModeBlendFunction::Linear:
BlendAlpha = BlendWeight;
break;
case EOLSCameraModeBlendFunction::EaseIn:
BlendAlpha = FMath::InterpEaseIn(0.0f, 1.0f, BlendWeight, InvExponent);
break;
case EOLSCameraModeBlendFunction::EaseOut:
BlendAlpha = FMath::InterpEaseOut(0.0f, 1.0f, BlendWeight, InvExponent);
break;
case EOLSCameraModeBlendFunction::EaseInOut:
BlendAlpha = FMath::InterpEaseInOut(0.0f, 1.0f, BlendWeight, InvExponent);
break;
default:
checkf(false, TEXT("SetBlendWeight: Invalid BlendFunction [%d]\n"), (uint8)BlendFunction);
break;
}
}
FGameplayTag UOLSCameraMode::GetCameraTypeTag() const
{
return CameraTypeTag;
}
void UOLSCameraMode::DrawDebug(UCanvas* canvas) const
{
check(canvas);
FDisplayDebugManager& displayDebugManager = canvas->DisplayDebugManager;
displayDebugManager.SetDrawColor(FColor::White);
displayDebugManager.DrawString(FString::Printf(TEXT(" OLSCameraMode: %s (%f)"), *GetName(), BlendWeight));
}
FVector UOLSCameraMode::GetPivotLocation() const
{
const AActor* targetActor = GetTargetActor();
check(targetActor);
if (const APawn* targetPawn = Cast<APawn>(targetActor))
{
// Height adjustments for characters to account for crouching.
if (const ACharacter* targetCharacter = Cast<ACharacter>(targetPawn))
{
const ACharacter* targetCharacterCDO = targetCharacter->GetClass()->GetDefaultObject<ACharacter>();
check(targetCharacterCDO);
const UCapsuleComponent* capsuleComp = targetCharacter->GetCapsuleComponent();
check(capsuleComp);
const UCapsuleComponent* capsuleCompCDO = targetCharacterCDO->GetCapsuleComponent();
check(capsuleCompCDO);
const float defaultHalfHeight = capsuleCompCDO->GetUnscaledCapsuleHalfHeight();
const float actualHalfHeight = capsuleComp->GetUnscaledCapsuleHalfHeight();
const float heightAdjustment = (defaultHalfHeight - actualHalfHeight) + targetCharacterCDO->BaseEyeHeight;
return targetCharacter->GetActorLocation() + (FVector::UpVector * heightAdjustment);
}
return targetPawn->GetPawnViewLocation();
}
return targetActor->GetActorLocation();
}
FRotator UOLSCameraMode::GetPivotRotation() const
{
const AActor* targetActor = GetTargetActor();
check(targetActor);
if (const APawn* targetPawn = Cast<APawn>(targetActor))
{
return targetPawn->GetViewRotation();
}
return targetActor->GetActorRotation();
}
void UOLSCameraMode::UpdateView(float deltaTime)
{
FVector pivotLocation = GetPivotLocation();
FRotator pivotRotation = GetPivotRotation();
pivotRotation.Pitch = FMath::ClampAngle(pivotRotation.Pitch, ViewPitchMin, ViewPitchMax);
View.Location = pivotLocation;
View.Rotation = pivotRotation;
View.ControlRotation = View.Rotation;
View.FieldOfView = FieldOfView;
}
void UOLSCameraMode::UpdateBlending(float deltaTime)
{
if (BlendTime > 0.0f)
{
BlendAlpha += (deltaTime / BlendTime);
BlendAlpha = FMath::Min(BlendAlpha, 1.0f);
}
else
{
BlendAlpha = 1.0f;
}
const float exponent = (BlendExponent > 0.0f) ? BlendExponent : 1.0f;
switch (BlendFunction)
{
case EOLSCameraModeBlendFunction::Linear:
BlendWeight = BlendAlpha;
break;
case EOLSCameraModeBlendFunction::EaseIn:
BlendWeight = FMath::InterpEaseIn(0.0f, 1.0f, BlendAlpha, exponent);
break;
case EOLSCameraModeBlendFunction::EaseOut:
BlendWeight = FMath::InterpEaseOut(0.0f, 1.0f, BlendAlpha, exponent);
break;
case EOLSCameraModeBlendFunction::EaseInOut:
BlendWeight = FMath::InterpEaseInOut(0.0f, 1.0f, BlendAlpha, exponent);
break;
default:
checkf(false, TEXT("UpdateBlending: Invalid BlendFunction [%d]\n"), (uint8)BlendFunction);
break;
}
}
//////////////////////////////////////////////////////////////////////////
// UOLSCameraModeStack
//////////////////////////////////////////////////////////////////////////
UOLSCameraModeStack::UOLSCameraModeStack()
{
bIsStackActive = true;
}
void UOLSCameraModeStack::ActivateStack()
{
if (!IsStackActivate())
{
bIsStackActive = true;
// Notify camera modes that they are being activated.
for (UOLSCameraMode* cameraMode : CameraModeStack)
{
check(cameraMode);
cameraMode->OnActivation();
}
}
}
void UOLSCameraModeStack::DeactivateStack()
{
if (IsStackActivate())
{
bIsStackActive = false;
// Notify camera modes that they are being deactivated.
for (UOLSCameraMode* cameraMode : CameraModeStack)
{
check(cameraMode);
cameraMode->OnDeactivation();
}
}
}
bool UOLSCameraModeStack::IsStackActivate() const
{
return bIsStackActive;
}
void UOLSCameraModeStack::PushCameraMode(TSubclassOf<UOLSCameraMode> cameraModeClass)
{
if (!cameraModeClass)
{
return;
}
UOLSCameraMode* cameraMode = GetCameraModeInstance(cameraModeClass);
check(cameraMode);
int32 stackSize = CameraModeStack.Num();
if ((stackSize > 0) && (CameraModeStack[0] == cameraMode))
{
// Already top of stack.
return;
}
// See if it's already in the stack and remove it.
// Figure out how much it was contributing to the stack.
int32 existingStackIndex = INDEX_NONE;
float existingStackContribution = 1.0f;
for (int32 stackIndex = 0; stackIndex < stackSize; ++stackIndex)
{
if (CameraModeStack[stackIndex] == cameraMode)
{
existingStackIndex = stackIndex;
existingStackContribution *= cameraMode->GetBlendWeight();
break;
}
else
{
existingStackContribution *= (1.0f - CameraModeStack[stackIndex]->GetBlendWeight());
}
}
if (existingStackIndex != INDEX_NONE)
{
CameraModeStack.RemoveAt(existingStackIndex);
stackSize--;
}
else
{
existingStackContribution = 0.0f;
}
// Decide what initial weight to start with.
const bool shouldBlend = ((cameraMode->GetBlendTime() > 0.0f) && (stackSize > 0));
const float blendWeight = (shouldBlend ? existingStackContribution : 1.0f);
cameraMode->SetBlendWeight(blendWeight);
// Add new entry to top of stack.
CameraModeStack.Insert(cameraMode, 0);
// Make sure stack bottom is always weighted 100%.
CameraModeStack.Last()->SetBlendWeight(1.0f);
// Let the camera mode know if it's being added to the stack.
if (existingStackIndex == INDEX_NONE)
{
cameraMode->OnActivation();
}
}
bool UOLSCameraModeStack::EvaluateStack(float deltaTime, FOLSCameraModeView& outCameraModeView)
{
if (!IsStackActivate())
{
return false;
}
UpdateStack(deltaTime);
BlendStack(outCameraModeView);
return true;
}
void UOLSCameraModeStack::DrawDebug(UCanvas* canvas) const
{
check(canvas);
FDisplayDebugManager& displayDebugManager = canvas->DisplayDebugManager;
displayDebugManager.SetDrawColor(FColor::Green);
displayDebugManager.DrawString(FString(TEXT(" --- Camera Modes (Begin) ---")));
for (const UOLSCameraMode* cameraMode : CameraModeStack)
{
check(cameraMode);
cameraMode->DrawDebug(canvas);
}
displayDebugManager.SetDrawColor(FColor::Green);
displayDebugManager.DrawString(FString::Printf(TEXT(" --- Camera Modes (End) ---")));
}
void UOLSCameraModeStack::GetBlendInfo(float& outWeightOfTopLayer, FGameplayTag& outTagOfTopLayer) const
{
if (CameraModeStack.Num() == 0)
{
outWeightOfTopLayer = 1.0f;
outTagOfTopLayer = FGameplayTag();
return;
}
UOLSCameraMode* topEntry = CameraModeStack.Last();
check(topEntry);
outWeightOfTopLayer = topEntry->GetBlendWeight();
outTagOfTopLayer = topEntry->GetCameraTypeTag();
}
UOLSCameraMode* UOLSCameraModeStack::GetCameraModeInstance(TSubclassOf<UOLSCameraMode> cameraModeClass)
{
check(cameraModeClass);
// First see if we already created one.
for (UOLSCameraMode* cameraMode : CameraModeInstances)
{
if ((cameraMode != nullptr) && (cameraMode->GetClass() == cameraModeClass))
{
return cameraMode;
}
}
// Not found, so we need to create it.
UOLSCameraMode* newCameraMode = NewObject<UOLSCameraMode>(GetOuter(), cameraModeClass, NAME_None, RF_NoFlags);
check(newCameraMode);
CameraModeInstances.Add(newCameraMode);
return newCameraMode;
}
void UOLSCameraModeStack::UpdateStack(float deltaTime)
{
const int32 stackSize = CameraModeStack.Num();
if (stackSize <= 0)
{
return;
}
int32 removeCount = 0;
int32 removeIndex = INDEX_NONE;
for (int32 stackIndex = 0; stackIndex < stackSize; ++stackIndex)
{
UOLSCameraMode* cameraMode = CameraModeStack[stackIndex];
check(cameraMode);
cameraMode->UpdateCameraMode(deltaTime);
if (cameraMode->GetBlendWeight() >= 1.0f)
{
// Everything below this mode is now irrelevant and can be removed.
removeIndex = (stackIndex + 1);
removeCount = (stackSize - removeIndex);
break;
}
}
if (removeCount > 0)
{
// Let the camera modes know they being removed from the stack.
for (int32 stackIndex = removeIndex; stackIndex < stackSize; ++stackIndex)
{
UOLSCameraMode* cameraMode = CameraModeStack[stackIndex];
check(cameraMode);
cameraMode->OnDeactivation();
}
CameraModeStack.RemoveAt(removeIndex, removeCount);
}
}
void UOLSCameraModeStack::BlendStack(FOLSCameraModeView& outCameraModeView) const
{
const int32 stackSize = CameraModeStack.Num();
if (stackSize <= 0)
{
return;
}
// Start at the bottom and blend up the stack
const UOLSCameraMode* cameraMode = CameraModeStack[stackSize - 1];
check(cameraMode);
outCameraModeView = cameraMode->GetCameraModeView();
for (int32 stackIndex = (stackSize - 2); stackIndex >= 0; --stackIndex)
{
cameraMode = CameraModeStack[stackIndex];
check(cameraMode);
outCameraModeView.Blend(cameraMode->GetCameraModeView(), cameraMode->GetBlendWeight());
}
}

View File

@ -0,0 +1,61 @@
// © 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 "Camera/OLSPlayerCameraManager.h"
#include "Camera/Components/OLSCameraComponent.h"
#include "Camera/Components/OLSUICameraManagerComponent.h"
#include "Engine/Canvas.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSPlayerCameraManager)
static FName UICameraComponentName(TEXT("UICameraComponent"));
AOLSPlayerCameraManager::AOLSPlayerCameraManager(const FObjectInitializer& objectInitializer)
: Super(objectInitializer)
{
DefaultFOV = OLS_CAMERA_DEFAULT_FOV;
ViewPitchMin = OLS_CAMERA_DEFAULT_PITCH_MIN;
ViewPitchMax = OLS_CAMERA_DEFAULT_PITCH_MAX;
UICameraComponent = CreateDefaultSubobject<UOLSUICameraManagerComponent>(UICameraComponentName);
}
UOLSUICameraManagerComponent* AOLSPlayerCameraManager::GetUICameraComponent() const
{
return UICameraComponent;
}
void AOLSPlayerCameraManager::UpdateViewTarget(FTViewTarget& outVT, float deltaTime)
{
// If the UI Camera is looking at something, let it have priority.
if (UICameraComponent->NeedsToUpdateViewTarget())
{
Super::UpdateViewTarget(outVT, deltaTime);
UICameraComponent->UpdateViewTarget(outVT, deltaTime);
return;
}
Super::UpdateViewTarget(outVT, deltaTime);
}
void AOLSPlayerCameraManager::DisplayDebug(UCanvas* canvas, const FDebugDisplayInfo& debugDisplay,
float& yl, float& yPos)
{
check(canvas);
FDisplayDebugManager& displayDebugManager = canvas->DisplayDebugManager;
displayDebugManager.SetFont(GEngine->GetSmallFont());
displayDebugManager.SetDrawColor(FColor::Yellow);
displayDebugManager.DrawString(FString::Printf(TEXT("LyraPlayerCameraManager: %s"), *GetNameSafe(this)));
Super::DisplayDebug(canvas, debugDisplay, yl, yPos);
const APawn* pawn = (PCOwner ? PCOwner->GetPawn() : nullptr);
if (const UOLSCameraComponent* cameraComponent = UOLSCameraComponent::FindCameraComponent(pawn))
{
cameraComponent->DrawDebug(canvas);
}
}

View File

@ -6,6 +6,7 @@
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "OLSLog.h" #include "OLSLog.h"
#include "AbilitySystem/OLSAbilitySystemComponent.h" #include "AbilitySystem/OLSAbilitySystemComponent.h"
#include "Camera/OLSCameraMode.h"
#include "Characters/OLSCharacter.h" #include "Characters/OLSCharacter.h"
#include "Components/GameFrameworkComponentManager.h" #include "Components/GameFrameworkComponentManager.h"
#include "Components/OLSPawnExtensionComponent.h" #include "Components/OLSPawnExtensionComponent.h"
@ -31,8 +32,7 @@ const FName UOLSHeroComponent::NAME_ActorFeatureName("Hero");
UOLSHeroComponent::UOLSHeroComponent(const FObjectInitializer& objectInitializer) : Super(objectInitializer) UOLSHeroComponent::UOLSHeroComponent(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{ {
//@TODO: implement UOLSCameraMode. AbilityCameraMode = nullptr;
// AbilityCameraMode = nullptr;
bIsReadyToBindInputs = false; bIsReadyToBindInputs = false;
} }
@ -154,11 +154,11 @@ void UOLSHeroComponent::HandleChangeInitState(UGameFrameworkComponentManager* ma
// } // }
// } // }
// //
// //@TODO: implement UOLSCameraMode. //
// // Hook up the delegate for all pawns, in case we spectate later // // Hook up the delegate for all pawns, in case we spectate later
// // if (pawnData) // // if (pawnData)
// // { // // {
// // if (ULyraCameraComponent* CameraComponent = ULyraCameraComponent::FindCameraComponent(pawn)) // // if (UOLSCameraComponent* CameraComponent = UOLSCameraComponent::FindCameraComponent(pawn))
// // { // // {
// // CameraComponent->DetermineCameraModeDelegate.BindUObject(this, &ThisClass::DetermineCameraMode); // // CameraComponent->DetermineCameraModeDelegate.BindUObject(this, &ThisClass::DetermineCameraMode);
// // } // // }
@ -199,6 +199,11 @@ UOLSHeroComponent* UOLSHeroComponent::FindHeroComponent(const AActor* actor)
return (actor ? actor->FindComponentByClass<UOLSHeroComponent>() : nullptr); return (actor ? actor->FindComponentByClass<UOLSHeroComponent>() : nullptr);
} }
void UOLSHeroComponent::SetAbilityCameraMode(TSubclassOf<UOLSCameraMode> CameraMode,
const FGameplayAbilitySpecHandle& OwningSpecHandle)
{
}
void UOLSHeroComponent::ClearAbilityCameraMode(const FGameplayAbilitySpecHandle& owningSpecHandle) void UOLSHeroComponent::ClearAbilityCameraMode(const FGameplayAbilitySpecHandle& owningSpecHandle)
{ {
if (AbilityCameraModeOwningSpecHandle == owningSpecHandle) if (AbilityCameraModeOwningSpecHandle == owningSpecHandle)
@ -520,3 +525,27 @@ void UOLSHeroComponent::Input_AutoRun(const FInputActionValue& inputActionValue)
} }
} }
} }
TSubclassOf<UOLSCameraMode> UOLSHeroComponent::DetermineCameraMode() const
{
if (AbilityCameraMode)
{
return AbilityCameraMode;
}
const APawn* Pawn = GetPawn<APawn>();
if (!Pawn)
{
return nullptr;
}
if (UOLSPawnExtensionComponent* pawnExtComp = UOLSPawnExtensionComponent::FindPawnExtensionComponent(Pawn))
{
if (const UOLSPawnDataAsset* pawnData = pawnExtComp->GetPawnData<UOLSPawnDataAsset>())
{
return pawnData->DefaultCameraMode;
}
}
return nullptr;
}

View File

@ -5,7 +5,9 @@
#include "CommonUserSubsystem.h" #include "CommonUserSubsystem.h"
#include "GameMapsSettings.h" #include "GameMapsSettings.h"
#include "OLSLog.h"
#include "Characters/OLSCharacter.h" #include "Characters/OLSCharacter.h"
#include "Components/OLSPawnExtensionComponent.h"
#include "DataAssets/OLSExperienceDefinitionDataAsset.h" #include "DataAssets/OLSExperienceDefinitionDataAsset.h"
#include "DataAssets/OLSPawnDataAsset.h" #include "DataAssets/OLSPawnDataAsset.h"
#include "GameModes/OLSExperienceManagerComponent.h" #include "GameModes/OLSExperienceManagerComponent.h"
@ -15,11 +17,15 @@
#include "Player/OLSPlayerState.h" #include "Player/OLSPlayerState.h"
#include "Systems/OLSAssetManager.h" #include "Systems/OLSAssetManager.h"
#include "Systems/OLSGameSession.h" #include "Systems/OLSGameSession.h"
#include "CommonUserSubsystem.h"
#include "CommonSessionSubsystem.h"
#include "UI/OLSHUD.h" #include "UI/OLSHUD.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(OLSGameMode) #include UE_INLINE_GENERATED_CPP_BY_NAME(OLSGameMode)
DEFINE_LOG_CATEGORY(LogOLSGameMode);
AOLSGameMode::AOLSGameMode(const FObjectInitializer& objectInitializer) : Super(objectInitializer) AOLSGameMode::AOLSGameMode(const FObjectInitializer& objectInitializer) : Super(objectInitializer)
{ {
GameStateClass = AOLSGameState::StaticClass(); GameStateClass = AOLSGameState::StaticClass();
@ -100,32 +106,29 @@ APawn* AOLSGameMode::SpawnDefaultPawnAtTransform_Implementation(
{ {
if (APawn* spawnedPawn = GetWorld()->SpawnActor<APawn>(pawnClass, spawnTransform, spawnInfo)) if (APawn* spawnedPawn = GetWorld()->SpawnActor<APawn>(pawnClass, spawnTransform, spawnInfo))
{ {
// @TODO: Implement this as well as implement UOLSawnExtensionComponent if (UOLSPawnExtensionComponent* pawnExtComp = UOLSPawnExtensionComponent::FindPawnExtensionComponent(spawnedPawn))
// if (UOLSawnExtensionComponent* PawnExtComp = UOLSawnExtensionComponent::FindPawnExtensionComponent(spawnedPawn)) {
// { if (const UOLSPawnDataAsset* pawnData = GetPawnDataForController(newPlayer))
// if (const ULyraPawnData* PawnData = GetPawnDataForController(newPlayer)) {
// { pawnExtComp->SetPawnData(pawnData);
// PawnExtComp->SetPawnData(PawnData); }
// } else
// else {
// { // @TODO: Replace this with out custom log. OLS_LOG(LogOLSGameMode, Error,
// UE_LOG(LogLyra, Error, TEXT("Game mode was unable to set PawnData on the spawned pawn [%s]."), *GetNameSafe(spawnedPawn } TEXT("Game mode was unable to set PawnData on the spawned pawn [%s]."),
// } *GetNameSafe(spawnedPawn));
}
}
spawnedPawn->FinishSpawning(spawnTransform); spawnedPawn->FinishSpawning(spawnTransform);
return spawnedPawn; return spawnedPawn;
} }
else OLS_LOG(LogOLSGameMode, Error, TEXT("Game mode was unable to spawn Pawn of class [%s] at [%s]."), *GetNameSafe(pawnClass), *spawnTransform.ToHumanReadableString());
{
// @TODO: Replace this with out custom log.
// UE_LOG(LogLyra, Error, TEXT("Game mode was unable to spawn Pawn of class [%s] at [%s]."), *GetNameSafe(pawnClass), *spawnTransform.ToHumanReadableString());
}
} }
else else
{ {
// @TODO: Replace this with out custom log. OLS_LOG(LogOLSGameMode, Error, TEXT("Game mode was unable to spawn Pawn due to NULL pawn class."));
// UE_LOG(LogLyra, Error, TEXT("Game mode was unable to spawn Pawn due to NULL pawn class."));
} }
return nullptr; return nullptr;
@ -308,8 +311,7 @@ void AOLSGameMode::OnMatchAssignmentGiven(FPrimaryAssetId experienceId, const FS
{ {
if (experienceId.IsValid()) if (experienceId.IsValid())
{ {
// @TODO: Replace this with our custom. OLS_LOG(LogOLSGameMode, Log, TEXT("Identified experience %s (Source: %s)"), *experienceId.ToString(), *experienceIdSource);
// UE_LOG(LogLyraExperience, Log, TEXT("Identified experience %s (Source: %s)"), *ExperienceId.ToString(), *ExperienceIdSource);
UOLSExperienceManagerComponent* experienceComponent = GameState->FindComponentByClass<UOLSExperienceManagerComponent>(); UOLSExperienceManagerComponent* experienceComponent = GameState->FindComponentByClass<UOLSExperienceManagerComponent>();
check(experienceComponent); check(experienceComponent);
@ -317,8 +319,7 @@ void AOLSGameMode::OnMatchAssignmentGiven(FPrimaryAssetId experienceId, const FS
} }
else else
{ {
// @TODO: Replace this with our custom. OLS_LOG(LogOLSGameMode, Error, TEXT("Failed to identify experience, loading screen will stay up forever"));
// UE_LOG(LogLyraExperience, Error, TEXT("Failed to identify experience, loading screen will stay up forever"));
} }
} }
@ -382,8 +383,7 @@ void AOLSGameMode::HandleMatchAssignmentIfNotExpectingOne()
FAssetData dummy; FAssetData dummy;
if (experienceId.IsValid() && !assetManager.GetPrimaryAssetData(experienceId, /*out*/ dummy)) if (experienceId.IsValid() && !assetManager.GetPrimaryAssetData(experienceId, /*out*/ dummy))
{ {
// @TODO: Replace this with our custom. OLS_LOG(LogOLSGameMode, Error, TEXT("EXPERIENCE: Wanted to use %s but couldn't find it, falling back to the default)"), *experienceId.ToString());
// UE_LOG(LogLyraExperience, Error, TEXT("EXPERIENCE: Wanted to use %s but couldn't find it, falling back to the default)"), *experienceIding());
experienceId = FPrimaryAssetId(); experienceId = FPrimaryAssetId();
} }
@ -397,7 +397,7 @@ void AOLSGameMode::HandleMatchAssignmentIfNotExpectingOne()
} }
//@TODO: Pull this from a config setting or something //@TODO: Pull this from a config setting or something
experienceId = FPrimaryAssetId(FPrimaryAssetType("LyraExperienceDefinition"), FName("B_LyraDefaultExperience")); experienceId = FPrimaryAssetId(FPrimaryAssetType("OLSExperienceDefinition"), FName("B_OLSDefaultExperience"));
experienceIdSource = TEXT("Default"); experienceIdSource = TEXT("Default");
} }
@ -513,19 +513,21 @@ void AOLSGameMode::OnUserInitializedForDedicatedServer(
if (gameInstance) if (gameInstance)
{ {
// Unbind // Unbind
UCommonUserSubsystem* UserSubsystem = gameInstance->GetSubsystem<UCommonUserSubsystem>(); UCommonUserSubsystem* userSubsystem = gameInstance->GetSubsystem<UCommonUserSubsystem>();
UserSubsystem->OnUserInitializeComplete.RemoveDynamic(this, &ThisClass::OnUserInitializedForDedicatedServer); userSubsystem->OnUserInitializeComplete.RemoveDynamic(this, &ThisClass::OnUserInitializedForDedicatedServer);
// Dedicated servers do not require user login, but some online subsystems may expect it // Dedicated servers do not require user login, but some online subsystems may expect it
if (isSuccess && ensure(userInfo)) if (isSuccess && ensure(userInfo))
{ {
// @TODO: replace this with our custom. // @TODO: Fix compiler error.
// UE_LOG(LogLyraExperience, Log, TEXT("Dedicated server user login succeeded for id %s, starting online server"), *UserInfo->GetNetId().ToString()); // OLS_LOG(LogOLSGameMode, Log,
// TEXT("Dedicated server user login succeeded for id %s, starting online server"),
// *userInfo->GetNetId().ToString());
} }
else else
{ {
// @TODO: replace this with our custom. OLS_LOG(LogOLSGameMode, Log,
// UE_LOG(LogLyraExperience, Log, TEXT("Dedicated server user login unsuccessful, starting online server as login is not required")); TEXT("Dedicated server user login unsuccessful, starting online server as login is not required"));
} }
HostDedicatedServerMatch(ECommonSessionOnlineMode::Online); HostDedicatedServerMatch(ECommonSessionOnlineMode::Online);

View File

@ -118,14 +118,13 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "OLS|Ability", Meta = (ExpandBoolAsExecs = "ReturnValue")) UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "OLS|Ability", Meta = (ExpandBoolAsExecs = "ReturnValue"))
bool ChangeActivationGroup(EOLSAbilityActivationGroup newGroup); bool ChangeActivationGroup(EOLSAbilityActivationGroup newGroup);
// @TODO: Implement OLSCameraMode. // Sets the ability's camera mode.
// // Sets the ability's camera mode. UFUNCTION(BlueprintCallable, Category = "Lyra|Ability")
// UFUNCTION(BlueprintCallable, Category = "Lyra|Ability") void SetCameraMode(TSubclassOf<class UOLSCameraMode> cameraMode);
// void SetCameraMode(TSubclassOf<ULyraCameraMode> CameraMode);
// // Clears the ability's camera mode. Automatically called if needed when the ability ends.
// // Clears the ability's camera mode. Automatically called if needed when the ability ends. UFUNCTION(BlueprintCallable, Category = "Lyra|Ability")
// UFUNCTION(BlueprintCallable, Category = "Lyra|Ability") void ClearCameraMode();
// void ClearCameraMode();
public: public:
@ -188,7 +187,6 @@ protected:
UPROPERTY(EditDefaultsOnly, Category = "Advanced") UPROPERTY(EditDefaultsOnly, Category = "Advanced")
uint8 bShouldLogCancellation : 1 = false; uint8 bShouldLogCancellation : 1 = false;
// @TODO: Implement OLSCameraMode
// Current camera mode set by the ability. // Current camera mode set by the ability.
// TSubclassOf<OLSCameraMode> ActiveCameraMode; TSubclassOf<class UOLSCameraMode> ActiveCameraMode;
}; };

View File

@ -160,7 +160,7 @@ protected:
virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability) override; virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability) override;
virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability, const FGameplayTagContainer& failureReason) override; virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability, const FGameplayTagContainer& failureReason) override;
virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle handle, class UGameplayAbility* Ability, bool bWasCancelled) override; virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle handle, class UGameplayAbility* ability, bool bWasCancelled) override;
virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool shouldEnableBlockTags, const FGameplayTagContainer& blockTags, bool shouldExecuteCancelTags, const FGameplayTagContainer& cancelTags) override; virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool shouldEnableBlockTags, const FGameplayTagContainer& blockTags, bool shouldExecuteCancelTags, const FGameplayTagContainer& cancelTags) override;
virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool canBeCanceled) override; virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& abilityTags, class UGameplayAbility* requestingAbility, bool canBeCanceled) override;

View File

@ -0,0 +1,61 @@
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
#pragma once
#include "CoreMinimal.h"
#include "Camera/CameraComponent.h"
#include "GameplayTagContainer.h"
#include "OLSCameraComponent.generated.h"
DECLARE_DELEGATE_RetVal(TSubclassOf<class UOLSCameraMode>, FOLSCameraModeDelegate);
/**
* UOLSCameraComponent
*
* The base camera component class used by this project.
*/
UCLASS()
class OLS_API UOLSCameraComponent : public UCameraComponent
{
GENERATED_BODY()
public:
UOLSCameraComponent(const FObjectInitializer& objectInitializer);
// Returns the camera component if one exists on the specified actor.
UFUNCTION(BlueprintPure, Category = "OLS|Camera")
static UOLSCameraComponent* FindCameraComponent(const AActor* Actor);
// Returns the target actor that the camera is looking at.
virtual AActor* GetTargetActor() const;
// Delegate used to query for the best camera mode.
FOLSCameraModeDelegate DetermineCameraModeDelegate;
// Add an offset to the field of view. The offset is only for one frame, it gets cleared once it is applied.
void AddFieldOfViewOffset(float FovOffset);
virtual void DrawDebug(UCanvas* canvas) const;
// Gets the tag associated with the top layer and the blend weight of it
void GetBlendInfo(float& outWeightOfTopLayer, FGameplayTag& outTagOfTopLayer) const;
protected:
virtual void OnRegister() override;
virtual void GetCameraView(float deltaTime, FMinimalViewInfo& desiredView) override;
virtual void UpdateCameraModes();
protected:
// Stack used to blend the camera modes.
UPROPERTY()
TObjectPtr<class UOLSCameraModeStack> CameraModeStack = nullptr;
// Offset applied to the field of view. The offset is only for one frame, it gets cleared once it is applied.
float FieldOfViewOffset = 0.0f;
};

View File

@ -0,0 +1,37 @@
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "OLSUICameraManagerComponent.generated.h"
UCLASS( Transient, Within=OLSPlayerCameraManager )
class UOLSUICameraManagerComponent : public UActorComponent
{
GENERATED_BODY()
public:
static class UOLSUICameraManagerComponent* GetComponent(APlayerController* playerController);
public:
UOLSUICameraManagerComponent();
bool IsSettingViewTarget() const;
AActor* GetViewTarget() const;
void SetViewTarget(AActor* viewTarget, FViewTargetTransitionParams transitionParams = FViewTargetTransitionParams());
bool NeedsToUpdateViewTarget() const;
void UpdateViewTarget(struct FTViewTarget& outVT, float deltaTime);
void OnShowDebugInfo(AHUD* hud, UCanvas* canvas, const FDebugDisplayInfo& displayInfo, float& yl, float& yPos);
private:
UPROPERTY()
TObjectPtr<class AActor> ViewTarget = nullptr;;
UPROPERTY(Transient)
bool bShouldUpdatingViewTarget = false;
};

View File

@ -0,0 +1,39 @@
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "OLSCameraAssistInterface.generated.h"
UINTERFACE(BlueprintType)
class UOLSCameraAssistInterface : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class IOLSCameraAssistInterface
{
GENERATED_BODY()
public:
/**
* Get the list of actors that we're allowing the camera to penetrate. Useful in 3rd person cameras
* when you need the following camera to ignore things like the a collection of view targets, the pawn,
* a vehicle..etc.
*/
virtual void GetIgnoredActorsForCameraPenetration(TArray<const AActor*>& outActorsAllowPenetration) const;
/**
* The target actor to prevent penetration on. Normally, this is almost always the view target, which if
* unimplemented will remain true. However, sometimes the view target, isn't the same as the root actor
* you need to keep in frame.
*/
virtual TOptional<AActor*> GetCameraPreventPenetrationTarget() const;
/** Called if the camera penetrates the focal target. Useful if you want to hide the target actor when being overlapped. */
virtual void OnCameraPenetratingTarget();
};

View File

@ -0,0 +1,191 @@
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "UObject/Object.h"
#include "OLSCameraMode.generated.h"
/**
* EOLSCameraModeBlendFunction
*
* Blend function used for transitioning between camera modes.
*/
UENUM(BlueprintType)
enum class EOLSCameraModeBlendFunction : uint8
{
// Does a simple linear interpolation.
Linear,
// Immediately accelerates, but smoothly decelerates into the target. Ease amount controlled by the exponent.
EaseIn,
// Smoothly accelerates, but does not decelerate into the target. Ease amount controlled by the exponent.
EaseOut,
// Smoothly accelerates and decelerates. Ease amount controlled by the exponent.
EaseInOut,
COUNT UMETA(Hidden)
};
/**
* FOLSCameraModeView
*
* View data produced by the camera mode that is used to blend camera modes.
*/
struct FOLSCameraModeView
{
public:
FOLSCameraModeView();
void Blend(const FOLSCameraModeView& other, float otherWeight);
public:
FVector Location;
FRotator Rotation;
FRotator ControlRotation;
float FieldOfView;
};
/**
* UOLSCameraMode
*
* Base class for all camera modes.
*/
UCLASS(Abstract, NotBlueprintable)
class OLS_API UOLSCameraMode : public UObject
{
GENERATED_BODY()
public:
UOLSCameraMode();
class UOLSCameraComponent* GetOLSCameraComponent() const;
virtual UWorld* GetWorld() const override;
AActor* GetTargetActor() const;
const FOLSCameraModeView& GetCameraModeView() const;
// Called when this camera mode is activated on the camera mode stack.
virtual void OnActivation();
// Called when this camera mode is deactivated on the camera mode stack.
virtual void OnDeactivation();
void UpdateCameraMode(float deltaTime);
float GetBlendTime() const;
float GetBlendWeight() const;
void SetBlendWeight(float weight);
FGameplayTag GetCameraTypeTag() const;
virtual void DrawDebug(UCanvas* canvas) const;
protected:
virtual FVector GetPivotLocation() const;
virtual FRotator GetPivotRotation() const;
virtual void UpdateView(float deltaTime);
virtual void UpdateBlending(float deltaTime);
protected:
// A tag that can be queried by gameplay code that cares when a kind of camera mode is active
// without having to ask about a specific mode (e.g., when aiming downsights to get more accuracy)
UPROPERTY(EditDefaultsOnly, Category = "Blending")
FGameplayTag CameraTypeTag = FGameplayTag::EmptyTag;
// View output produced by the camera mode.
FOLSCameraModeView View;
// The horizontal field of view (in degrees).
UPROPERTY(EditDefaultsOnly, Category = "View", Meta = (UIMin = "5.0", UIMax = "170", ClampMin = "5.0", ClampMax = "170.0"))
float FieldOfView = 0.0f;
// Minimum view pitch (in degrees).
UPROPERTY(EditDefaultsOnly, Category = "View", Meta = (UIMin = "-89.9", UIMax = "89.9", ClampMin = "-89.9", ClampMax = "89.9"))
float ViewPitchMin = 0.0f;
// Maximum view pitch (in degrees).
UPROPERTY(EditDefaultsOnly, Category = "View", Meta = (UIMin = "-89.9", UIMax = "89.9", ClampMin = "-89.9", ClampMax = "89.9"))
float ViewPitchMax = 0.0f;
// How long it takes to blend in this mode.
UPROPERTY(EditDefaultsOnly, Category = "Blending")
float BlendTime = 0.0f;
// Function used for blending.
UPROPERTY(EditDefaultsOnly, Category = "Blending")
EOLSCameraModeBlendFunction BlendFunction = EOLSCameraModeBlendFunction::Linear;
// Exponent used by blend functions to control the shape of the curve.
UPROPERTY(EditDefaultsOnly, Category = "Blending")
float BlendExponent = 0.0f;
// Linear blend alpha used to determine the blend weight.
float BlendAlpha = 0.0f;
// Blend weight calculated using the blend alpha and function.
float BlendWeight = 0.0f;
protected:
/** If true, skips all interpolation and puts camera in ideal location. Automatically set to false next frame. */
UPROPERTY(Transient)
uint32 bShouldResetInterpolation : 1 = false;
};
/**
* UOLSCameraModeStack
*
* Stack used for blending camera modes.
*/
UCLASS()
class UOLSCameraModeStack : public UObject
{
GENERATED_BODY()
public:
UOLSCameraModeStack();
void ActivateStack();
void DeactivateStack();
bool IsStackActivate() const;
void PushCameraMode(TSubclassOf<UOLSCameraMode> cameraModeClass);
bool EvaluateStack(float deltaTime, FOLSCameraModeView& outCameraModeView);
void DrawDebug(UCanvas* canvas) const;
// Gets the tag associated with the top layer and the blend weight of it
void GetBlendInfo(float& outWeightOfTopLayer, FGameplayTag& outTagOfTopLayer) const;
protected:
UOLSCameraMode* GetCameraModeInstance(TSubclassOf<UOLSCameraMode> cameraModeClass);
void UpdateStack(float deltaTime);
void BlendStack(FOLSCameraModeView& outCameraModeView) const;
protected:
uint8 bIsStackActive : 1 = true;
UPROPERTY()
TArray<TObjectPtr<UOLSCameraMode>> CameraModeInstances;
UPROPERTY()
TArray<TObjectPtr<UOLSCameraMode>> CameraModeStack;
};

View File

@ -0,0 +1,40 @@
// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.
#pragma once
#include "CoreMinimal.h"
#include "Camera/PlayerCameraManager.h"
#include "OLSPlayerCameraManager.generated.h"
#define OLS_CAMERA_DEFAULT_FOV (80.0f)
#define OLS_CAMERA_DEFAULT_PITCH_MIN (-89.0f)
#define OLS_CAMERA_DEFAULT_PITCH_MAX (89.0f)
/**
* AOLSPlayerCameraManager
*
* The base player camera manager class used by this project.
*/
UCLASS(NotPlaceable, MinimalAPI)
class AOLSPlayerCameraManager : public APlayerCameraManager
{
GENERATED_BODY()
public:
AOLSPlayerCameraManager(const FObjectInitializer& objectInitializer);
class UOLSUICameraManagerComponent* GetUICameraComponent() const;
protected:
virtual void UpdateViewTarget(FTViewTarget& outVT, float deltaTime) override;
virtual void DisplayDebug(UCanvas* canvas, const FDebugDisplayInfo& debugDisplay, float& yl, float& yPos) override;
private:
/** The UI Camera Component, controls the camera when UI is doing something important that gameplay doesn't get priority over. */
UPROPERTY()
TObjectPtr<class UOLSUICameraManagerComponent> UICameraComponent = nullptr;
};

View File

@ -45,8 +45,7 @@ public:
/** Overrides the camera from an active gameplay ability */ /** Overrides the camera from an active gameplay ability */
//@TODO: implement UOLSCameraMode. void SetAbilityCameraMode(TSubclassOf<class UOLSCameraMode> CameraMode, const FGameplayAbilitySpecHandle& OwningSpecHandle);
// void SetAbilityCameraMode(TSubclassOf<ULyraCameraMode> CameraMode, const FGameplayAbilitySpecHandle& OwningSpecHandle);
/** Clears the camera override if it is set */ /** Clears the camera override if it is set */
void ClearAbilityCameraMode(const FGameplayAbilitySpecHandle& owningSpecHandle); void ClearAbilityCameraMode(const FGameplayAbilitySpecHandle& owningSpecHandle);
@ -79,8 +78,7 @@ protected:
void Input_Crouch(const struct FInputActionValue& InputActionValue); void Input_Crouch(const struct FInputActionValue& InputActionValue);
void Input_AutoRun(const struct FInputActionValue& inputActionValue); void Input_AutoRun(const struct FInputActionValue& inputActionValue);
//@TODO: implement UOLSCameraMode. TSubclassOf<class UOLSCameraMode> DetermineCameraMode() const;
// TSubclassOf<ULyraCameraMode> DetermineCameraMode() const;
protected: protected:
@ -88,8 +86,8 @@ protected:
TArray<struct FOLSInputMappingContextAndPriority> DefaultInputMappings; TArray<struct FOLSInputMappingContextAndPriority> DefaultInputMappings;
/** Camera mode set by an ability. */ /** Camera mode set by an ability. */
// UPROPERTY() UPROPERTY()
// TSubclassOf<ULyraCameraMode> AbilityCameraMode; TSubclassOf<class UOLSCameraMode> AbilityCameraMode;
/** Spec handle for the last ability to set a camera mode. */ /** Spec handle for the last ability to set a camera mode. */
FGameplayAbilitySpecHandle AbilityCameraModeOwningSpecHandle; FGameplayAbilitySpecHandle AbilityCameraModeOwningSpecHandle;

View File

@ -43,8 +43,7 @@ public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Input") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "OLS|Input")
TObjectPtr<class UOLSInputConfigDataAsset> InputConfig = nullptr; TObjectPtr<class UOLSInputConfigDataAsset> InputConfig = nullptr;
// @Todo: implement DefaultCamera mode here.
// Default camera mode used by player controlled pawns. // Default camera mode used by player controlled pawns.
// UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Camera") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Lyra|Camera")
// TSubclassOf<ULyraCameraMode> DefaultCameraMode = nullptr; TSubclassOf<class UOLSCameraMode> DefaultCameraMode = nullptr;
}; };

View File

@ -7,6 +7,8 @@
#include "ModularGameplayActors/OLSModularGameMode.h" #include "ModularGameplayActors/OLSModularGameMode.h"
#include "OLSGameMode.generated.h" #include "OLSGameMode.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogOLSGameMode, Verbose, All);
/** /**
* Post login event, triggered when a player or bot joins the game as well as after seamless and non seamless travel * Post login event, triggered when a player or bot joins the game as well as after seamless and non seamless travel
* *
@ -15,7 +17,6 @@
DECLARE_MULTICAST_DELEGATE_TwoParams(FOLSGameModePlayerInitializeNativeDelegate, class AGameModeBase* /*GameMode*/, DECLARE_MULTICAST_DELEGATE_TwoParams(FOLSGameModePlayerInitializeNativeDelegate, class AGameModeBase* /*GameMode*/,
class AController* /*NewPlayer*/); class AController* /*NewPlayer*/);
/** /**
* AOLSGameMode * AOLSGameMode
* *