First commit
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
136
Plugins/NDIIO/Source/Editor/Classes/NDIIOEditorModule.cpp
Normal file
136
Plugins/NDIIO/Source/Editor/Classes/NDIIOEditorModule.cpp
Normal 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
|
||||
380
Plugins/NDIIO/Source/Editor/Classes/Widgets/NDIWidgets.cpp
Normal file
380
Plugins/NDIIO/Source/Editor/Classes/Widgets/NDIWidgets.cpp
Normal 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
|
||||
92
Plugins/NDIIO/Source/Editor/NDIIOEditor.Build.cs
Normal file
92
Plugins/NDIIO/Source/Editor/NDIIOEditor.Build.cs
Normal 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"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
12
Plugins/NDIIO/Source/Editor/Public/NDIIOEditorAPI.h
Normal file
12
Plugins/NDIIO/Source/Editor/Public/NDIIOEditorAPI.h
Normal 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"))
|
||||
25
Plugins/NDIIO/Source/Editor/Public/NDIIOEditorModule.h
Normal file
25
Plugins/NDIIO/Source/Editor/Public/NDIIOEditorModule.h
Normal 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)
|
||||
29
Plugins/NDIIO/Source/Editor/Public/Widgets/NDIWidgets.h
Normal file
29
Plugins/NDIIO/Source/Editor/Public/Widgets/NDIWidgets.h
Normal 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:
|
||||
};
|
||||
Reference in New Issue
Block a user