// Copyright Epic Games, Inc. All Rights Reserved. #include "CineCameraComponent.h" #include "UObject/CineCameraObjectVersion.h" #include "UObject/ReleaseObjectVersion.h" #include "UObject/ConstructorHelpers.h" #include "GameFramework/Actor.h" #include "Engine/World.h" #include "Components/StaticMeshComponent.h" #include "Engine/StaticMesh.h" #include "Engine/CollisionProfile.h" #include "Materials/Material.h" #include "GameFramework/WorldSettings.h" #include "Materials/MaterialInstanceDynamic.h" #include "DrawDebugHelpers.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(CineCameraComponent) #define LOCTEXT_NAMESPACE "CineCameraComponent" ////////////////////////////////////////////////////////////////////////// // UCameraComponent /// @cond DOXYGEN_WARNINGS UCineCameraComponent::UCineCameraComponent() { // Super 35mm 4 Perf // Default filmback and lens settings will be overridden if valid default presets are specified in ini #if WITH_EDITORONLY_DATA bTickInEditor = true; #endif // NOTE: in UE 5.3 and onward, classes deriving from this component must explicitly register for tick if // overriding the tick function, since this class only ticks productively with the following defines on #if WITH_EDITORONLY_DATA || ENABLE_DRAW_DEBUG PrimaryComponentTick.bCanEverTick = true; #endif bAutoActivate = true; bConstrainAspectRatio = true; const UCineCameraSettings* CineCameraSettings = GetDefault(); check(CineCameraSettings); // default filmback SetFilmbackPresetByNameInternal(CineCameraSettings->DefaultFilmbackPreset, Filmback); SetFilmbackPresetByNameInternal(CineCameraSettings->DefaultFilmbackPreset, FilmbackSettings_DEPRECATED); SetLensPresetByNameInternal(CineCameraSettings->DefaultLensPresetName); SetCropPresetByNameInternal(CineCameraSettings->DefaultCropPresetName); // other lens defaults CurrentAperture = CineCameraSettings->DefaultLensFStop; CurrentFocalLength = CineCameraSettings->DefaultLensFocalLength; RecalcDerivedData(); #if WITH_EDITORONLY_DATA if (!IsRunningCommandlet()) { // overrides CameraComponent's camera mesh static ConstructorHelpers::FObjectFinder EditorCameraMesh(TEXT("/Engine/EditorMeshes/Camera/SM_CineCam.SM_CineCam")); CameraMesh = EditorCameraMesh.Object; } static ConstructorHelpers::FObjectFinder PlaneMesh(TEXT("/Engine/ArtTools/RenderToTexture/Meshes/S_1_Unit_Plane.S_1_Unit_Plane")); FocusPlaneVisualizationMesh = PlaneMesh.Object; static ConstructorHelpers::FObjectFinder PlaneMat(TEXT("/Engine/EngineDebugMaterials/M_SimpleUnlitTranslucent.M_SimpleUnlitTranslucent")); FocusPlaneVisualizationMaterial = PlaneMat.Object; #endif CustomNearClippingPlane = GNearClippingPlane; bOverride_CustomNearClippingPlane = false; } void UCineCameraComponent::Serialize(FArchive& Ar) { PRAGMA_DISABLE_DEPRECATION_WARNINGS Ar.UsingCustomVersion(FCineCameraObjectVersion::GUID); Ar.UsingCustomVersion(FReleaseObjectVersion::GUID); Super::Serialize(Ar); if (Ar.IsLoading() && Ar.CustomVer(FReleaseObjectVersion::GUID) < FReleaseObjectVersion::DeprecateFilmbackSettings) { bool bUpgradeFilmback = true; if (Ar.CustomVer(FCineCameraObjectVersion::GUID) == FCineCameraObjectVersion::ChangeDefaultFilmbackToDigitalFilm) { UCineCameraComponent* Template = Cast(GetArchetype()); if (Template) { TArray const& Presets = UCineCameraSettings::GetFilmbackPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedFilmbackPreset const& P = Presets[PresetIdx]; // ChangeDefaultFilmbackToDigitalFilm was pre 4.24, but post 4.23. In that case, the filmback settings would have been DSLR // and RecalcDerivedData would not have been called yet, which equates to SensorAspectRatio being left at 1.33f. This isn't // ideal for detecting this case, but it's the best notion of whether upgrading this film back should be skipped and get its // values from the default template object, which is the new Digital Film default. if (P.FilmbackSettings == FilmbackSettings_DEPRECATED && FilmbackSettings_DEPRECATED.SensorAspectRatio == 1.33f) { if (P.Name == Template->DefaultFilmbackPresetName_DEPRECATED) { bUpgradeFilmback = false; break; } } } } } if (bUpgradeFilmback) { Filmback = FilmbackSettings_DEPRECATED; } } PRAGMA_ENABLE_DEPRECATION_WARNINGS } void UCineCameraComponent::PostInitProperties() { Super::PostInitProperties(); RecalcDerivedData(); } void UCineCameraComponent::PostLoad() { Super::PostLoad(); if (FocusSettings.FocusMethod >= ECameraFocusMethod::MAX ) { FocusSettings.FocusMethod = ECameraFocusMethod::DoNotOverride; } RecalcDerivedData(); bResetInterpolation = true; } static const FColor DebugFocusPointSolidColor(102, 26, 204, 153); // purple static const FColor DebugFocusPointOutlineColor = FColor::Black; void UCineCameraComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { #if WITH_EDITORONLY_DATA // make sure drawing is set up if (FocusSettings.bDrawDebugFocusPlane) { if (DebugFocusPlaneComponent == nullptr) { CreateDebugFocusPlane(); } UpdateDebugFocusPlane(); } else { if (DebugFocusPlaneComponent != nullptr) { DestroyDebugFocusPlane(); } } #endif #if ENABLE_DRAW_DEBUG if (FocusSettings.TrackingFocusSettings.bDrawDebugTrackingFocusPoint) { AActor const* const TrackedActor = FocusSettings.TrackingFocusSettings.ActorToTrack.Get(); FVector FocusPoint; if (TrackedActor) { FTransform const BaseTransform = TrackedActor->GetActorTransform(); FocusPoint = BaseTransform.TransformPosition(FocusSettings.TrackingFocusSettings.RelativeOffset); } else { FocusPoint = FocusSettings.TrackingFocusSettings.RelativeOffset; } ::DrawDebugSolidBox(GetWorld(), FocusPoint, FVector(12.f), DebugFocusPointSolidColor); ::DrawDebugBox(GetWorld(), FocusPoint, FVector(12.f), DebugFocusPointOutlineColor); } #endif // ENABLE_DRAW_DEBUG Super::TickComponent(DeltaTime, TickType, ThisTickFunction); } #if WITH_EDITORONLY_DATA void UCineCameraComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { static const FName NAME_MinFocalLength = GET_MEMBER_NAME_CHECKED(FCameraLensSettings, MinFocalLength); static const FName NAME_MaxFocalLength = GET_MEMBER_NAME_CHECKED(FCameraLensSettings, MaxFocalLength); const FName PropertyChangedName = PropertyChangedEvent.GetPropertyName(); // If the user changed one of these 2 properties, leave the one that they changed alone, and // re-adjust the other one. if (PropertyChangedName == NAME_MinFocalLength) { LensSettings.MaxFocalLength = FMath::Max(LensSettings.MinFocalLength, LensSettings.MaxFocalLength); } else if (PropertyChangedName == NAME_MaxFocalLength) { LensSettings.MinFocalLength = FMath::Min(LensSettings.MinFocalLength, LensSettings.MaxFocalLength); } // Recalculate everything based on any new values. RecalcDerivedData(); // handle debug focus plane if (FocusSettings.bDrawDebugFocusPlane && (DebugFocusPlaneComponent == nullptr)) { CreateDebugFocusPlane(); } else if ((FocusSettings.bDrawDebugFocusPlane == false) && (DebugFocusPlaneComponent != nullptr)) { DestroyDebugFocusPlane(); } // set focus plane color in case that's what changed if (DebugFocusPlaneMID) { DebugFocusPlaneMID->SetVectorParameterValue(FName(TEXT("Color")), FocusSettings.DebugFocusPlaneColor.ReinterpretAsLinear()); } // reset interpolation if the user changes anything bResetInterpolation = true; UpdateDebugFocusPlane(); Super::PostEditChangeProperty(PropertyChangedEvent); } void UCineCameraComponent::ResetProxyMeshTransform() { if (ProxyMeshComponent) { // CineCam mesh is offset 90deg yaw ProxyMeshComponent->SetRelativeRotation(FRotator(0.f, 90.f, 0.f)); ProxyMeshComponent->SetRelativeLocation(FVector(-46.f, 0, -24.f)); } } #endif // WITH_EDITORONLY_DATA void UCineCameraComponent::SetFieldOfView(float InFieldOfView) { Super::SetFieldOfView(InFieldOfView); float CropedSensorWidth = Filmback.SensorWidth * LensSettings.SqueezeFactor; if (CropSettings.AspectRatio > 0.0f) { float DesqueezeAspectRatio = Filmback.SensorWidth * LensSettings.SqueezeFactor / Filmback.SensorHeight; if (CropSettings.AspectRatio < DesqueezeAspectRatio) { CropedSensorWidth *= CropSettings.AspectRatio / DesqueezeAspectRatio; } } CurrentFocalLength = (CropedSensorWidth / 2.f) / FMath::Tan(FMath::DegreesToRadians(InFieldOfView / 2.f)); } void UCineCameraComponent::SetCurrentFocalLength(float InFocalLength) { CurrentFocalLength = InFocalLength; RecalcDerivedData(); } float UCineCameraComponent::GetHorizontalFieldOfView() const { return GetHorizontalFieldOfViewInternal(/* bIncludeOverscan =*/ true); } float UCineCameraComponent::GetHorizontalFieldOfViewInternal(bool bIncludeOverscan) const { if (CurrentFocalLength > 0.f) { float CropedSensorWidth = Filmback.SensorWidth * LensSettings.SqueezeFactor; if (CropSettings.AspectRatio > 0.0f) { float DesqueezeAspectRatio = Filmback.SensorWidth * LensSettings.SqueezeFactor / Filmback.SensorHeight; if (CropSettings.AspectRatio < DesqueezeAspectRatio) { CropedSensorWidth *= CropSettings.AspectRatio / DesqueezeAspectRatio; } } const float OverscanScalar = bIncludeOverscan ? (1.0f + Overscan) * 0.5f * (AsymmetricOverscan.X + AsymmetricOverscan.Y + 2.0f) : 1.0f; return FMath::RadiansToDegrees(2.f * FMath::Atan(CropedSensorWidth * OverscanScalar / (2.f * CurrentFocalLength))); } return 0.f; } float UCineCameraComponent::GetVerticalFieldOfView() const { return GetVerticalFieldOfViewInternal(/* bIncludeOverscan =*/ true); } float UCineCameraComponent::GetVerticalFieldOfViewInternal(bool bIncludeOverscan) const { if (CurrentFocalLength > 0.f) { float CropedSensorHeight = Filmback.SensorHeight; if (CropSettings.AspectRatio > 0.0f) { float DesqueezeAspectRatio = Filmback.SensorWidth * LensSettings.SqueezeFactor / Filmback.SensorHeight; if (DesqueezeAspectRatio < CropSettings.AspectRatio) { CropedSensorHeight *= DesqueezeAspectRatio / CropSettings.AspectRatio; } } const float OverscanScalar = bIncludeOverscan ? (1.0f + Overscan) * 0.5f * (AsymmetricOverscan.Z + AsymmetricOverscan.W + 2.0f) : 1.0f; return FMath::RadiansToDegrees(2.f * FMath::Atan(CropedSensorHeight * OverscanScalar / (2.f * CurrentFocalLength))); } return 0.f; } float UCineCameraComponent::GetHorizontalProjectionOffset() const { float CroppedSensorWidth = Filmback.SensorWidth * LensSettings.SqueezeFactor; if (CropSettings.AspectRatio > 0.0f) { float DesqueezeAspectRatio = Filmback.SensorWidth * LensSettings.SqueezeFactor / Filmback.SensorHeight; if (CropSettings.AspectRatio < DesqueezeAspectRatio) { CroppedSensorWidth *= CropSettings.AspectRatio / DesqueezeAspectRatio; } } const float OverscanScalar = (1.0f + Overscan) * 0.5f * (AsymmetricOverscan.X + AsymmetricOverscan.Y + 2.0f); const float AsymmetricOverscanOffset = (AsymmetricOverscan.Y - AsymmetricOverscan.X) / (AsymmetricOverscan.X + AsymmetricOverscan.Y + 2.0f); return 2.0f * Filmback.SensorHorizontalOffset / (CroppedSensorWidth * OverscanScalar) + AsymmetricOverscanOffset; } float UCineCameraComponent::GetVerticalProjectionOffset() const { float CroppedSensorHeight = Filmback.SensorHeight; if (CropSettings.AspectRatio > 0.0f) { float DesqueezeAspectRatio = Filmback.SensorWidth * LensSettings.SqueezeFactor / Filmback.SensorHeight; if (DesqueezeAspectRatio < CropSettings.AspectRatio) { CroppedSensorHeight *= DesqueezeAspectRatio / CropSettings.AspectRatio; } } const float OverscanScalar = (1.0f + Overscan) * 0.5f * (AsymmetricOverscan.Z + AsymmetricOverscan.W + 2.0f); const float AsymmetricOverscanOffset = (AsymmetricOverscan.Z - AsymmetricOverscan.W) / (AsymmetricOverscan.Z + AsymmetricOverscan.W + 2.0f); return 2.0f * Filmback.SensorVerticalOffset / (CroppedSensorHeight * OverscanScalar) + AsymmetricOverscanOffset; } FString UCineCameraComponent::GetFilmbackPresetName() const { TArray const& Presets = UCineCameraSettings::GetFilmbackPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedFilmbackPreset const& P = Presets[PresetIdx]; if (P.FilmbackSettings == Filmback) { return P.Name; } } return FString(); } FString UCineCameraComponent::GetDefaultFilmbackPresetName() const { // Try to get the default from the CineCameraSettings object but fallback to an empty string on failure if (const UCineCameraSettings* CineCameraSettings = GetDefault()) { return CineCameraSettings->DefaultFilmbackPreset; } return FString(); } void UCineCameraComponent::SetFilmbackPresetByName(const FString& InPresetName) { SetFilmbackPresetByNameInternal(InPresetName, Filmback); // Explicitely call RecalcDerivedData() when invoked via Blueprint, since no other method (incl. PostEditChangeProperty) will trigger RecalcDerivedData(); } void UCineCameraComponent::SetFilmbackPresetByNameInternal(const FString& InPresetName, FCameraFilmbackSettings& InOutFilmbackSettings) { TArray const& Presets = UCineCameraSettings::GetFilmbackPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedFilmbackPreset const& P = Presets[PresetIdx]; if (P.Name == InPresetName) { InOutFilmbackSettings = P.FilmbackSettings; break; } } } FString UCineCameraComponent::GetLensPresetName() const { TArray const& Presets = UCineCameraSettings::GetLensPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedLensPreset const& P = Presets[PresetIdx]; if (P.LensSettings == LensSettings) { return P.Name; } } return FString(); } void UCineCameraComponent::SetLensPresetByName(const FString& InPresetName) { SetLensPresetByNameInternal(InPresetName); // Explicitely call RecalcDerivedData() when invoked via Blueprint, since no other method (incl. PostEditChangeProperty) will trigger RecalcDerivedData(); } void UCineCameraComponent::SetLensPresetByNameInternal(const FString& InPresetName) { TArray const& Presets = UCineCameraSettings::GetLensPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedLensPreset const& P = Presets[PresetIdx]; if (P.Name == InPresetName) { LensSettings = P.LensSettings; break; } } } FString UCineCameraComponent::GetCropPresetName() const { TArray const& Presets = UCineCameraSettings::GetCropPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedPlateCropPreset const& P = Presets[PresetIdx]; if (P.CropSettings == CropSettings) { return P.Name; } } return FString(); } void UCineCameraComponent::SetCropPresetByName(const FString& InPresetName) { SetCropPresetByNameInternal(InPresetName); // Explicitely call RecalcDerivedData() when invoked via Blueprint, since no other method (incl. PostEditChangeProperty) will trigger RecalcDerivedData(); } void UCineCameraComponent::SetCropPresetByNameInternal(const FString& InPresetName) { TArray const& Presets = UCineCameraSettings::GetCropPresets(); int32 const NumPresets = Presets.Num(); for (int32 PresetIdx = 0; PresetIdx < NumPresets; ++PresetIdx) { FNamedPlateCropPreset const& P = Presets[PresetIdx]; if (P.Name == InPresetName) { CropSettings = P.CropSettings; break; } } } float UCineCameraComponent::GetWorldToMetersScale() const { UWorld const* const World = GetWorld(); AWorldSettings const* const WorldSettings = World ? World->GetWorldSettings() : nullptr; return WorldSettings ? WorldSettings->WorldToMeters : 100.f; } // static TArray UCineCameraComponent::GetFilmbackPresetsCopy() { return UCineCameraSettings::GetFilmbackPresets(); } // static TArray UCineCameraComponent::GetLensPresetsCopy() { return UCineCameraSettings::GetLensPresets(); } // static TArray const& UCineCameraComponent::GetFilmbackPresets() { return UCineCameraSettings::GetFilmbackPresets(); } // static TArray const& UCineCameraComponent::GetLensPresets() { return UCineCameraSettings::GetLensPresets(); } void UCineCameraComponent::RecalcDerivedData() { // validate incorrect values LensSettings.MaxFocalLength = FMath::Max(LensSettings.MinFocalLength, LensSettings.MaxFocalLength); // respect physical limits of the (simulated) hardware CurrentFocalLength = FMath::Clamp(CurrentFocalLength, LensSettings.MinFocalLength, LensSettings.MaxFocalLength); CurrentAperture = FMath::Clamp(CurrentAperture, LensSettings.MinFStop, LensSettings.MaxFStop); float const MinFocusDistInWorldUnits = LensSettings.MinimumFocusDistance * (GetWorldToMetersScale() / 1000.f); // convert mm to uu FocusSettings.ManualFocusDistance = FMath::Max(FocusSettings.ManualFocusDistance, MinFocusDistInWorldUnits); FieldOfView = GetHorizontalFieldOfViewInternal(/*bIncludeOverscan =*/ false); Filmback.RecalcSensorAspectRatio(); AspectRatio = Filmback.SensorAspectRatio * LensSettings.SqueezeFactor; if (CropSettings.AspectRatio > 0.0f) { AspectRatio = CropSettings.AspectRatio; } #if WITH_EDITORONLY_DATA CurrentHorizontalFOV = FieldOfView; // informational variable only, for editor users #endif } /// @endcond float UCineCameraComponent::GetDesiredFocusDistance(const FVector& InLocation) const { float DesiredFocusDistance = 0.f; // get focus distance switch (FocusSettings.FocusMethod) { case ECameraFocusMethod::Manual: DesiredFocusDistance = FocusSettings.ManualFocusDistance; break; case ECameraFocusMethod::Tracking: { AActor const* const TrackedActor = FocusSettings.TrackingFocusSettings.ActorToTrack.Get(); FVector FocusPoint; if (TrackedActor) { FTransform const BaseTransform = TrackedActor->GetActorTransform(); FocusPoint = BaseTransform.TransformPosition(FocusSettings.TrackingFocusSettings.RelativeOffset); } else { FocusPoint = FocusSettings.TrackingFocusSettings.RelativeOffset; } const bool bBehindCamera = FVector::DotProduct(GetForwardVector(), FocusPoint - InLocation) < 0; if (bBehindCamera) { DesiredFocusDistance = 0; } else { FVector OutClosestPoint; FMath::PointDistToLine(FocusPoint, GetForwardVector(), InLocation, OutClosestPoint); DesiredFocusDistance = (OutClosestPoint - InLocation).Size(); } } break; } // add in the adjustment offset DesiredFocusDistance += FocusSettings.FocusOffset; return DesiredFocusDistance; } void UCineCameraComponent::GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView) { RecalcDerivedData(); Super::GetCameraView(DeltaTime, DesiredView); UpdateCameraLens(DeltaTime, DesiredView); DesiredView.PerspectiveNearClipPlane = bOverride_CustomNearClippingPlane ? CustomNearClippingPlane : -1.0f; DesiredView.OffCenterProjectionOffset.X = GetHorizontalProjectionOffset(); DesiredView.OffCenterProjectionOffset.Y = GetVerticalProjectionOffset(); bResetInterpolation = false; } #if WITH_EDITOR FText UCineCameraComponent::GetFilmbackText() const { const float SensorWidth = Filmback.SensorWidth; const float SensorHeight = Filmback.SensorHeight; // Search presets for one that matches const FNamedFilmbackPreset* Preset = UCineCameraSettings::GetFilmbackPresets().FindByPredicate([&](const FNamedFilmbackPreset& InPreset) { return InPreset.FilmbackSettings.SensorWidth == SensorWidth && InPreset.FilmbackSettings.SensorHeight == SensorHeight; }); if (Preset) { return FText::Format( LOCTEXT("PresetFormat","FilmbackPreset: {0} | Zoom: {1}mm | Av: {2} | Squeeze: {3}"), Preset->DisplayName.IsEmpty() ? FText::FromString(Preset->Name) : Preset->DisplayName, FText::AsNumber(CurrentFocalLength), FText::AsNumber(CurrentAperture), FText::AsNumber(LensSettings.SqueezeFactor) ); } else { FNumberFormattingOptions Opts = FNumberFormattingOptions().SetMaximumFractionalDigits(1); return FText::Format( LOCTEXT("CustomFilmbackFormat", "Custom ({0}mm x {1}mm) | Zoom: {2}mm | Av: {3} | Squeeze: {4}"), FText::AsNumber(SensorWidth, &Opts), FText::AsNumber(SensorHeight, &Opts), FText::AsNumber(CurrentFocalLength), FText::AsNumber(CurrentAperture), FText::AsNumber(LensSettings.SqueezeFactor) ); } } #endif void UCineCameraComponent::SetFilmback(const FCameraFilmbackSettings& NewFilmback) { Filmback = NewFilmback; RecalcDerivedData(); } void UCineCameraComponent::SetLensSettings(const FCameraLensSettings& NewLensSettings) { LensSettings = NewLensSettings; RecalcDerivedData(); } void UCineCameraComponent::SetFocusSettings(const FCameraFocusSettings& NewFocusSettings) { FocusSettings = NewFocusSettings; RecalcDerivedData(); } void UCineCameraComponent::SetCropSettings(const FPlateCropSettings& NewCropSettings) { CropSettings = NewCropSettings; RecalcDerivedData(); } void UCineCameraComponent::SetCurrentAperture(const float NewCurrentAperture) { CurrentAperture = NewCurrentAperture; RecalcDerivedData(); } void UCineCameraComponent::SetCustomNearClippingPlane(const float NewCustomNearClippingPlane) { CustomNearClippingPlane = NewCustomNearClippingPlane; } #if WITH_EDITORONLY_DATA void UCineCameraComponent::UpdateDebugFocusPlane() { if (FocusPlaneVisualizationMesh && DebugFocusPlaneComponent) { FVector const CamLocation = GetComponentTransform().GetLocation(); FVector const CamDir = GetComponentTransform().GetRotation().Vector(); UWorld const* const World = GetWorld(); float const FocusDistance = (World && World->IsGameWorld()) ? CurrentFocusDistance : GetDesiredFocusDistance(CamLocation); // in editor, use desired focus distance directly, no interp FVector const FocusPoint = GetComponentTransform().GetLocation() + CamDir * FocusDistance; DebugFocusPlaneComponent->SetWorldLocation(FocusPoint); } } #endif void UCineCameraComponent::UpdateCameraLens(float DeltaTime, FMinimalViewInfo& DesiredView) { // UE-192569: Given that aperture impacts exposure, we always override it. DesiredView.PostProcessSettings.bOverride_DepthOfFieldFstop = true; DesiredView.PostProcessSettings.DepthOfFieldFstop = CurrentAperture; if (FocusSettings.FocusMethod == ECameraFocusMethod::DoNotOverride) { DesiredView.PostProcessSettings.bOverride_DepthOfFieldMinFstop = false; DesiredView.PostProcessSettings.bOverride_DepthOfFieldBladeCount = false; DesiredView.PostProcessSettings.bOverride_DepthOfFieldFocalDistance = false; DesiredView.PostProcessSettings.bOverride_DepthOfFieldSensorWidth = false; DesiredView.PostProcessSettings.bOverride_DepthOfFieldSqueezeFactor = false; } else if (FocusSettings.FocusMethod == ECameraFocusMethod::Disable) { // There might be a post process volume that is enabled with depth of field settings, override it and disable depth of field by setting the distance to 0 DesiredView.PostProcessSettings.bOverride_DepthOfFieldFocalDistance = true; DesiredView.PostProcessSettings.DepthOfFieldFocalDistance = 0.f; } else { // Update focus/DoF DesiredView.PostProcessBlendWeight = PostProcessBlendWeight; DesiredView.PostProcessSettings.bOverride_DepthOfFieldMinFstop = true; DesiredView.PostProcessSettings.DepthOfFieldMinFstop = LensSettings.MinFStop; DesiredView.PostProcessSettings.bOverride_DepthOfFieldBladeCount = true; DesiredView.PostProcessSettings.DepthOfFieldBladeCount = LensSettings.DiaphragmBladeCount; CurrentFocusDistance = GetDesiredFocusDistance(DesiredView.Location); // clamp to min focus distance float const MinFocusDistInWorldUnits = LensSettings.MinimumFocusDistance * (GetWorldToMetersScale() / 1000.f); // convert mm to uu CurrentFocusDistance = FMath::Max(CurrentFocusDistance, MinFocusDistInWorldUnits); // smoothing, if desired if (FocusSettings.bSmoothFocusChanges) { if (bResetInterpolation == false) { CurrentFocusDistance = FMath::FInterpTo(LastFocusDistance, CurrentFocusDistance, DeltaTime, FocusSettings.FocusSmoothingInterpSpeed); } } LastFocusDistance = CurrentFocusDistance; DesiredView.PostProcessSettings.bOverride_DepthOfFieldFocalDistance = true; DesiredView.PostProcessSettings.DepthOfFieldFocalDistance = CurrentFocusDistance; const float OverscanScalar = (1.0f + Overscan) * 0.5f * (AsymmetricOverscan.X + AsymmetricOverscan.Y + 2.0f); DesiredView.PostProcessSettings.bOverride_DepthOfFieldSensorWidth = true; DesiredView.PostProcessSettings.DepthOfFieldSensorWidth = Filmback.SensorWidth * OverscanScalar; const float AsymmetricSqueezeFactor = bCropOverscan ? (AsymmetricOverscan.X + AsymmetricOverscan.Y + 2.0f) / (AsymmetricOverscan.Z + AsymmetricOverscan.W + 2.0f) : 1.0f; DesiredView.PostProcessSettings.bOverride_DepthOfFieldSqueezeFactor = true; DesiredView.PostProcessSettings.DepthOfFieldSqueezeFactor = LensSettings.SqueezeFactor * AsymmetricSqueezeFactor; DesiredView.PostProcessSettings.bOverride_DepthOfFieldAspectRatioScalar = true; DesiredView.PostProcessSettings.DepthOfFieldAspectRatioScalar = AsymmetricSqueezeFactor; } } void UCineCameraComponent::NotifyCameraCut() { Super::NotifyCameraCut(); // reset any interpolations bResetInterpolation = true; } #if WITH_EDITORONLY_DATA void UCineCameraComponent::CreateDebugFocusPlane() { if (AActor* const MyOwner = GetOwner()) { if (DebugFocusPlaneComponent == nullptr) { DebugFocusPlaneComponent = NewObject(MyOwner, NAME_None, RF_Transient | RF_Transactional | RF_TextExportTransient); DebugFocusPlaneComponent->SetupAttachment(this); DebugFocusPlaneComponent->SetIsVisualizationComponent(true); DebugFocusPlaneComponent->SetStaticMesh(FocusPlaneVisualizationMesh); DebugFocusPlaneComponent->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName); DebugFocusPlaneComponent->bHiddenInGame = false; DebugFocusPlaneComponent->CastShadow = false; DebugFocusPlaneComponent->CreationMethod = CreationMethod; DebugFocusPlaneComponent->bSelectable = false; DebugFocusPlaneComponent->SetIgnoreBoundsForEditorFocus(true); DebugFocusPlaneComponent->SetRelativeScale3D_Direct(FVector(10000.f, 10000.f, 1.f)); DebugFocusPlaneComponent->SetRelativeRotation_Direct(FRotator(90.f, 0.f, 0.f)); DebugFocusPlaneComponent->RegisterComponentWithWorld(GetWorld()); DebugFocusPlaneMID = DebugFocusPlaneComponent->CreateAndSetMaterialInstanceDynamicFromMaterial(0, FocusPlaneVisualizationMaterial); if (DebugFocusPlaneMID) { DebugFocusPlaneMID->SetVectorParameterValue(FName(TEXT("Color")), FocusSettings.DebugFocusPlaneColor.ReinterpretAsLinear()); } } } } void UCineCameraComponent::DestroyDebugFocusPlane() { if (DebugFocusPlaneComponent) { DebugFocusPlaneComponent->SetVisibility(false); DebugFocusPlaneComponent = nullptr; DebugFocusPlaneMID = nullptr; } } #endif void UCineCameraComponent::OnRegister() { Super::OnRegister(); #if WITH_EDITORONLY_DATA ResetProxyMeshTransform(); #endif } #if WITH_EDITOR void UCineCameraComponent::OnComponentDestroyed(bool bDestroyingHierarchy) { Super::OnComponentDestroyed(bDestroyingHierarchy); if (DebugFocusPlaneComponent) { DebugFocusPlaneComponent->DestroyComponent(); } } #endif #undef LOCTEXT_NAMESPACE