Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

234 lines
7.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SLiveLinkDataView.h"
#include "DetailsViewArgs.h"
#include "LiveLinkMetaDataDetailCustomization.h"
#include "IDetailsView.h"
#include "LiveLinkClient.h"
#include "LiveLinkRole.h"
#include "LiveLinkSubjectSettings.h"
#include "IStructureDetailsView.h"
#include "Modules/ModuleManager.h"
#include "PropertyEditorModule.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "Widgets/Input/SComboButton.h"
#include "Widgets/Input/SSpinBox.h"
#include "Widgets/Layout/SWidgetSwitcher.h"
#define LOCTEXT_NAMESPACE "LiveLinkDataView"
void SLiveLinkDataView::Construct(const FArguments& Args, FLiveLinkClient* InClient)
{
Client = InClient;
LastUpdateSeconds = 0.0;
UpdateDelay = 1.0;
DetailType = EDetailType::Property;
FMenuBuilder DetailViewOptions(true, nullptr);
DetailViewOptions.BeginSection("Properties", LOCTEXT("Properties", "Properties"));
{
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowSubjectDetail", "Show Subject Properties"),
LOCTEXT("ShowSubjectDetail_ToolTip", "Displays the subject properties"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateSP(this, &SLiveLinkDataView::OnSelectDetailWidget, EDetailType::Property),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SLiveLinkDataView::IsSelectedDetailWidget, EDetailType::Property)
),
NAME_None,
EUserInterfaceActionType::RadioButton
);
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowStaticDataDetail", "Show Static Data"),
LOCTEXT("ShowStaticData_ToolTip", "Displays the subject static data"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateSP(this, &SLiveLinkDataView::OnSelectDetailWidget, EDetailType::StaticData),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SLiveLinkDataView::IsSelectedDetailWidget, EDetailType::StaticData)
),
NAME_None,
EUserInterfaceActionType::RadioButton
);
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowFrameDataDetail", "Show Frame Data"),
LOCTEXT("ShowFrameData_ToolTip", "Displays the subject frame data"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateSP(this, &SLiveLinkDataView::OnSelectDetailWidget, EDetailType::FrameData),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SLiveLinkDataView::IsSelectedDetailWidget, EDetailType::FrameData)
),
NAME_None,
EUserInterfaceActionType::RadioButton
);
}
DetailViewOptions.EndSection();
DetailViewOptions.BeginSection("Settings", LOCTEXT("Settings", "Settings"));
{
TSharedRef<SWidget> RefreshDelay = SNew(SSpinBox<double>)
.MinValue(0.0)
.MaxValue(10.0)
.MinSliderValue(0.0)
.MaxSliderValue(10.0)
.ToolTipText(LOCTEXT("RefreshDelay_ToolTip", "Refresh delay of Static & Frame data."))
.Value(this, &SLiveLinkDataView::GetRefreshDelay)
.OnValueCommitted(this, &SLiveLinkDataView::SetRefreshDelayInternal)
.IsEnabled(this, &SLiveLinkDataView::CanEditRefreshDelay);
DetailViewOptions.AddWidget(RefreshDelay, LOCTEXT("RefreshDelay", "Refresh Delay"));
}
DetailViewOptions.EndSection();
FDetailsViewArgs DetailsViewArgs;
DetailsViewArgs.bUpdatesFromSelection = false;
DetailsViewArgs.bLockable = false;
DetailsViewArgs.bShowPropertyMatrixButton = false;
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
DetailsViewArgs.ViewIdentifier = NAME_None;
DetailsViewArgs.bShowCustomFilterOption = false;
DetailsViewArgs.bShowOptions = false;
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
SettingsDetailsView = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
SettingsDetailsView->OnFinishedChangingProperties().AddSP(this, &SLiveLinkDataView::OnPropertyChanged);
SettingsDetailsView->SetIsPropertyEditingEnabledDelegate(FIsPropertyEditingEnabled::CreateLambda([bReadOnly = Args._ReadOnly](){ return !bReadOnly.Get(); }));
FStructureDetailsViewArgs StructViewArgs;
StructureDetailsView = PropertyEditorModule.CreateStructureDetailView(DetailsViewArgs, StructViewArgs, TSharedPtr<FStructOnScope>());
StructureDetailsView->GetDetailsView()->SetIsPropertyEditingEnabledDelegate(FIsPropertyEditingEnabled::CreateLambda([]() { return false; }));
StructureDetailsView->GetDetailsView()->RegisterInstancedCustomPropertyTypeLayout(FLiveLinkMetaData::StaticStruct()->GetFName(),
FOnGetPropertyTypeCustomizationInstance::CreateLambda([](){ return MakeShared<FLiveLinkMetaDataDetailCustomization>(); })
);
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNullWidget::NullWidget
]
+ SHorizontalBox::Slot()
.HAlign(HAlign_Right)
.AutoWidth()
[
SNew(SComboButton)
.ContentPadding(0)
.ForegroundColor(FSlateColor::UseForeground())
.ButtonStyle(FAppStyle::Get(), "ToggleButton")
.MenuContent()
[
DetailViewOptions.MakeWidget()
]
.ButtonContent()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0, 0, 2, 0)
.VAlign(VAlign_Center)
[
SNew(SImage)
.ColorAndOpacity(FSlateColor::UseForeground())
.Image(FSlateIcon(FAppStyle::Get().GetStyleSetName(), "Icons.Visibility").GetIcon())
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2, 0, 0, 0)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(LOCTEXT("ViewButton", "View Options"))
]
]
]
]
+ SVerticalBox::Slot()
.Padding(FMargin(0.0, 2.0))
[
SNew(SWidgetSwitcher)
.WidgetIndex(this, &SLiveLinkDataView::GetDetailWidgetIndex)
+ SWidgetSwitcher::Slot()
[
SettingsDetailsView.ToSharedRef()
]
+ SWidgetSwitcher::Slot()
[
StructureDetailsView->GetWidget().ToSharedRef()
]
]
];
}
void SLiveLinkDataView::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
Super::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
if (DetailType != EDetailType::Property && InCurrentTime - LastUpdateSeconds > UpdateDelay)
{
LastUpdateSeconds = InCurrentTime;
if (Client->IsSubjectEnabled(SubjectKey, true))
{
TSubclassOf<ULiveLinkRole> SubjectRole = Client->GetSubjectRole_AnyThread(SubjectKey.SubjectName);
if (SubjectRole)
{
FLiveLinkSubjectFrameData SubjectData;
if (Client->EvaluateFrame_AnyThread(SubjectKey.SubjectName, SubjectRole, SubjectData))
{
if (DetailType == EDetailType::StaticData)
{
TSharedPtr<FStructOnScope> StructOnScope = MakeShared<FStructOnScope>(SubjectData.StaticData.GetStruct());
CastChecked<UScriptStruct>(StructOnScope->GetStruct())->CopyScriptStruct(StructOnScope->GetStructMemory(), SubjectData.StaticData.GetBaseData());
StructureDetailsView->SetStructureData(StructOnScope);
}
else
{
TSharedPtr<FStructOnScope> StructOnScope = MakeShared<FStructOnScope>(SubjectData.FrameData.GetStruct());
CastChecked<UScriptStruct>(StructOnScope->GetStruct())->CopyScriptStruct(StructOnScope->GetStructMemory(), SubjectData.FrameData.GetBaseData());
StructureDetailsView->SetStructureData(StructOnScope);
}
}
}
}
}
}
void SLiveLinkDataView::SetSubjectKey(FLiveLinkSubjectKey InSubjectKey)
{
SubjectKey = InSubjectKey;
UObject* SettingsObject = Client->GetSubjectSettings(SubjectKey);
SettingsDetailsView->SetObject(SettingsObject);
}
int32 SLiveLinkDataView::GetDetailWidgetIndex() const
{
return DetailType == EDetailType::Property ? 0 : 1;
}
void SLiveLinkDataView::OnSelectDetailWidget(EDetailType InDetailType)
{
DetailType = InDetailType;
}
void SLiveLinkDataView::OnPropertyChanged(const FPropertyChangedEvent& InEvent)
{
Client->OnPropertyChanged(SubjectKey.Source, InEvent);
}
#undef LOCTEXT_NAMESPACE