Clearing up plugin issues

This commit is contained in:
2025-09-05 15:58:28 +03:00
parent 0b65461e3b
commit 3fe0c90dfb
136 changed files with 15080 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <Factories/NDIMediaReceiverFactory.h>
#include <AssetTypeCategories.h>
#include <Objects/Media/NDIMediaReceiver.h>
#define LOCTEXT_NAMESPACE "NDIIOEditorMediaReceiverFactory"
UNDIMediaReceiverFactory::UNDIMediaReceiverFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer) {
this->bCreateNew = true;
this->bEditAfterNew = true;
this->SupportedClass = UNDIMediaReceiver::StaticClass();
}
FText UNDIMediaReceiverFactory::GetDisplayName() const { return LOCTEXT("NDIMediaReceiverFactoryDisplayName", "NDI Media Receiver"); }
uint32 UNDIMediaReceiverFactory::GetMenuCategories() const
{
return EAssetTypeCategories::Media;
}
UObject* UNDIMediaReceiverFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
return NewObject<UNDIMediaReceiver>(InParent, InClass, InName, Flags | RF_Transactional);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <Factories/NDIMediaSenderFactory.h>
#include <AssetTypeCategories.h>
#include <Objects/Media/NDIMediaSender.h>
#define LOCTEXT_NAMESPACE "NDIIOEditorMediaSenderFactory"
UNDIMediaSenderFactory::UNDIMediaSenderFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer) {
bCreateNew = true;
bEditAfterNew = true;
this->SupportedClass = UNDIMediaSender::StaticClass();
}
FText UNDIMediaSenderFactory::GetDisplayName() const { return LOCTEXT("NDIMediaSenderFactoryDisplayName", "NDI Media Sender"); }
uint32 UNDIMediaSenderFactory::GetMenuCategories() const { return EAssetTypeCategories::Media; }
UObject* UNDIMediaSenderFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
return NewObject<UNDIMediaSender>(InParent, InClass, InName, Flags | RF_Transactional);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <Factories/NDIMediaSoundWaveFactory.h>
#include <AssetTypeCategories.h>
#include <Objects/Media/NDIMediaSoundWave.h>
#define LOCTEXT_NAMESPACE "NDIIOEditorMediaSoundWaveFactory"
UNDIMediaSoundWaveFactory::UNDIMediaSoundWaveFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer) {
this->bCreateNew = true;
this->bEditAfterNew = true;
this->SupportedClass = UNDIMediaSoundWave::StaticClass();
}
FText UNDIMediaSoundWaveFactory::GetDisplayName() const { return LOCTEXT("NDIMediaSoundWaveFactoryDisplayName", "NDI Media Sound Wave"); }
uint32 UNDIMediaSoundWaveFactory::GetMenuCategories() const { return EAssetTypeCategories::Sounds; }
UObject* UNDIMediaSoundWaveFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
return NewObject<UNDIMediaSoundWave>(InParent, InName, Flags | RF_Transactional);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,40 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <Factories/NDIMediaTexture2DFactory.h>
#include <AssetTypeCategories.h>
#include <Objects/Media/NDIMediaTexture2D.h>
#include <Misc/EngineVersionComparison.h>
#define LOCTEXT_NAMESPACE "NDIIOEditorMediaSoundWaveFactory"
UNDIMediaTexture2DFactory::UNDIMediaTexture2DFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer) {
this->bCreateNew = true;
this->bEditAfterNew = true;
this->SupportedClass = UNDIMediaTexture2D::StaticClass();
}
FText UNDIMediaTexture2DFactory::GetDisplayName() const { return LOCTEXT("NDIMediaTexture2DFactoryDisplayName", "NDI Media Texture2D"); }
uint32 UNDIMediaTexture2DFactory::GetMenuCategories() const { return EAssetTypeCategories::Textures; }
UObject* UNDIMediaTexture2DFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
if (UNDIMediaTexture2D* Resource = NewObject<UNDIMediaTexture2D>(InParent, InName, Flags | RF_Transactional))
{
Resource->UpdateResource();
return Resource;
}
return nullptr;
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,136 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <NDIIOEditorModule.h>
#include <Editor.h>
#include <PropertyEditorModule.h>
#include <IPlacementModeModule.h>
#include <Interfaces/IPluginManager.h>
#include <Styling/SlateStyleRegistry.h>
#include <Actors/NDIReceiveActor.h>
#include <Actors/NDIBroadcastActor.h>
#include <Framework/Application/SlateApplication.h>
#include <Misc/EngineVersionComparison.h>
#include "Widgets/NDIWidgets.h"
#define LOCTEXT_NAMESPACE "FNDIEditorModule"
#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(StyleInstance->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)
#define PLACEMENT_CATEGORY TEXT("NDI(R)")
#define PLACEMENT_LOCTEXT NSLOCTEXT("Vizrt", "NDI", "NDI(R)")
#define PLACEMENT_TEXT TEXT("PMNDI")
void FNDIIOEditorModule::StartupModule()
{
const FName& CategoryName = PLACEMENT_CATEGORY;
IPlacementModeModule& PlacementModeModule = IPlacementModeModule::Get();
const FVector2D Icon20x20(20.0f, 20.0f);
const FVector2D Icon64x64(64.0f, 64.0f);
this->StyleInstance = MakeUnique<FSlateStyleSet>("NDIEditorStyle");
if (IPlugin* NDIIOPlugin = IPluginManager::Get().FindPlugin("NDIIOPlugin").Get())
{
StyleInstance->SetContentRoot(FPaths::Combine(NDIIOPlugin->GetContentDir(), TEXT("Editor/Icons")));
StyleInstance->Set("ClassThumbnail.NDIBroadcastActor", new IMAGE_BRUSH("NDIBroadcastActorIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIBroadcastActor", new IMAGE_BRUSH("NDIBroadcastActorIcon_x20", Icon20x20));
StyleInstance->Set("ClassThumbnail.NDIReceiveActor", new IMAGE_BRUSH("NDIReceiveActorIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIReceiveActor", new IMAGE_BRUSH("NDIReceiveActorIcon_x20", Icon20x20));
StyleInstance->Set("ClassThumbnail.NDIMediaReceiver", new IMAGE_BRUSH("NDIReceiverIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIMediaReceiver", new IMAGE_BRUSH("NDIReceiverIcon_x20", Icon20x20));
StyleInstance->Set("ClassThumbnail.NDIMediaSender", new IMAGE_BRUSH("NDISenderIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIMediaSender", new IMAGE_BRUSH("NDISenderIcon_x20", Icon20x20));
StyleInstance->Set("ClassThumbnail.NDIMediaSoundWave", new IMAGE_BRUSH("NDISoundWaveIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIMediaSoundWave", new IMAGE_BRUSH("NDISoundWaveIcon_x20", Icon20x20));
StyleInstance->Set("ClassThumbnail.NDIMediaTexture2D", new IMAGE_BRUSH("NDIVideoTextureIcon_x64", Icon64x64));
StyleInstance->Set("ClassIcon.NDIMediaTexture2D", new IMAGE_BRUSH("NDIVideoTextureIcon_x20", Icon20x20));
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance.Get());
PlacementModeModule.RegisterPlacementCategory(
FPlacementCategoryInfo(
PLACEMENT_LOCTEXT,
CategoryName,
PLACEMENT_TEXT,
41, // FBuiltInPlacementCategories::Volumes() == 40
true
)
);
}
// Get the Registered Placement Category
if (const FPlacementCategoryInfo* PlacementCategoryInformation = PlacementModeModule.GetRegisteredPlacementCategory(CategoryName))
{
// Register the NDI Broadcast Actor a placeable item within the editor
PlacementModeModule.RegisterPlaceableItem(PlacementCategoryInformation->UniqueHandle, MakeShareable(
new FPlaceableItem(
*UActorFactory::StaticClass(),
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 6)) // 5.6 or later
FAssetData(GetDefault<ANDIBroadcastActor>()),
#else
FAssetData(ANDIBroadcastActor::StaticClass()->ClassDefaultObject),
#endif
FName("ClassThumbnail.NDIBroadcastActor"),
NAME_None,
TOptional<FLinearColor>(),
10,
NSLOCTEXT("Vizrt", "NDIBroadcastActor", "NDI Broadcast Actor")
))
);
// Register the NDI Receive Actor a placeable item within the editor
PlacementModeModule.RegisterPlaceableItem(PlacementCategoryInformation->UniqueHandle, MakeShareable(
new FPlaceableItem(
*UActorFactory::StaticClass(),
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 6)) // 5.6 or later
FAssetData(GetDefault<ANDIReceiveActor>()),
#else
FAssetData(ANDIReceiveActor::StaticClass()->ClassDefaultObject),
#endif
FName("ClassThumbnail.NDIReceiveActor"),
NAME_None,
TOptional<FLinearColor>(),
20,
NSLOCTEXT("Vizrt", "NDIReceiveActor", "NDI Receive Actor")
))
);
}
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.RegisterCustomPropertyTypeLayout(FNDIConnectionInformation::StaticStruct()->GetFName(), FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FNDIConnectionInformationCustomization::MakeInstance));
}
void FNDIIOEditorModule::ShutdownModule()
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.UnregisterCustomPropertyTypeLayout(FNDIConnectionInformation::StaticStruct()->GetFName());
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance.Get());
StyleInstance.Reset();
IPlacementModeModule& PlacementModeModule = IPlacementModeModule::Get();
PlacementModeModule.UnregisterPlacementCategory(PLACEMENT_CATEGORY);
}
#undef PLACEMENT_CATEGORY
#undef PLACEMENT_LOCTEXT
#undef PLACEMENT_TEXT
#undef IMAGE_BRUSH
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,380 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#include <Widgets/NDIWidgets.h>
#include <Services/NDIFinderService.h>
#include <DetailLayoutBuilder.h>
#include <DetailWidgetRow.h>
#include <Editor.h>
#include <IDetailChildrenBuilder.h>
#include <IPropertyUtilities.h>
#include <PropertyHandle.h>
#include <Framework/MultiBox/MultiBoxBuilder.h>
#include <Widgets/Input/SComboButton.h>
#include <atomic>
#define LOCTEXT_NAMESPACE "UNDIWidgets"
/**
Organizes NDI sources into a tree
*/
struct FNDISourceTreeItem
{
TArray<TSharedRef<FNDISourceTreeItem> > Children;
FNDIConnectionInformation NDISource;
FText DisplayText;
bool IsExpanded { false };
bool IsSelected { false };
FNDISourceTreeItem()
{}
FNDISourceTreeItem(const FText& DisplayTextIn)
: DisplayText(DisplayTextIn)
{}
FNDISourceTreeItem(const FNDIConnectionInformation& Source)
: NDISource(Source)
{}
FNDISourceTreeItem(TSharedRef<FNDISourceTreeItem>&& Child)
{
Children.Add(Child);
}
static const TSharedRef<FNDISourceTreeItem>* FindMachineNode(const FNDISourceTreeItem& RootNode, const FNDIConnectionInformation& SourceItem)
{
const TSharedRef<FNDISourceTreeItem>* MachineNode = nullptr;
if(!SourceItem.MachineName.IsEmpty())
{
const FString& SearchName = SourceItem.MachineName;
MachineNode = RootNode.Children.FindByPredicate([&SearchName](const TSharedRef<FNDISourceTreeItem>& Child)
{
if(Child->Children.Num() > 0)
return Child->Children[0]->NDISource.MachineName == SearchName;
else
return false;
});
}
else if(!SourceItem.Url.IsEmpty())
{
const FString& SearchName = SourceItem.Url;
MachineNode = RootNode.Children.FindByPredicate([&SearchName](const TSharedRef<FNDISourceTreeItem>& Child)
{
if(Child->Children.Num() > 0)
return Child->Children[0]->NDISource.Url == SearchName;
else
return false;
});
}
return MachineNode;
}
static const TSharedRef<FNDISourceTreeItem>* FindStreamNodeInMachineNode(const TSharedRef<FNDISourceTreeItem>& MachineNode, const FNDIConnectionInformation& SourceItem)
{
const TSharedRef<FNDISourceTreeItem>* StreamNode = nullptr;
if(!SourceItem.StreamName.IsEmpty())
{
const FString& SearchName = SourceItem.StreamName;
StreamNode = MachineNode->Children.FindByPredicate([&SearchName](const TSharedRef<FNDISourceTreeItem>& Child)
{
return Child->NDISource.StreamName == SearchName;
});
}
else if(!SourceItem.Url.IsEmpty())
{
const FString& SearchName = SourceItem.Url;
StreamNode = MachineNode->Children.FindByPredicate([&SearchName](const TSharedRef<FNDISourceTreeItem>& Child)
{
return Child->NDISource.Url == SearchName;
});
}
return StreamNode;
}
void SetFromSources(const TArray<FNDIConnectionInformation>& SourceItems, const FText& SearchingTxt, bool StartExpanded)
{
FNDISourceTreeItem RootNode;
//
// Build new tree
//
for(int32 i = 0; i < SourceItems.Num(); ++i)
{
const TSharedRef<FNDISourceTreeItem>* MachineNode = FindMachineNode(RootNode, SourceItems[i]);
if(MachineNode != nullptr)
{
FNDISourceTreeItem* NewNode = new FNDISourceTreeItem(SourceItems[i]);
(*MachineNode)->Children.Add(MakeShareable(NewNode));
}
else
{
FNDISourceTreeItem* NewNode = new FNDISourceTreeItem(SourceItems[i]);
FNDISourceTreeItem* NewMachineNode = new FNDISourceTreeItem(MakeShareable(NewNode));
RootNode.Children.Add(MakeShareable(NewMachineNode));
}
}
//
// Preserve expansion and selection state by matching with old tree
//
for(int32 i = 0; i < RootNode.Children.Num(); ++i)
{
const TSharedRef<FNDISourceTreeItem>* OldMachineNode = FindMachineNode(*this, RootNode.Children[i]->Children[0]->NDISource);
if(OldMachineNode != nullptr)
{
RootNode.Children[i]->IsExpanded = (*OldMachineNode)->IsExpanded;
for(int32 j = 0; j < RootNode.Children[i]->Children.Num(); ++j)
{
const TSharedRef<FNDISourceTreeItem>* OldStreamNode = FindStreamNodeInMachineNode(*OldMachineNode, RootNode.Children[i]->Children[j]->NDISource);
if(OldStreamNode != nullptr)
{
RootNode.Children[i]->Children[j]->IsSelected = (*OldStreamNode)->IsSelected;
}
}
}
else
{
RootNode.Children[i]->IsExpanded = StartExpanded;
}
}
if(RootNode.Children.Num() == 0)
{
RootNode.Children.Add(MakeShareable(new FNDISourceTreeItem(SearchingTxt)));
}
//
// Set to new tree
//
*this = RootNode;
}
};
/**
A menu widget containing NDI sources
*/
DECLARE_DELEGATE_OneParam(FOnSourceClicked, FNDIConnectionInformation);
class SNDISourcesMenu : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SNDISourcesMenu)
: _OnSourceClicked()
{}
SLATE_EVENT(FOnSourceClicked, OnSourceClicked)
SLATE_END_ARGS()
SNDISourcesMenu()
{}
virtual ~SNDISourcesMenu()
{
FNDIFinderService::EventOnNDISourceCollectionChanged.Remove(SourceCollectionChangedEventHandle);
SourceCollectionChangedEventHandle.Reset();
}
void Construct(const FArguments& InArgs)
{
OnSourceClicked = InArgs._OnSourceClicked;
ChildSlot
[
SNew(SComboButton)
.ButtonContent()
[
SNew(STextBlock)
.Font(IDetailLayoutBuilder::GetDetailFont())
.ToolTipText(LOCTEXT("NDI Sources Tip", "Currently Available NDI Sources"))
.Text(LOCTEXT("NDI Sources", "NDI Sources"))
]
.OnGetMenuContent_Lambda([this]() -> TSharedRef<SWidget>
{
FMenuBuilder MenuBuilder(true, nullptr);
for (const auto& Sources : SourceTreeItems.Children)
ConstructSourceMenu(MenuBuilder, Sources.Get());
return MenuBuilder.MakeWidget();
})
];
UpdateSources = true;
FNDIFinderService::EventOnNDISourceCollectionChanged.Remove(SourceCollectionChangedEventHandle);
SourceCollectionChangedEventHandle.Reset();
SourceCollectionChangedEventHandle = FNDIFinderService::EventOnNDISourceCollectionChanged.AddLambda([this]()
{
UpdateSources = true;
});
}
virtual void Tick(const FGeometry& AllottedGeometry, const double CurrentTime, const float DeltaTime) override
{
bool IsDifferent = false;
if (UpdateSources.exchange(false))
{
IsDifferent = FNDIFinderService::UpdateSourceCollection(SourceItems);
}
if (SourceItems.Num() == 0)
{
FText NewSearchingTxt;
double WholeTime = 0.0;
double FracTime = FMath::Modf(CurrentTime, &WholeTime);
if(FracTime < 1/4.0)
NewSearchingTxt = FText(LOCTEXT("NDI Sources Searching0", "Searching"));
else if(FracTime < 2/4.0)
NewSearchingTxt = FText(LOCTEXT("NDI Sources Searching1", "Searching."));
else if(FracTime < 3/4.0)
NewSearchingTxt = FText(LOCTEXT("NDI Sources Searching2", "Searching.."));
else
NewSearchingTxt = FText(LOCTEXT("NDI Sources Searching3", "Searching..."));
if(!NewSearchingTxt.EqualTo(SearchingTxt))
{
SearchingTxt = NewSearchingTxt;
IsDifferent = true;
}
}
if (IsDifferent)
{
SourceTreeItems.SetFromSources(SourceItems, SearchingTxt, false);
Invalidate(EInvalidateWidgetReason::PaintAndVolatility | EInvalidateWidgetReason::ChildOrder);
}
SCompoundWidget::Tick(AllottedGeometry, CurrentTime, DeltaTime);
}
protected:
void ConstructSourceMenu(FMenuBuilder& MenuBuilder, const FNDISourceTreeItem& SourceTreeItem)
{
if (SourceTreeItem.NDISource.IsValid())
{
MenuBuilder.AddMenuEntry(
FText::FromString(SourceTreeItem.NDISource.StreamName),
FText::GetEmpty(),
FSlateIcon(),
FUIAction(FExecuteAction::CreateLambda([this,&SourceTreeItem]()
{
this->OnSourceClicked.ExecuteIfBound(SourceTreeItem.NDISource);
})),
NAME_None,
EUserInterfaceActionType::Button
);
}
else if (SourceTreeItem.Children.Num() > 0)
{
MenuBuilder.AddSubMenu(
FText::FromString(SourceTreeItem.Children[0]->NDISource.MachineName),
FText::GetEmpty(),
FNewMenuDelegate::CreateLambda([this,&SourceTreeItem](FMenuBuilder& MenuBuilder)
{
for(const auto& ChildSource : SourceTreeItem.Children)
ConstructSourceMenu(MenuBuilder, ChildSource.Get());
})
);
}
else if (!SourceTreeItem.DisplayText.IsEmpty())
{
MenuBuilder.AddMenuEntry(
SourceTreeItem.DisplayText,
FText::GetEmpty(),
FSlateIcon(),
FUIAction(FExecuteAction::CreateLambda([this]
{
})),
NAME_None,
EUserInterfaceActionType::Button
);
}
}
private:
TArray<FNDIConnectionInformation> SourceItems;
FText SearchingTxt;
FNDISourceTreeItem SourceTreeItems;
FDelegateHandle SourceCollectionChangedEventHandle;
std::atomic_bool UpdateSources { false };
FOnSourceClicked OnSourceClicked;
};
/**
Customization of NDIConnectionInformation property
by including a menu to select from currently available NDI sources
*/
TSharedRef<IPropertyTypeCustomization> FNDIConnectionInformationCustomization::MakeInstance()
{
return MakeShareable(new FNDIConnectionInformationCustomization);
}
void FNDIConnectionInformationCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
HeaderRow.NameContent()
[
PropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
[
SNew(SNDISourcesMenu)
.OnSourceClicked_Lambda([this,PropertyHandle](FNDIConnectionInformation Source)
{
TArray<void*> RawData;
PropertyHandle->AccessRawData(RawData);
FNDIConnectionInformation* ConnectionInformation = reinterpret_cast<FNDIConnectionInformation*>(RawData[0]);
if (ConnectionInformation != nullptr)
{
ConnectionInformation->Url = "";
PropertyHandle->GetChildHandle("SourceName")->SetValue(Source.SourceName);
}
})
].IsEnabled(true);
}
void FNDIConnectionInformationCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
TSharedPtr<IPropertyUtilities> PropertyUtils = CustomizationUtils.GetPropertyUtilities();
uint32 NumberOfChild;
if (PropertyHandle->GetNumChildren(NumberOfChild) == FPropertyAccess::Success)
{
for (uint32 Index = 0; Index < NumberOfChild; ++Index)
{
TSharedRef<IPropertyHandle> ChildPropertyHandle = PropertyHandle->GetChildHandle(Index).ToSharedRef();
ChildBuilder.AddProperty(ChildPropertyHandle)
.ShowPropertyButtons(true)
.IsEnabled(MakeAttributeLambda([=] { return !PropertyHandle->IsEditConst() && PropertyUtils->IsPropertyEditingEnabled(); }));
}
}
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,92 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
using System;
using System.IO;
using UnrealBuildTool;
public class NDIIOEditor : ModuleRules
{
public NDIIOEditor(ReadOnlyTargetRules Target) : base(Target)
{
#if UE_5_2_OR_LATER
IWYUSupport = IWYUSupport.Full;
#else
bEnforceIWYU = true;
#endif
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
#region Public Includes
if (Directory.Exists(Path.Combine(ModuleDirectory, "Public")))
{
PublicIncludePaths.AddRange(new string[] {
// ... add public include paths required here ...
Path.Combine(ModuleDirectory, "Public" ),
});
}
PublicDependencyModuleNames.AddRange(new string[] {
"Engine",
"Core",
"CoreUObject"
});
#endregion
if (Target.bBuildEditor == true)
{
#region Private Includes
if (Directory.Exists(Path.Combine(ModuleDirectory, "Private")))
{
PrivateIncludePaths.AddRange(new string[] {
// ... add other private include paths required here ...
Path.Combine(ModuleDirectory, "Private" ),
Path.Combine(ModuleDirectory, "../Core/Private"),
});
}
#endregion
PrivateIncludePathModuleNames.AddRange(new string[] {
"AssetTools",
"TargetPlatform",
});
PrivateDependencyModuleNames.AddRange(new string[] {
"Projects",
"UnrealEd",
"AssetTools",
"MaterialUtilities",
"Renderer",
"RenderCore",
"PlacementMode",
"CinematicCamera",
"RHI",
"Slate",
"SlateCore",
"UMG",
"ImageWrapper",
"Media",
"MediaAssets",
"MediaUtils",
"AssetTools",
"TargetPlatform",
"PropertyEditor",
"DetailCustomizations",
"EditorStyle",
"NDIIO"
});
}
}
}

