// Copyright Epic Games, Inc. All Rights Reserved. #include "SubmixDetailsCustomization.h" #include "Misc/PackageName.h" #include "Widgets/Layout/SBox.h" #include "Widgets/Input/SButton.h" #include "Widgets/Input/SComboBox.h" #include "Widgets/Text/STextBlock.h" #include "DetailLayoutBuilder.h" #include "DetailWidgetRow.h" #include "IDetailChildrenBuilder.h" #include "IDetailPropertyRow.h" #include "DetailCategoryBuilder.h" #include "ISoundfieldFormat.h" #include "IAudioEndpoint.h" #include "ISoundfieldEndpoint.h" #include "Sound/SoundSubmix.h" #define LOCTEXT_NAMESPACE "SubmixDetailsInspector" FText FNameSelectorGenerator::GetComboBoxContent() const { FName DesiredName = CachedCallbacks.GetCurrentlySelectedName(); return FText::FromName(DesiredName); } FText FNameSelectorGenerator::GetComboBoxToolTip() const { return FText::FromString(CachedCallbacks.GetTooltipText()); } TSharedRef FNameSelectorGenerator::MakeNameSelectorWidget(TArray& InNameArray, FNameSelectorCallbacks&& InCallbacks) { CachedNameArray.Reset(); for (FName& InName : InNameArray) { CachedNameArray.Add(TSharedPtr(new FName(InName))); } CachedCallbacks = MoveTemp(InCallbacks); FName CurrentlySelectedName = CachedCallbacks.GetCurrentlySelectedName(); TSharedPtr InitialSelectedName; for (TSharedPtr& NameSelection : CachedNameArray) { if (*NameSelection == CurrentlySelectedName) { InitialSelectedName = NameSelection; break; } } return SNew(SComboBox>) .OnGenerateWidget(this, &FNameSelectorGenerator::HandleResponseComboBoxGenerateWidget) .OptionsSource(&CachedNameArray) .OnSelectionChanged(this, &FNameSelectorGenerator::OnSelectionChanged) .InitiallySelectedItem(InitialSelectedName) .IsEnabled(FSlateApplication::Get().GetNormalExecutionAttribute()) .ContentPadding(FMargin(2.0f, 2.0f)) .Content() [ SNew(STextBlock) .Text(this, &FNameSelectorGenerator::GetComboBoxContent) .Font(IDetailLayoutBuilder::GetDetailFont()) .ToolTipText(this, &FNameSelectorGenerator::GetComboBoxToolTip) ]; } void FNameSelectorGenerator::OnSelectionChanged(TSharedPtr NameItem, ESelectInfo::Type SelectInfo) { check(NameItem.IsValid()); CachedCallbacks.OnNewNameSelected(*NameItem); } TSharedRef FNameSelectorGenerator::HandleResponseComboBoxGenerateWidget(TSharedPtr StringItem) { return SNew(STextBlock) .Text(FText::FromName(*StringItem)) .Font(IDetailLayoutBuilder::GetDetailFont()); } TSharedRef FSoundfieldSubmixDetailsCustomization::MakeInstance() { return MakeShareable(new FSoundfieldSubmixDetailsCustomization); } void FSoundfieldSubmixDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) { if (!SoundfieldFormatNameSelectorGenerator) { SoundfieldFormatNameSelectorGenerator = MakeShareable(new FNameSelectorGenerator()); } IDetailCategoryBuilder& SoundfieldCategory = DetailLayout.EditCategory(TEXT("Soundfield")); TSharedPtr EncodingFormatPropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(USoundfieldSubmix, SoundfieldEncodingFormat)); IDetailPropertyRow& EncodingFormatPropertyRow = SoundfieldCategory.AddProperty(EncodingFormatPropertyHandle); check(EncodingFormatPropertyHandle); TWeakPtr WeakEncodingFormatPtr = EncodingFormatPropertyHandle; // Set up callbacks for the name selector dropdown menu: FNameSelectorGenerator::FNameSelectorCallbacks Callbacks = { // void OnNameChanged(FName InName) [EncodingFormatPropertyHandle](FName SelectedName) { if (EncodingFormatPropertyHandle.IsValid() && EncodingFormatPropertyHandle->IsValidHandle()) { EncodingFormatPropertyHandle->SetValue(SelectedName); } }, // FName GetCurrentName() [EncodingFormatPropertyHandle]() { FName SelectedName; if (EncodingFormatPropertyHandle.IsValid() && EncodingFormatPropertyHandle->IsValidHandle()) { EncodingFormatPropertyHandle->GetValue(SelectedName); } return SelectedName; }, // FString GetTooltipText() []() { return FString(TEXT("Use this to select the channel or soundfield configuration of this submix.")); } }; TArray AvailableSoundfieldFormats = ISoundfieldFactory::GetAvailableSoundfieldFormats(); EncodingFormatPropertyRow.CustomWidget() .NameContent() [ EncodingFormatPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(1000.0f) .MinDesiredWidth(50.0f) [ SoundfieldFormatNameSelectorGenerator->MakeNameSelectorWidget(AvailableSoundfieldFormats, MoveTemp(Callbacks)) ]; } TSharedRef FEndpointSubmixDetailsCustomization::MakeInstance() { return MakeShareable(new FEndpointSubmixDetailsCustomization); } void FEndpointSubmixDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) { if (!EndpointTypeNameSelectorGenerator) { EndpointTypeNameSelectorGenerator = MakeShareable(new FNameSelectorGenerator()); } IDetailCategoryBuilder& EndpointCategory = DetailLayout.EditCategory(TEXT("Endpoint")); TSharedPtr EndpointTypePropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UEndpointSubmix, EndpointType)); IDetailPropertyRow& EndpointTypePropertyRow = EndpointCategory.AddProperty(EndpointTypePropertyHandle); TWeakPtr WeakEndpointFormatPtr = EndpointTypePropertyHandle; // Set up callbacks for the name selector dropdown menu: FNameSelectorGenerator::FNameSelectorCallbacks Callbacks = { // void OnNameChanged(FName InName) [EndpointTypePropertyHandle](FName SelectedName) { EndpointTypePropertyHandle->SetValue(SelectedName); }, // FName GetCurrentName() [EndpointTypePropertyHandle]() { FName SelectedName; EndpointTypePropertyHandle->GetValue(SelectedName); return SelectedName; }, // FString GetTooltipText() []() { return FString(TEXT("Use this to select which endpoint this submix sends to.")); } }; TArray AvailableEndpointTypes = IAudioEndpointFactory::GetAvailableEndpointTypes(); EndpointTypePropertyRow.CustomWidget() .NameContent() [ EndpointTypePropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(1000.0f) .MinDesiredWidth(50.0f) [ EndpointTypeNameSelectorGenerator->MakeNameSelectorWidget(AvailableEndpointTypes, MoveTemp(Callbacks)) ]; } TSharedRef FSoundfieldEndpointSubmixDetailsCustomization::MakeInstance() { return MakeShareable(new FSoundfieldEndpointSubmixDetailsCustomization); } void FSoundfieldEndpointSubmixDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) { if (!EndpointTypeNameSelectorGenerator) { EndpointTypeNameSelectorGenerator = MakeShareable(new FNameSelectorGenerator()); } IDetailCategoryBuilder& EndpointCategory = DetailLayout.EditCategory(TEXT("Endpoint")); TSharedPtr EndpointTypePropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(USoundfieldEndpointSubmix, SoundfieldEndpointType)); IDetailPropertyRow& EndpointTypePropertyRow = EndpointCategory.AddProperty(EndpointTypePropertyHandle); TWeakPtr WeakEndpointFormatPtr = EndpointTypePropertyHandle; // Set up callbacks for the name selector dropdown menu: FNameSelectorGenerator::FNameSelectorCallbacks Callbacks = { // void OnNameChanged(FName InName) [EndpointTypePropertyHandle](FName SelectedName) { EndpointTypePropertyHandle->SetValue(SelectedName); }, // FName GetCurrentName() [EndpointTypePropertyHandle]() { FName SelectedName; EndpointTypePropertyHandle->GetValue(SelectedName); return SelectedName; }, // FString GetTooltipText() []() { return FString(TEXT("Use this to select which endpoint this submix sends to.")); } }; TArray AvailableEndpointTypes = ISoundfieldEndpointFactory::GetAllSoundfieldEndpointTypes(); EndpointTypePropertyRow.CustomWidget() .NameContent() [ EndpointTypePropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(1000.0f) .MinDesiredWidth(50.0f) [ EndpointTypeNameSelectorGenerator->MakeNameSelectorWidget(AvailableEndpointTypes, MoveTemp(Callbacks)) ]; } #undef LOCTEXT_NAMESPACE