From 3c1a6840398d8e8a99fa0fbefd91c4c19e36bbba Mon Sep 17 00:00:00 2001 From: andrey yamashev Date: Tue, 26 Mar 2024 02:01:55 -0400 Subject: [PATCH] [nDisplay] Media configuration improvements #jira UE-208957 #rb Alejandro.Arango, Ruslan.Idrisov [FYI] Alejandro.Arango [CL 32498668 by andrey yamashev in 5.4 branch] --- .../DisplayClusterConfiguratorModule.cpp | 11 +- ...terConfiguratorICVFXMediaCustomization.cpp | 9 +- ...onfiguratorICVFXMediaTileCustomization.cpp | 266 -------------- ...rConfiguratorICVFXMediaTileCustomization.h | 109 ------ ...sterConfiguratorMediaCustomizationBase.cpp | 346 ++++++++++++++++++ ...lusterConfiguratorMediaCustomizationBase.h | 107 ++++++ ...terConfiguratorMediaCustomizationCVars.cpp | 13 + ...usterConfiguratorMediaCustomizationCVars.h | 9 + ...onfiguratorMediaFullFrameCustomization.cpp | 34 ++ ...rConfiguratorMediaFullFrameCustomization.h | 44 +++ ...sterConfiguratorMediaTileCustomization.cpp | 43 +++ ...lusterConfiguratorMediaTileCustomization.h | 44 +++ .../DisplayClusterConfiguratorMediaUtils.cpp | 12 + .../DisplayClusterConfiguratorMediaUtils.h | 23 +- .../SharedMemoryMediaInitializerFeature.cpp | 44 ++- .../SharedMemoryMediaInitializerFeature.h | 8 +- ...layClusterModularFeatureMediaInitializer.h | 58 ++- .../RivermaxMediaInitializerFeature.cpp | 87 ++++- .../RivermaxMediaInitializerFeature.h | 6 +- 19 files changed, 845 insertions(+), 428 deletions(-) delete mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.cpp delete mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.cpp create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.cpp create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.h create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.cpp create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.cpp create mode 100644 Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/DisplayClusterConfiguratorModule.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/DisplayClusterConfiguratorModule.cpp index e33d22e08d64..4c8e655051aa 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/DisplayClusterConfiguratorModule.cpp +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/DisplayClusterConfiguratorModule.cpp @@ -27,7 +27,8 @@ #include "Views/Details/Components/DisplayClusterConfiguratorScreenComponentDetailsCustomization.h" #include "Views/Details/Components/DisplayClusterICVFXCameraComponentDetailsCustomization.h" #include "Views/Details/Media/DisplayClusterConfiguratorICVFXMediaCustomization.h" -#include "Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h" #include "Views/Details/Policies/DisplayClusterConfiguratorPolicyDetailCustomization.h" #include "Blueprints/DisplayClusterBlueprint.h" @@ -226,8 +227,12 @@ void FDisplayClusterConfiguratorModule::RegisterCustomLayouts() REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationViewport_RemapData, FDisplayClusterConfiguratorViewportRemapCustomization); REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationRectangle, FDisplayClusterConfiguratorRectangleCustomization); REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaICVFX, FDisplayClusterConfiguratorICVFXMediaCustomization); - REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaUniformTileInput, FDisplayClusterConfiguratorICVFXMediaInputTileCustomization); - REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaUniformTileOutput, FDisplayClusterConfiguratorICVFXMediaOutputTileCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaUniformTileInput, FDisplayClusterConfiguratorMediaInputTileCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaUniformTileOutput, FDisplayClusterConfiguratorMediaOutputTileCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaInput, FDisplayClusterConfiguratorMediaFullFrameInputCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaOutput, FDisplayClusterConfiguratorMediaFullFrameOutputCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaInputGroup, FDisplayClusterConfiguratorMediaFullFrameInputCustomization); + REGISTER_PROPERTY_LAYOUT(FDisplayClusterConfigurationMediaOutputGroup, FDisplayClusterConfiguratorMediaFullFrameOutputCustomization); } void FDisplayClusterConfiguratorModule::UnregisterCustomLayouts() diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaCustomization.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaCustomization.cpp index 01e19bd6eb3c..fa05e239c903 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaCustomization.cpp +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaCustomization.cpp @@ -87,10 +87,7 @@ void FDisplayClusterConfiguratorICVFXMediaCustomization::CustomizeChildren(TShar FDisplayClusterConfiguratorBaseTypeCustomization::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); // Create auto-configure button in the bottom - if (SplitTypeValue == EDisplayClusterConfigurationMediaSplitType::UniformTiles) - { - AddAutoConfigurationButton(InChildBuilder); - } + AddAutoConfigurationButton(InChildBuilder); } void FDisplayClusterConfiguratorICVFXMediaCustomization::AddAutoConfigurationButton(IDetailChildrenBuilder& InChildBuilder) @@ -107,7 +104,7 @@ void FDisplayClusterConfiguratorICVFXMediaCustomization::AddAutoConfigurationBut [ SNew(STextBlock) .Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont"))) - .Text(LOCTEXT("AutoConfigureTiledInputButtonTitle", "Auto-Configure")) + .Text(LOCTEXT("AutoConfigureInputButtonTitle", "Auto-Configure")) ] ] ]; @@ -116,7 +113,7 @@ void FDisplayClusterConfiguratorICVFXMediaCustomization::AddAutoConfigurationBut FReply FDisplayClusterConfiguratorICVFXMediaCustomization::OnAutoConfigureButtonClicked() { // Notify tile customizators to re-initialize their media subjects - FDisplayClusterConfiguratorMediaUtils::Get().OnTiledMediaAutoConfiguration().Broadcast(EditingObject.Get()); + FDisplayClusterConfiguratorMediaUtils::Get().OnMediaAutoConfiguration().Broadcast(EditingObject.Get()); return FReply::Handled(); } diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.cpp deleted file mode 100644 index 8d595a54bdd6..000000000000 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h" -#include "Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h" - -#include "Components/DisplayClusterICVFXCameraComponent.h" -#include "DisplayClusterConfigurationTypes_Media.h" -#include "DisplayClusterConfiguratorBlueprintEditor.h" -#include "DisplayClusterConfiguratorUtils.h" -#include "DisplayClusterRootActor.h" - -#include "IDisplayClusterModularFeatureMediaInitializer.h" - -#include "IDetailChildrenBuilder.h" -#include "IPropertyUtilities.h" -#include "PropertyHandle.h" - -#include "Features/IModularFeatures.h" - -#define LOCTEXT_NAMESPACE "FDisplayClusterConfiguratorICVFXMediaCustomization" - - -// Enable/disable live auto-configuration. Does not affect "auto-configure" button. -TAutoConsoleVariable CVarTiledMediaAutoInitializationEnabled( - TEXT("nDisplay.Media.TiledMediaAutoInitialization"), - true, - TEXT("nDisplay tiled media auto-configuration\n") - TEXT("0 : Disabled\n") - TEXT("1 : Enabled\n"), - ECVF_Default -); - - -// -// Input tiles -// -void FDisplayClusterConfiguratorICVFXMediaInputTileCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) -{ - // MediaSource property - MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileInput, MediaSource); - check(MediaSubjectHandle->IsValidHandle()); - - // Tile position property - TilePosHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileInput, Position); - check(TilePosHandle->IsValidHandle()); - - FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); -} - -// -// Output tiles -// -void FDisplayClusterConfiguratorICVFXMediaOutputTileCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) -{ - // MediaOutput property - MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileOutput, MediaOutput); - check(MediaSubjectHandle->IsValidHandle()); - - // Tile position property - TilePosHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileOutput, Position); - check(TilePosHandle->IsValidHandle()); - - FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); -} - -// -// Common customization -// - -// Static members -bool FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::bMediaInitializersObtained = false; -TArray FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::MediaInitializers; - -FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase() -{ - // Obtain media initializer modular features once. We don't expect any of them to be loaded dynamically in runtime. - if (!bMediaInitializersObtained) - { - IModularFeatures& ModularFeatures = IModularFeatures::Get(); - ModularFeatures.LockModularFeatureList(); - MediaInitializers = ModularFeatures.GetModularFeatureImplementations(IDisplayClusterModularFeatureMediaInitializer::ModularFeatureName); - ModularFeatures.UnlockModularFeatureList(); - - bMediaInitializersObtained = true; - } - - // Subscribe for auto-configure event - FDisplayClusterConfiguratorMediaUtils::Get().OnTiledMediaAutoConfiguration().AddRaw(this, &FDisplayClusterConfiguratorICVFXMediaInputTileCustomization::OnAutoConfigureRequested); -} - -FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::~FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase() -{ - // Unsubscribe from auto-configure event - FDisplayClusterConfiguratorMediaUtils::Get().OnTiledMediaAutoConfiguration().RemoveAll(this); -} - -void FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) -{ - if (CVarTiledMediaAutoInitializationEnabled.GetValueOnGameThread()) - { - // Subscribe for change callbacks - if (MediaSubjectHandle->IsValidHandle() && TilePosHandle->IsValidHandle()) - { - MediaSubjectHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateRaw(this, &FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnMediaSubjectChanged)); - - TilePosHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateRaw(this, &FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnTilePositionChanged)); - TilePosHandle->SetOnChildPropertyValueChanged(FSimpleDelegate::CreateRaw(this, &FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnTilePositionChanged)); - } - } - - FDisplayClusterConfiguratorBaseTypeCustomization::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); -} - -void FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::ModifyMediaSubjectParameters() -{ - if (!EditingObject.IsValid()) - { - return; - } - - UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent = Cast(EditingObject.Get()); - if (!MediaSubjectHandle->IsValidHandle() || !ICVFXCameraComponent) - { - return; - } - - UObject* NewMediaSubject = nullptr; - if (MediaSubjectHandle->GetValue(NewMediaSubject) != FPropertyAccess::Success) - { - return; - } - - if (!NewMediaSubject) - { - return; - } - - // Get input tile position - const FIntPoint TilePos = GetEditedTilePos(); - if (TilePos.X == FIntPoint::NoneValue.X || TilePos.Y == FIntPoint::NoneValue.Y) - { - return; - } - - // Find a suitable initializer, and let it process new media data - for (IDisplayClusterModularFeatureMediaInitializer* Initializer : MediaInitializers) - { - if (Initializer && Initializer->IsMediaSubjectSupported(NewMediaSubject)) - { - const FString OwnerName = GetOwnerName(ICVFXCameraComponent); - const uint8 UniqueOwnerIndex = GenerateUniqueOwnerIndex(OwnerName); - - if (UniqueOwnerIndex < TNumericLimits::Max()) - { - Initializer->InitializeMediaSubjectForTile(NewMediaSubject, OwnerName, UniqueOwnerIndex, TilePos); - } - - break; - } - } -} - -AActor* FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::GetOwningActor() const -{ - if (UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent = Cast(EditingObject)) - { - if (AActor* Actor1 = ICVFXCameraComponent->GetOwner()) - { - return Actor1; - } - else if (AActor* Actor2 = Cast(FindRootActor())) - { - return Actor2; - } - else if(FDisplayClusterConfiguratorBlueprintEditor* BlueprintEditor = FDisplayClusterConfiguratorUtils::GetBlueprintEditorForObject(ICVFXCameraComponent)) - { - return BlueprintEditor->GetPreviewActor(); - } - } - - return nullptr; -} - -FString FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::GetOwnerName(const UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent) const -{ - // In blueprint editor, the components are transient with the following suffix. We don't need it. The instances in a level don't have such suffix. - FString CameraName = ICVFXCameraComponent->GetName(); - CameraName.RemoveFromEnd(TEXT("_GEN_VARIABLE")); - - return CameraName; -} - -FIntPoint FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::GetEditedTilePos() const -{ - FIntPoint TilePos = FIntPoint::NoneValue; - - // Children 0 and 1 correspond to X and Y subproperties of FIntPoint - TilePosHandle->GetChildHandle(0)->GetValue(TilePos.X); - TilePosHandle->GetChildHandle(1)->GetValue(TilePos.Y); - - return TilePos; -} - -uint8 FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::GenerateUniqueOwnerIndex(const FString& OwnerName) const -{ - if (const AActor* OwningActor = GetOwningActor()) - { - // Get all camera components - TArray ICVFXCameras; - OwningActor->GetComponents(ICVFXCameras); - - if (ICVFXCameras.Num() > 0) - { - // Camera sort predicate - struct FCameraSortPredicate - { - bool operator()(UDisplayClusterICVFXCameraComponent& LHS, UDisplayClusterICVFXCameraComponent& RHS) const - { - return LHS.GetName().Compare(RHS.GetName(), ESearchCase::IgnoreCase) < 0; - } - }; - - // Just in case, sort by name to always keep the same order - ICVFXCameras.Sort(FCameraSortPredicate()); - - const int32 CamerasAmount = ICVFXCameras.Num(); - checkSlow(CamerasAmount > 0 && CamerasAmount < TNumericLimits::Max()); - - // Find camera index in the list - for (uint8 CameraIdx = 0; CameraIdx < CamerasAmount; ++CameraIdx) - { - if (ICVFXCameras[CameraIdx]->GetName().Equals(OwnerName, ESearchCase::IgnoreCase)) - { - return CameraIdx; - } - } - } - else - { - // Should not normally happen because the camera being edited should be there at least. - checkSlow(false); - } - } - - return TNumericLimits::Max(); -} - -void FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnMediaSubjectChanged() -{ - ModifyMediaSubjectParameters(); -} - -void FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnTilePositionChanged() -{ - ModifyMediaSubjectParameters(); -} - -void FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase::OnAutoConfigureRequested(UObject* InEditingObject) -{ - if (EditingObject == InEditingObject) - { - ModifyMediaSubjectParameters(); - } -} - -#undef LOCTEXT_NAMESPACE diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h deleted file mode 100644 index 2a6629f86c1d..000000000000 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorICVFXMediaTileCustomization.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Views/Details/DisplayClusterConfiguratorBaseTypeCustomization.h" - -class IDisplayClusterModularFeatureMediaInitializer; -class UDisplayClusterICVFXCameraComponent; - - -/** - * Helper class to hanldle common functionality of input and output tiles customization - */ -class FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase - : public FDisplayClusterConfiguratorBaseTypeCustomization -{ -public: - FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase(); - ~FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase(); - -protected: - - //~ Begin IPropertyTypeCustomization - virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; - //~ End IPropertyTypeCustomization - -private: - - /** Entry point to modify media subjects. */ - void ModifyMediaSubjectParameters(); - - /** Returns the actor that owns the object being edited. */ - AActor* GetOwningActor() const; - - /** Returns the name of media subject's owner. */ - FString GetOwnerName(const UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent) const; - - /** Returns tile position currently set. */ - FIntPoint GetEditedTilePos() const; - - /** Generate unique index for the media subject's owner. */ - uint8 GenerateUniqueOwnerIndex(const FString& OwnerName) const; - -private: - - /** Handles media source/output change callbacks */ - void OnMediaSubjectChanged(); - - /** Handles tile position change callbacks */ - void OnTilePositionChanged(); - - /** Auto-configuration requests handler */ - void OnAutoConfigureRequested(UObject* EditingObject); - -protected: - - /** MediaSource or MediaOutput property handle, depending on the child implementation. */ - TSharedPtr MediaSubjectHandle; - - /** Tile position property handle. */ - TSharedPtr TilePosHandle; - -private: - - /** Media initializers (modular features) available. */ - static TArray MediaInitializers; - - /** Optimization flag to prevent retrieving modular features multiple times.*/ - static bool bMediaInitializersObtained; -}; - - -/** - * Details panel customization for FDisplayClusterConfigurationMediaUniformTileInput struct (input tiles). - */ -class FDisplayClusterConfiguratorICVFXMediaInputTileCustomization - : public FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase -{ -public: - static TSharedRef MakeInstance() - { - return MakeShared(); - } - -protected: - //~ Begin IPropertyTypeCustomization - virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; - //~ End IPropertyTypeCustomization -}; - - -/** - * Details panel customization for FDisplayClusterConfigurationMediaUniformTileOutput struct (output tiles). - */ -class FDisplayClusterConfiguratorICVFXMediaOutputTileCustomization - : public FDisplayClusterConfiguratorICVFXMediaTileCustomizationBase -{ -public: - static TSharedRef MakeInstance() - { - return MakeShared(); - } - -protected: - //~ Begin IPropertyTypeCustomization - virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; - //~ End IPropertyTypeCustomization -}; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.cpp new file mode 100644 index 000000000000..6671c7971c4a --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.cpp @@ -0,0 +1,346 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h" + +#include "Components/DisplayClusterICVFXCameraComponent.h" + +#include "DisplayClusterConfigurationTypes.h" +#include "DisplayClusterConfigurationTypes_Media.h" +#include "DisplayClusterConfiguratorBlueprintEditor.h" +#include "DisplayClusterConfiguratorUtils.h" +#include "DisplayClusterRootActor.h" + +#include "IDetailChildrenBuilder.h" +#include "IPropertyUtilities.h" +#include "PropertyHandle.h" + + +FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::FDisplayClusterConfiguratorMediaFullFrameCustomizationBase() +{ + // Subscribe for auto-configure event + FDisplayClusterConfiguratorMediaUtils::Get().OnMediaAutoConfiguration().AddRaw(this, &FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::OnAutoConfigureRequested); +} + +FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::~FDisplayClusterConfiguratorMediaFullFrameCustomizationBase() +{ + // Unsubscribe from auto-configure event + FDisplayClusterConfiguratorMediaUtils::Get().OnMediaAutoConfiguration().RemoveAll(this); +} + +void FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + if (CVarMediaAutoInitializationEnabled.GetValueOnGameThread()) + { + // Subscribe for change callbacks + if (MediaSubjectHandle->IsValidHandle()) + { + MediaSubjectHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateSP(this, &FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::OnMediaSubjectChanged)); + } + } + + FDisplayClusterConfiguratorBaseTypeCustomization::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} + +void FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::ModifyMediaSubjectParameters() +{ + // Nothing to do if disabled by a CVar + if (!CVarMediaAutoInitializationEnabled.GetValueOnGameThread()) + { + return; + } + + // Validate object being edited + if (!EditingObject.IsValid()) + { + return; + } + + UObject* Owner = EditingObject.Get(); + if (!MediaSubjectHandle->IsValidHandle() || !Owner) + { + return; + } + + // Get media subject + UObject* NewMediaSubject = nullptr; + if (MediaSubjectHandle->GetValue(NewMediaSubject) != FPropertyAccess::Success) + { + return; + } + + if (!NewMediaSubject) + { + return; + } + + // Find a suitable initializer, and let it process new media data + const TArray MediaInitializers = FDisplayClusterConfiguratorMediaUtils::Get().GetMediaInitializers(); + for (IDisplayClusterModularFeatureMediaInitializer* Initializer : MediaInitializers) + { + if (Initializer && Initializer->IsMediaSubjectSupported(NewMediaSubject)) + { + if (PerformMediaInitialization(Owner, NewMediaSubject, Initializer)) + { + ModifyBlueprint(); + } + + break; + } + } +} + +bool FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::PerformMediaInitialization(UObject* Owner, UObject* MediaSubject, IDisplayClusterModularFeatureMediaInitializer* Initializer) +{ + IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo OwnerInfo; + const bool bGotOwnerData = GetOwnerData(Owner, OwnerInfo); + + if (bGotOwnerData && Initializer) + { + Initializer->InitializeMediaSubjectForFullFrame(MediaSubject, OwnerInfo); + return true; + } + + return false; +} + +bool FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::GetOwnerData(const UObject* Owner, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const +{ + if (const UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent = Cast(Owner)) + { + return GetOwnerData(ICVFXCameraComponent, OutOwnerInfo); + } + else if (const UDisplayClusterConfigurationViewport* ViewportCfg = Cast(Owner)) + { + return GetOwnerData(ViewportCfg, OutOwnerInfo); + } + else if (const UDisplayClusterConfigurationClusterNode* NodeCfg = Cast(Owner)) + { + return GetOwnerData(NodeCfg, OutOwnerInfo); + } + else + { + checkNoEntry(); + } + + return false; +} + +bool FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::GetOwnerData(const UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const +{ + if (const AActor* const OwningActor = GetOwningActor()) + { + // Get all camera components + TArray ICVFXCameras; + OwningActor->GetComponents(ICVFXCameras); + + const int32 CamerasAmount = ICVFXCameras.Num(); + if (CamerasAmount > 0) + { + // Camera sort predicate + struct FCameraSortPredicate + { + bool operator()(UDisplayClusterICVFXCameraComponent& LHS, UDisplayClusterICVFXCameraComponent& RHS) const + { + return LHS.GetName().Compare(RHS.GetName(), ESearchCase::IgnoreCase) < 0; + } + }; + + // Sort by name to always keep the same ABC-order + ICVFXCameras.Sort(FCameraSortPredicate()); + + FString OrigCameraName = ICVFXCameraComponent->GetName(); + OrigCameraName.RemoveFromEnd(TEXT("_GEN_VARIABLE")); + + // Find camera index in the list + for (uint8 CameraIdx = 0; CameraIdx < CamerasAmount; ++CameraIdx) + { + if (ICVFXCameras[CameraIdx]->GetName().Equals(OrigCameraName, ESearchCase::IgnoreCase)) + { + OutOwnerInfo.OwnerType = IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::ICVFXCamera; + OutOwnerInfo.OwnerName = OrigCameraName; + OutOwnerInfo.OwnerUniqueIdx = CameraIdx; + + return true; + } + } + } + } + + return false; +} + +bool FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::GetOwnerData(const UDisplayClusterConfigurationViewport* ViewportCfg, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const +{ + // Get cluster node that holds the viewport requested + if (const UDisplayClusterConfigurationClusterNode* const ClusterNodeCfg = ViewportCfg->GetTypedOuter()) + { + // Find the pair that holds the viewport requested + for (const TPair>& ViewportIt : ClusterNodeCfg->Viewports) + { + if (ViewportIt.Value == ViewportCfg) + { + // Get ABC-sorted list of the viewport IDs + TArray ViewportIds; + ClusterNodeCfg->Viewports.GenerateKeyArray(ViewportIds); + ViewportIds.Sort(); + + // Find viewport index + for (int32 ViewportIdx = 0; ViewportIdx < ViewportIds.Num(); ++ViewportIdx) + { + if (ViewportIds[ViewportIdx].Equals(ViewportIt.Key, ESearchCase::IgnoreCase)) + { + checkSlow(ViewportIdx < TNumericLimits::Max()); + + OutOwnerInfo.OwnerType = IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Viewport; + OutOwnerInfo.OwnerName = ViewportIt.Key; + OutOwnerInfo.OwnerUniqueIdx = static_cast(ViewportIdx); + + // Here we leverage cluster node data provider to get unique cluster node index + { + IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo TempNodeInfo; + if (GetOwnerData(ClusterNodeCfg, TempNodeInfo)) + { + OutOwnerInfo.ClusterNodeUniqueIdx = TempNodeInfo.ClusterNodeUniqueIdx; + } + } + + return true; + } + } + } + } + } + + return false; +} + +bool FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::GetOwnerData(const UDisplayClusterConfigurationClusterNode* NodeCfg, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const +{ + // Get cluster object holding the node requested + if (const UDisplayClusterConfigurationCluster* const ClusterCfg = NodeCfg->GetTypedOuter()) + { + // Find the pair that holds the node requested + for (const TPair>& NodeIt : ClusterCfg->Nodes) + { + if (NodeIt.Value == NodeCfg) + { + // Get ABC-sorted list of the cluster nodes + TArray NodeIds; + ClusterCfg->Nodes.GenerateKeyArray(NodeIds); + NodeIds.Sort(); + + // Find node index + for (int32 NodeIdx = 0; NodeIdx < ClusterCfg->Nodes.Num(); ++NodeIdx) + { + if (NodeIds[NodeIdx].Equals(NodeIt.Key, ESearchCase::IgnoreCase)) + { + checkSlow(NodeIdx < TNumericLimits::Max()); + + OutOwnerInfo.OwnerType = IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Backbuffer; + OutOwnerInfo.OwnerName = NodeIt.Key; + OutOwnerInfo.OwnerUniqueIdx = static_cast(NodeIdx); + OutOwnerInfo.ClusterNodeUniqueIdx = static_cast(NodeIdx); + + return true; + } + } + } + } + } + + return false; +} + +AActor* FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::GetOwningActor() const +{ + if (UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent = Cast(EditingObject)) + { + if (AActor* Actor1 = ICVFXCameraComponent->GetOwner()) + { + return Actor1; + } + else if (AActor* Actor2 = Cast(FindRootActor())) + { + return Actor2; + } + else if (FDisplayClusterConfiguratorBlueprintEditor* BlueprintEditor = FDisplayClusterConfiguratorUtils::GetBlueprintEditorForObject(ICVFXCameraComponent)) + { + return BlueprintEditor->GetPreviewActor(); + } + } + + return nullptr; +} + +void FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::OnMediaSubjectChanged() +{ + ModifyMediaSubjectParameters(); +} + +void FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::OnAutoConfigureRequested(UObject* InEditingObject) +{ + if (EditingObject == InEditingObject) + { + ModifyMediaSubjectParameters(); + } +} + + +// +// Common customization +// + +void FDisplayClusterConfiguratorMediaTileCustomizationBase::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + if (CVarMediaAutoInitializationEnabled.GetValueOnGameThread()) + { + // Subscribe for change callbacks + if (TilePosHandle->IsValidHandle()) + { + TilePosHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateSP(this, &FDisplayClusterConfiguratorMediaTileCustomizationBase::OnTilePositionChanged)); + TilePosHandle->SetOnChildPropertyValueChanged(FSimpleDelegate::CreateSP(this, &FDisplayClusterConfiguratorMediaTileCustomizationBase::OnTilePositionChanged)); + } + } + + FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} + +bool FDisplayClusterConfiguratorMediaTileCustomizationBase::PerformMediaInitialization(UObject* Owner, UObject* MediaSubject, IDisplayClusterModularFeatureMediaInitializer* Initializer) +{ + IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo OwnerInfo; + const bool bGotOwnerData = GetOwnerData(Owner, OwnerInfo); + + if (bGotOwnerData) + { + // Get input tile position + const FIntPoint TilePos = GetEditedTilePos(); + if (TilePos.X != FIntPoint::NoneValue.X && TilePos.Y != FIntPoint::NoneValue.Y) + { + if (Initializer) + { + Initializer->InitializeMediaSubjectForTile(MediaSubject, OwnerInfo, TilePos); + return true; + } + } + } + + return false; +} + +FIntPoint FDisplayClusterConfiguratorMediaTileCustomizationBase::GetEditedTilePos() const +{ + FIntPoint TilePos = FIntPoint::NoneValue; + + // Children 0 and 1 correspond to X and Y subproperties of FIntPoint + TilePosHandle->GetChildHandle(0)->GetValue(TilePos.X); + TilePosHandle->GetChildHandle(1)->GetValue(TilePos.Y); + + return TilePos; +} + +void FDisplayClusterConfiguratorMediaTileCustomizationBase::OnTilePositionChanged() +{ + ModifyMediaSubjectParameters(); +} diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h new file mode 100644 index 000000000000..050a3f2a9df7 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h @@ -0,0 +1,107 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Views/Details/DisplayClusterConfiguratorBaseTypeCustomization.h" + +#include "IDisplayClusterModularFeatureMediaInitializer.h" + +class UDisplayClusterConfigurationClusterNode; +class UDisplayClusterConfigurationViewport; +class UDisplayClusterICVFXCameraComponent; + + +/** + * Base class for full frame media input & output customization + */ +class FDisplayClusterConfiguratorMediaFullFrameCustomizationBase + : public FDisplayClusterConfiguratorBaseTypeCustomization +{ +public: + FDisplayClusterConfiguratorMediaFullFrameCustomizationBase(); + ~FDisplayClusterConfiguratorMediaFullFrameCustomizationBase(); + +protected: + + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization + +protected: + + /** Entry point to modify media subjects. */ + void ModifyMediaSubjectParameters(); + + /** Virtual media initialization depending on media type (full-frame, split, etc.) */ + virtual bool PerformMediaInitialization(UObject* Owner, UObject* MediaSubject, IDisplayClusterModularFeatureMediaInitializer* Initializer); + + /** Returns the actor that owns the object being edited. */ + AActor* GetOwningActor() const; + + /** Returns the name of media subject's owner. */ + bool GetOwnerData(const UObject* Owner, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const; + +private: + + /** Helper data provider for ICVFX cameras. */ + bool GetOwnerData(const UDisplayClusterICVFXCameraComponent* ICVFXCameraComponent, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const; + + /** Helper data provider for viewports. */ + bool GetOwnerData(const UDisplayClusterConfigurationViewport* ViewportCfg, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const; + + /** Helper data provider for cluster nodes. */ + bool GetOwnerData(const UDisplayClusterConfigurationClusterNode* NodeCfg, IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo& OutOwnerInfo) const; + +private: + + /** Handles media source/output change callbacks */ + void OnMediaSubjectChanged(); + + /** Auto-configuration requests handler */ + void OnAutoConfigureRequested(UObject* EditingObject); + +protected: + + /** MediaSource or MediaOutput property handle, depending on the child implementation. */ + TSharedPtr MediaSubjectHandle; +}; + + + +/** + * Base class for tiled media input & output customization + */ +class FDisplayClusterConfiguratorMediaTileCustomizationBase + : public FDisplayClusterConfiguratorMediaFullFrameCustomizationBase +{ +protected: + + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization + +protected: + + //~ Begin FDisplayClusterConfiguratorMediaFullFrameCustomizationBase + + /** Virtual media initialization depending on media type (full-frame, split, etc.) */ + virtual bool PerformMediaInitialization(UObject* Owner, UObject* MediaSubject, IDisplayClusterModularFeatureMediaInitializer* Initializer) override; + + //~ End FDisplayClusterConfiguratorMediaFullFrameCustomizationBase + +private: + + /** Returns tile position currently set. */ + FIntPoint GetEditedTilePos() const; + +private: + + /** Handles tile position change callbacks */ + void OnTilePositionChanged(); + +protected: + + /** Tile position property handle. */ + TSharedPtr TilePosHandle; +}; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.cpp new file mode 100644 index 000000000000..e413b485d9e1 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.cpp @@ -0,0 +1,13 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "Views\Details\Media\DisplayClusterConfiguratorMediaCustomizationCVars.h" + + +TAutoConsoleVariable CVarMediaAutoInitializationEnabled( + TEXT("nDisplay.Media.MediaAutoInitialization"), + true, + TEXT("nDisplay tiled media auto-configuration\n") + TEXT("0 : Disabled\n") + TEXT("1 : Enabled\n"), + ECVF_Default +); diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.h new file mode 100644 index 000000000000..fb3c3bb988f3 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationCVars.h @@ -0,0 +1,9 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "HAL/IConsoleManager.h" + +// Enable/disable live auto-configuration. Does not affect "auto-configure" button. +extern TAutoConsoleVariable CVarMediaAutoInitializationEnabled; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.cpp new file mode 100644 index 000000000000..939140c8a31f --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.cpp @@ -0,0 +1,34 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h" + +#include "DisplayClusterConfigurationTypes_Media.h" + +#include "IDetailChildrenBuilder.h" +#include "IPropertyUtilities.h" +#include "PropertyHandle.h" + + +// +// Input tiles +// +void FDisplayClusterConfiguratorMediaFullFrameInputCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + // MediaSource property + MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaInput, MediaSource); + check(MediaSubjectHandle->IsValidHandle()); + + FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} + +// +// Output tiles +// +void FDisplayClusterConfiguratorMediaFullFrameOutputCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + // MediaOutput property + MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaOutput, MediaOutput); + check(MediaSubjectHandle->IsValidHandle()); + + FDisplayClusterConfiguratorMediaFullFrameCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h new file mode 100644 index 000000000000..f00cba935782 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaFullFrameCustomization.h @@ -0,0 +1,44 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h" + + +/** + * Details panel customization for FDisplayClusterConfigurationMediaUniformTileInput struct (input tiles). + */ +class FDisplayClusterConfiguratorMediaFullFrameInputCustomization + : public FDisplayClusterConfiguratorMediaFullFrameCustomizationBase +{ +public: + static TSharedRef MakeInstance() + { + return MakeShared(); + } + +protected: + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization +}; + + +/** + * Details panel customization for FDisplayClusterConfigurationMediaUniformTileOutput struct (output tiles). + */ +class FDisplayClusterConfiguratorMediaFullFrameOutputCustomization + : public FDisplayClusterConfiguratorMediaFullFrameCustomizationBase +{ +public: + static TSharedRef MakeInstance() + { + return MakeShared(); + } + +protected: + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization +}; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.cpp new file mode 100644 index 000000000000..71442ba8db91 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.cpp @@ -0,0 +1,43 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h" + +#include "DisplayClusterConfigurationTypes_Media.h" + +#include "IDetailChildrenBuilder.h" +#include "IPropertyUtilities.h" +#include "PropertyHandle.h" + + +// +// Input tiles +// +void FDisplayClusterConfiguratorMediaInputTileCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + // MediaSource property + MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileInput, MediaSource); + check(MediaSubjectHandle->IsValidHandle()); + + // Tile position property + TilePosHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileInput, Position); + check(TilePosHandle->IsValidHandle()); + + FDisplayClusterConfiguratorMediaTileCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} + + +// +// Output tiles +// +void FDisplayClusterConfiguratorMediaOutputTileCustomization::CustomizeChildren(TSharedRef InPropertyHandle, IDetailChildrenBuilder& InChildBuilder, IPropertyTypeCustomizationUtils& InCustomizationUtils) +{ + // MediaOutput property + MediaSubjectHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileOutput, MediaOutput); + check(MediaSubjectHandle->IsValidHandle()); + + // Tile position property + TilePosHandle = GET_CHILD_HANDLE(FDisplayClusterConfigurationMediaUniformTileOutput, Position); + check(TilePosHandle->IsValidHandle()); + + FDisplayClusterConfiguratorMediaTileCustomizationBase::CustomizeChildren(InPropertyHandle, InChildBuilder, InCustomizationUtils); +} diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h new file mode 100644 index 000000000000..15c12727fb58 --- /dev/null +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaTileCustomization.h @@ -0,0 +1,44 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Views/Details/Media/DisplayClusterConfiguratorMediaCustomizationBase.h" + + +/** + * Details panel customization for FDisplayClusterConfigurationMediaUniformTileInput struct (input tiles). + */ +class FDisplayClusterConfiguratorMediaInputTileCustomization + : public FDisplayClusterConfiguratorMediaTileCustomizationBase +{ +public: + static TSharedRef MakeInstance() + { + return MakeShared(); + } + +protected: + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization +}; + + +/** + * Details panel customization for FDisplayClusterConfigurationMediaUniformTileOutput struct (output tiles). + */ +class FDisplayClusterConfiguratorMediaOutputTileCustomization + : public FDisplayClusterConfiguratorMediaTileCustomizationBase +{ +public: + static TSharedRef MakeInstance() + { + return MakeShared(); + } + +protected: + //~ Begin IPropertyTypeCustomization + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + //~ End IPropertyTypeCustomization +}; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.cpp b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.cpp index c856736016ae..8204d9cb1d84 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.cpp +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.cpp @@ -2,9 +2,21 @@ #include "Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h" +#include "IDisplayClusterModularFeatureMediaInitializer.h" +#include "Features/IModularFeatures.h" + FDisplayClusterConfiguratorMediaUtils& FDisplayClusterConfiguratorMediaUtils::Get() { static FDisplayClusterConfiguratorMediaUtils Instance; return Instance; } + +FDisplayClusterConfiguratorMediaUtils::FDisplayClusterConfiguratorMediaUtils() +{ + // Obtain media initializer modular features once. We don't expect any of them to be loaded dynamically in runtime. + IModularFeatures& ModularFeatures = IModularFeatures::Get(); + ModularFeatures.LockModularFeatureList(); + MediaInitializers = ModularFeatures.GetModularFeatureImplementations(IDisplayClusterModularFeatureMediaInitializer::ModularFeatureName); + ModularFeatures.UnlockModularFeatureList(); +} diff --git a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h index a85cb284aa77..7586bc929444 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h +++ b/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterConfigurator/Private/Views/Details/Media/DisplayClusterConfiguratorMediaUtils.h @@ -4,12 +4,16 @@ #include "CoreMinimal.h" +class IDisplayClusterModularFeatureMediaInitializer; /** * Media customization utilities */ class FDisplayClusterConfiguratorMediaUtils { +protected: + FDisplayClusterConfiguratorMediaUtils(); + public: /** Singleton access */ @@ -17,15 +21,24 @@ public: public: - /** Tiled media auto-configuration event */ - DECLARE_EVENT_OneParam(FDisplayClusterConfiguratorMediaUtils, FDisplayClusterConfiguratorTiledMediaAutoConfigurationRequestedEvent, UObject*); - FDisplayClusterConfiguratorTiledMediaAutoConfigurationRequestedEvent& OnTiledMediaAutoConfiguration() + /** Returns media initializers */ + const TArray& GetMediaInitializers() const { - return TiledMediaAutoConfigurationEvent; + return MediaInitializers; + } + + /** Tiled media auto-configuration event */ + DECLARE_EVENT_OneParam(FDisplayClusterConfiguratorMediaUtils, FDisplayClusterConfiguratorMediaAutoConfigurationRequestedEvent, UObject*); + FDisplayClusterConfiguratorMediaAutoConfigurationRequestedEvent& OnMediaAutoConfiguration() + { + return MediaAutoConfigurationEvent; } private: + /** Media initializers (modular features) available. */ + TArray MediaInitializers; + /** Tiled media auto-configuration event */ - FDisplayClusterConfiguratorTiledMediaAutoConfigurationRequestedEvent TiledMediaAutoConfigurationEvent; + FDisplayClusterConfiguratorMediaAutoConfigurationRequestedEvent MediaAutoConfigurationEvent; }; diff --git a/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.cpp b/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.cpp index 2e70f7acc0c2..2893b2f1a0a9 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.cpp +++ b/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.cpp @@ -18,26 +18,58 @@ bool FSharedMemoryMediaInitializerFeature::IsMediaSubjectSupported(const UObject return false; } -void FSharedMemoryMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* MediaSubject, const FString& OwnerName, uint8 OwnerUniqueIdx, const FIntPoint& TilePos) +static constexpr const TCHAR* GetMediaPrefix(const IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType OwnerType) { - checkSlow(MediaSubject); + switch (OwnerType) + { + case IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::ICVFXCamera: + return TEXT("icam"); + + case IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Viewport: + return TEXT("vp"); + + case IDisplayClusterModularFeatureMediaInitializer::FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Backbuffer: + return TEXT("node"); + + default: + return TEXT("unknown"); + } +} + +void FSharedMemoryMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo, const FIntPoint& TilePos) +{ + const FString UniqueName = FString::Printf(TEXT("%s@%s_tile_%d:%d"), GetMediaPrefix(OnwerInfo.OwnerType), *OnwerInfo.OwnerName, TilePos.X, TilePos.Y); if (USharedMemoryMediaSource* SMMediaSource = Cast(MediaSubject)) { + SMMediaSource->UniqueName = UniqueName; SMMediaSource->bZeroLatency = true; SMMediaSource->Mode = ESharedMemoryMediaSourceMode::Framelocked; - SMMediaSource->UniqueName = GenerateUniqueName(OwnerName, TilePos); } else if (USharedMemoryMediaOutput* SMMediaOutput = Cast(MediaSubject)) { - SMMediaOutput->UniqueName = GenerateUniqueName(OwnerName, TilePos); + SMMediaOutput->UniqueName = UniqueName; SMMediaOutput->bInvertAlpha = true; SMMediaOutput->bCrossGpu = true; SMMediaOutput->NumberOfTextureBuffers = 4; } } -FString FSharedMemoryMediaInitializerFeature::GenerateUniqueName(const FString& OwnerName, const FIntPoint& TilePos) +void FSharedMemoryMediaInitializerFeature::InitializeMediaSubjectForFullFrame(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo) { - return FString::Printf(TEXT("%s_tile_%d:%d"), *OwnerName, TilePos.X, TilePos.Y); + const FString UniqueName = FString::Printf(TEXT("%s@%s"), GetMediaPrefix(OnwerInfo.OwnerType), *OnwerInfo.OwnerName); + + if (USharedMemoryMediaSource* SMMediaSource = Cast(MediaSubject)) + { + SMMediaSource->UniqueName = UniqueName; + SMMediaSource->bZeroLatency = true; + SMMediaSource->Mode = ESharedMemoryMediaSourceMode::Framelocked; + } + else if (USharedMemoryMediaOutput* SMMediaOutput = Cast(MediaSubject)) + { + SMMediaOutput->UniqueName = UniqueName; + SMMediaOutput->bInvertAlpha = true; + SMMediaOutput->bCrossGpu = true; + SMMediaOutput->NumberOfTextureBuffers = 4; + } } diff --git a/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.h b/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.h index 0d35fff3de09..dc8e17a4fd08 100644 --- a/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.h +++ b/Engine/Plugins/Runtime/nDisplay/Source/SharedMemoryMediaEditor/Private/ModularFeatures/SharedMemoryMediaInitializerFeature.h @@ -16,11 +16,7 @@ public: //~ Begin IDisplayClusterModularFeatureMediaInitializer virtual bool IsMediaSubjectSupported(const UObject* MediaSubject) override; - virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FString& OwnerName, uint8 OwnerUniqueIdx, const FIntPoint& TilePos) override; + virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo, const FIntPoint& TilePos) override; + virtual void InitializeMediaSubjectForFullFrame(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo) override; //~ End IDisplayClusterModularFeatureMediaInitializer - -private: - - /** Generates unique name for SMM subjects */ - FString GenerateUniqueName(const FString& OwnerName, const FIntPoint& TilePos); }; diff --git a/Engine/Plugins/Runtime/nDisplayModularFeatures/Source/DisplayClusterModularFeaturesEditor/Public/IDisplayClusterModularFeatureMediaInitializer.h b/Engine/Plugins/Runtime/nDisplayModularFeatures/Source/DisplayClusterModularFeaturesEditor/Public/IDisplayClusterModularFeatureMediaInitializer.h index be7567895dba..dac154115ff8 100644 --- a/Engine/Plugins/Runtime/nDisplayModularFeatures/Source/DisplayClusterModularFeaturesEditor/Public/IDisplayClusterModularFeatureMediaInitializer.h +++ b/Engine/Plugins/Runtime/nDisplayModularFeatures/Source/DisplayClusterModularFeaturesEditor/Public/IDisplayClusterModularFeatureMediaInitializer.h @@ -17,6 +17,43 @@ public: static const FName ModularFeatureName; public: + + /** + * Container to carrier the info about media subject's owner + */ + struct FMediaSubjectOwnerInfo + { + /** + * Type of the media subject's owner + */ + enum class EMediaSubjectOwnerType : uint8 + { + ICVFXCamera = 0, + Viewport, + Backbuffer + }; + + + /** Owner name (ICVFX camera component name, viewport or node name) */ + FString OwnerName; + + /** Owner type (ICVFX camera component name, viewport or node name) */ + EMediaSubjectOwnerType OwnerType; + + /** Optional unique index of the cluster node holding the owner object */ + TOptional ClusterNodeUniqueIdx = 0; + + /** + * Unique index of the owner + * Camera - within a config + * Viewport - within a cluster node + * Backbuffer - within a config + */ + uint8 OwnerUniqueIdx = 0; + }; + +public: + virtual ~IDisplayClusterModularFeatureMediaInitializer() = default; public: @@ -30,14 +67,19 @@ public: virtual bool IsMediaSubjectSupported(const UObject* MediaSubject) = 0; /** - * Performs initialization of a media subject + * Performs initialization of a media subject for tiled input/output * - * @param MediaSubject - UMediaSource or UMediaOutput instance - * @param OwnerName - Owner name (e.g. ICVFX camera component) - * @param OwnerUniqueIdx - Unique owner index - * @param TilePos - TIle XY-position - * - * @return true if media subject supported + * @param MediaSubject - UMediaSource or UMediaOutput instance + * @param OwnerInfo - Additional information about the object holding the media subject + * @param TilePos - TIle XY-position */ - virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FString& OwnerName, uint8 OwnerUniqueIdx, const FIntPoint& TilePos) = 0; + virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo, const FIntPoint& TilePos) = 0; + + /** + * Performs initialization of a media subject for full frame input/output + * + * @param MediaSubject - UMediaSource or UMediaOutput instance + * @param OwnerInfo - Additional information about the object holding the media subject + */ + virtual void InitializeMediaSubjectForFullFrame(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo) = 0; }; diff --git a/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.cpp b/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.cpp index d42bf63647ef..9af2dfb84446 100644 --- a/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.cpp +++ b/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.cpp @@ -21,10 +21,8 @@ bool FRivermaxMediaInitializerFeature::IsMediaSubjectSupported(const UObject* Me return false; } -void FRivermaxMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* MediaSubject, const FString& OwnerName, uint8 OwnerUniqueIdx, const FIntPoint& TilePos) +void FRivermaxMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo, const FIntPoint& TilePos) { - checkSlow(MediaSubject); - if (URivermaxMediaSource* RivermaxMediaSource = Cast(MediaSubject)) { RivermaxMediaSource->PlayerMode = ERivermaxPlayerMode::Framelock; @@ -34,7 +32,7 @@ void FRivermaxMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* Me RivermaxMediaSource->FrameRate = { 60,1 }; RivermaxMediaSource->PixelFormat = ERivermaxMediaSourcePixelFormat::RGB_10bit; RivermaxMediaSource->InterfaceAddress = GetRivermaxInterfaceAddress(); - RivermaxMediaSource->StreamAddress = GenerateStreamAddress(OwnerUniqueIdx, TilePos); + RivermaxMediaSource->StreamAddress = GenerateStreamAddress(OnwerInfo.OwnerUniqueIdx, TilePos); RivermaxMediaSource->Port = 50000; RivermaxMediaSource->bIsSRGBInput = false; RivermaxMediaSource->bUseGPUDirect = true; @@ -51,12 +49,64 @@ void FRivermaxMediaInitializerFeature::InitializeMediaSubjectForTile(UObject* Me RivermaxMediaOutput->FrameRate = { 60,1 }; RivermaxMediaOutput->PixelFormat = ERivermaxMediaOutputPixelFormat::PF_10BIT_RGB; RivermaxMediaOutput->InterfaceAddress = GetRivermaxInterfaceAddress(); - RivermaxMediaOutput->StreamAddress = GenerateStreamAddress(OwnerUniqueIdx, TilePos); + RivermaxMediaOutput->StreamAddress = GenerateStreamAddress(OnwerInfo.OwnerUniqueIdx, TilePos); RivermaxMediaOutput->Port = 50000; RivermaxMediaOutput->bUseGPUDirect = true; } } +void FRivermaxMediaInitializerFeature::InitializeMediaSubjectForFullFrame(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo) +{ + if (URivermaxMediaSource* RivermaxMediaSource = Cast(MediaSubject)) + { + RivermaxMediaSource->PlayerMode = ERivermaxPlayerMode::Framelock; + RivermaxMediaSource->bUseZeroLatency = true; + RivermaxMediaSource->bOverrideResolution = false; + //RivermaxMediaSource->Resolution = default value + RivermaxMediaSource->FrameRate = { 60,1 }; + RivermaxMediaSource->PixelFormat = ERivermaxMediaSourcePixelFormat::RGB_10bit; + RivermaxMediaSource->InterfaceAddress = GetRivermaxInterfaceAddress(); + RivermaxMediaSource->StreamAddress = GenerateStreamAddress(OnwerInfo.ClusterNodeUniqueIdx.Get(0), OnwerInfo.OwnerUniqueIdx, OnwerInfo.OwnerType); + RivermaxMediaSource->Port = 50000; + RivermaxMediaSource->bIsSRGBInput = false; + RivermaxMediaSource->bUseGPUDirect = true; + } + else if (URivermaxMediaOutput* RivermaxMediaOutput = Cast(MediaSubject)) + { + RivermaxMediaOutput->FrameLockingMode = ERivermaxFrameLockingMode::BlockOnReservation; + RivermaxMediaOutput->PresentationQueueSize = 2; + RivermaxMediaOutput->bOverrideResolution = false; + //RivermaxMediaOutput->Resolution = default value + RivermaxMediaOutput->PixelFormat = ERivermaxMediaOutputPixelFormat::PF_10BIT_RGB; + RivermaxMediaOutput->InterfaceAddress = GetRivermaxInterfaceAddress(); + RivermaxMediaOutput->StreamAddress = GenerateStreamAddress(OnwerInfo.ClusterNodeUniqueIdx.Get(0), OnwerInfo.OwnerUniqueIdx, OnwerInfo.OwnerType); + RivermaxMediaOutput->Port = 50000; + + switch (OnwerInfo.OwnerType) + { + case FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::ICVFXCamera: + case FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Viewport: + RivermaxMediaOutput->AlignmentMode = ERivermaxMediaAlignmentMode::FrameCreation; + RivermaxMediaOutput->bDoContinuousOutput = false; + RivermaxMediaOutput->bDoFrameCounterTimestamping = true; + RivermaxMediaOutput->FrameRate = { 60,1 }; + RivermaxMediaOutput->bUseGPUDirect = true; + break; + + case FMediaSubjectOwnerInfo::EMediaSubjectOwnerType::Backbuffer: + RivermaxMediaOutput->AlignmentMode = ERivermaxMediaAlignmentMode::AlignmentPoint; + RivermaxMediaOutput->bDoContinuousOutput = true; + RivermaxMediaOutput->bDoFrameCounterTimestamping = false; + RivermaxMediaOutput->FrameRate = { 24,1 }; + RivermaxMediaOutput->bUseGPUDirect = false; + break; + + default: + checkNoEntry(); + } + } +} + FString FRivermaxMediaInitializerFeature::GetRivermaxInterfaceAddress() const { FString ResultAddress{ TEXT("*.*.*.*") }; @@ -70,20 +120,11 @@ FString FRivermaxMediaInitializerFeature::GetRivermaxInterfaceAddress() const TArray Octets; Devices[0].InterfaceAddress.ParseIntoArray(Octets, TEXT(".")); - // IPv4? + // IPv4 always has 4 octets if (Octets.Num() == 4) { ResultAddress = FString::Printf(TEXT("%s.%s.%s.*"), *Octets[0], *Octets[1], *Octets[2]); } - // IPv6? - else - { - Devices[0].InterfaceAddress.ParseIntoArray(Octets, TEXT(":")); - if (Octets.Num() == 6) - { - ResultAddress = FString::Printf(TEXT("%s:%s:%s:%s:%s:*"), *Octets[0], *Octets[1], *Octets[2], *Octets[3], *Octets[4]); - } - } } return ResultAddress; @@ -91,8 +132,18 @@ FString FRivermaxMediaInitializerFeature::GetRivermaxInterfaceAddress() const FString FRivermaxMediaInitializerFeature::GenerateStreamAddress(uint8 OwnerUniqueIdx, const FIntPoint& TilePos) const { - constexpr uint8 MaxVal = TNumericLimits::Max(); - checkSlow(OwnerUniqueIdx < MaxVal && TilePos.X < MaxVal && TilePos.Y < MaxVal); + static const constexpr uint8 MaxVal = TNumericLimits::Max(); + checkSlow(TilePos.X < MaxVal && TilePos.Y < MaxVal); - return FString::Printf(TEXT("228.%u.%u.%u"), OwnerUniqueIdx + 1, TilePos.X + 1, TilePos.Y + 1); + static constexpr uint8 AddressOffsetForTiles = 200; + checkSlow((AddressOffsetForTiles + OwnerUniqueIdx) < MaxVal); + + // 228.200.*.* - 228.255.*.* - range for tiled media (max 56 objects) + return FString::Printf(TEXT("228.%u.%u.%u"), AddressOffsetForTiles + OwnerUniqueIdx, TilePos.X, TilePos.Y); +} + +FString FRivermaxMediaInitializerFeature::GenerateStreamAddress(uint8 ClusterNodeUniqueIdx, uint8 OwnerUniqueIdx, const FMediaSubjectOwnerInfo::EMediaSubjectOwnerType OwnerType) const +{ + // 228.0.*.* - 228.199.*.* - range for full-frame media (max 200 objects). But could be extended up to the limit if no tiles used. + return FString::Printf(TEXT("228.%u.%u.%u"), ClusterNodeUniqueIdx, static_cast(OwnerType), OwnerUniqueIdx); } diff --git a/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.h b/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.h index 86966faf7a52..f099d77e7888 100644 --- a/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.h +++ b/Engine/Plugins/VirtualProduction/Rivermax/RivermaxMedia/Source/RivermaxMediaEditor/Private/ModularFeatures/RivermaxMediaInitializerFeature.h @@ -16,7 +16,8 @@ public: //~ Begin IDisplayClusterModularFeatureMediaInitializer virtual bool IsMediaSubjectSupported(const UObject* MediaSubject) override; - virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FString& OwnerName, uint8 OwnerUniqueIdx, const FIntPoint& TilePos) override; + virtual void InitializeMediaSubjectForTile(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo, const FIntPoint& TilePos) override; + virtual void InitializeMediaSubjectForFullFrame(UObject* MediaSubject, const FMediaSubjectOwnerInfo& OnwerInfo) override; //~ End IDisplayClusterModularFeatureMediaInitializer private: @@ -26,4 +27,7 @@ private: /** Generates stream address based on the function parameters */ FString GenerateStreamAddress(uint8 OwnerUniqueIdx, const FIntPoint& TilePos) const; + + /** Generates stream address based on the function parameters */ + FString GenerateStreamAddress(uint8 ClusterNodeUniqueIdx, uint8 OwnerUniqueIdx, const FMediaSubjectOwnerInfo::EMediaSubjectOwnerType OwnerType) const; };