View File

@@ -0,0 +1,30 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <Factories/Factory.h>
#include <UObject/Object.h>
#include "NDIMediaReceiverFactory.generated.h"
/**
Factory Class used to create assets via content browser for NDI Receiver objects
*/
UCLASS()
class NDIIOEDITOR_API UNDIMediaReceiverFactory : public UFactory
{
GENERATED_UCLASS_BODY()
public:
virtual FText GetDisplayName() const override;
virtual uint32 GetMenuCategories() const override;
virtual bool ShouldShowInNewMenu() const override { return true; }
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
};

View File

@@ -0,0 +1,29 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <Factories/Factory.h>
#include <UObject/Object.h>
#include "NDIMediaSenderFactory.generated.h"
/**
Factory Class used to create assets via content browser for NDI Sender objects
*/
UCLASS()
class NDIIOEDITOR_API UNDIMediaSenderFactory : public UFactory
{
GENERATED_UCLASS_BODY()
public:
virtual FText GetDisplayName() const override;
virtual uint32 GetMenuCategories() const override;
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
};

View File

@@ -0,0 +1,29 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <Factories/Factory.h>
#include <UObject/Object.h>
#include "NDIMediaSoundWaveFactory.generated.h"
/**
Factory Class used to create assets via content browser for NDI Sound Wave objects
*/
UCLASS()
class NDIIOEDITOR_API UNDIMediaSoundWaveFactory : public UFactory
{
GENERATED_UCLASS_BODY()
public:
virtual FText GetDisplayName() const override;
virtual uint32 GetMenuCategories() const override;
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
};

