// © 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 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 cameraModeClass); void UpdateStack(float deltaTime); void BlendStack(FOLSCameraModeView& outCameraModeView) const; protected: uint8 bIsStackActive : 1 = true; UPROPERTY() TArray> CameraModeInstances; UPROPERTY() TArray> CameraModeStack; };