View File

@@ -0,0 +1,29 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <Factories/Factory.h>
#include <UObject/Object.h>
#include "NDIMediaTexture2DFactory.generated.h"
/**
Factory Class used to create assets via content browser for NDI Texture2D objects
*/
UCLASS()
class NDIIOEDITOR_API UNDIMediaTexture2DFactory : public UFactory
{
GENERATED_UCLASS_BODY()
public:
virtual FText GetDisplayName() const override;
virtual uint32 GetMenuCategories() const override;
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
};

View File

@@ -0,0 +1,12 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#define NDIIO_EDITOR_MODULE_NAME FName(TEXT("NDIIOEditor"))

View File

@@ -0,0 +1,25 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <Modules/ModuleManager.h>
#include <Styling/SlateStyle.h>
class NDIIOEDITOR_API FNDIIOEditorModule : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
private:
TUniquePtr<FSlateStyleSet> StyleInstance;
};
IMPLEMENT_MODULE(FNDIIOEditorModule, NDIIOEditor)

View File

@@ -0,0 +1,29 @@
/*
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
*/
#pragma once
#include <CoreMinimal.h>
#include <IPropertyTypeCustomization.h>
/**
Customization of NDIConnectionInformation property
by including a menu to select from currently available NDI sources
*/
class FNDIConnectionInformationCustomization : public IPropertyTypeCustomization
{
public:
static TSharedRef<IPropertyTypeCustomization> MakeInstance();
// IDetailCustomization interface
virtual void CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) override;
virtual void CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override;
private:
};