Files
UnrealEngine/Engine/Source/Editor/InternationalizationSettings/Private/UserGeneratedContentLocalizationDescriptorDetails.cpp
2025-05-18 13:04:45 +08:00

220 lines
8.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UserGeneratedContentLocalizationDescriptorDetails.h"
#include "UserGeneratedContentLocalization.h"
#include "PropertyHandle.h"
#include "DetailWidgetRow.h"
#include "IDetailChildrenBuilder.h"
#include "SCulturePicker.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SComboButton.h"
#include "Widgets/Views/SMultipleOptionTable.h"
#include "Internationalization/Culture.h"
#include "Internationalization/Internationalization.h"
#define LOCTEXT_NAMESPACE "UserGeneratedContentLocalizationDescriptorDetails"
void FUserGeneratedContentLocalizationDescriptorDetails::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
if (StructPropertyHandle->HasMetaData("ShowOnlyInnerProperties"))
{
return;
}
HeaderRow
.NameContent()
[
StructPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
[
StructPropertyHandle->CreatePropertyValueWidget()
];
}
void FUserGeneratedContentLocalizationDescriptorDetails::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
// Build the list of available cultures used by the child customizations
{
FUserGeneratedContentLocalizationDescriptor DefaultUGCLocDescriptor;
DefaultUGCLocDescriptor.InitializeFromProject();
const TArray<FCultureRef> LocalizedCultureList = FInternationalization::Get().GetAvailableCultures(DefaultUGCLocDescriptor.CulturesToGenerate, false);
AvailableCultures.Reset(LocalizedCultureList.Num());
Algo::Transform(LocalizedCultureList, AvailableCultures, [](const FCultureRef Culture) -> FCulturePtr { return Culture; });
// Sort by the current display name so that the order in the "native language" picker and the "cultures to generate" list matches
AvailableCultures.StableSort([](FCulturePtr One, FCulturePtr Two)
{
return FTextComparison::CompareTo(One->GetDisplayName(), Two->GetDisplayName()) < 0;
});
}
uint32 NumChildren = 0;
StructPropertyHandle->GetNumChildren(NumChildren);
for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
{
if (TSharedPtr<IPropertyHandle> ChildPropertyHandle = StructPropertyHandle->GetChildHandle(ChildIndex))
{
const FName ChildPropertyName = ChildPropertyHandle->GetProperty()->GetFName();
if (ChildPropertyName == GET_MEMBER_NAME_CHECKED(FUserGeneratedContentLocalizationDescriptor, NativeCulture))
{
CustomizeNativeCulture(ChildPropertyHandle.ToSharedRef(), StructBuilder, StructCustomizationUtils);
}
else if(ChildPropertyName == GET_MEMBER_NAME_CHECKED(FUserGeneratedContentLocalizationDescriptor, CulturesToGenerate))
{
CustomizeCulturesToGenerate(ChildPropertyHandle.ToSharedRef(), StructBuilder, StructCustomizationUtils);
}
else
{
StructBuilder.AddProperty(ChildPropertyHandle.ToSharedRef());
}
}
}
}
void FUserGeneratedContentLocalizationDescriptorDetails::CustomizeNativeCulture(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
NativeCultureHandle = PropertyHandle;
StructBuilder.AddCustomRow(PropertyHandle->GetPropertyDisplayName())
.RowTag(PropertyHandle->GetProperty()->GetFName())
.PropertyHandleList({ PropertyHandle })
.NameContent()
[
PropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
[
SNew(SCulturePickerCombo)
.Font(IPropertyTypeCustomizationUtils::GetRegularFont())
.SelectedCulture(this, &FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_GetCulture)
.OnSelectionChanged(this, &FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_OnSelectionChanged)
.IsCulturePickable(this, &FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_IsCulturePickable)
.DisplayNameFormat(SCulturePicker::ECultureDisplayFormat::ActiveCultureDisplayName)
.ViewMode(SCulturePicker::ECulturesViewMode::Flat)
];
}
FCulturePtr FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_GetCulture() const
{
FString NativeCultureName;
NativeCultureHandle->GetValue(NativeCultureName);
return NativeCultureName.IsEmpty()
? nullptr
: FInternationalization::Get().GetCulture(NativeCultureName);
}
bool FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_IsCulturePickable(FCulturePtr Culture) const
{
return AvailableCultures.Contains(Culture);
}
void FUserGeneratedContentLocalizationDescriptorDetails::NativeCulture_OnSelectionChanged(FCulturePtr SelectedCulture, ESelectInfo::Type SelectInfo)
{
NativeCultureHandle->SetValue(SelectedCulture->GetName());
}
void FUserGeneratedContentLocalizationDescriptorDetails::CustomizeCulturesToGenerate(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
CulturesToGenerateHandle = PropertyHandle;
StructBuilder.AddCustomRow(PropertyHandle->GetPropertyDisplayName())
.RowTag(PropertyHandle->GetProperty()->GetFName())
.PropertyHandleList({ PropertyHandle })
.NameContent()
[
PropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SMultipleOptionTable<FCulturePtr>, &AvailableCultures)
.ListHeight(100.0f)
.OnGenerateOptionWidget_Lambda([](FCulturePtr Culture) -> TSharedRef<SWidget>
{
return SNew(STextBlock)
.Font(IPropertyTypeCustomizationUtils::GetRegularFont())
.Text(FText::AsCultureInvariant(Culture->GetDisplayName()))
.ToolTipText(FText::AsCultureInvariant(Culture->GetName()));
})
.OnPreBatchSelect(this, &FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnPreBatchSelect)
.OnPostBatchSelect(this, &FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnPostBatchSelect)
.OnOptionSelectionChanged(this, &FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnCultureSelectionChanged)
.IsOptionSelected(this, &FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_IsCultureSelected)
];
}
void FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnPreBatchSelect()
{
CulturesToGenerate_IsInBatchSelectOperation = true;
CulturesToGenerateHandle->NotifyPreChange();
}
void FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnPostBatchSelect()
{
CulturesToGenerateHandle->NotifyPostChange(EPropertyChangeType::ValueSet);
CulturesToGenerateHandle->NotifyFinishedChangingProperties();
CulturesToGenerate_IsInBatchSelectOperation = false;
}
void FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_OnCultureSelectionChanged(bool IsSelected, FCulturePtr Culture)
{
if (!CulturesToGenerate_IsInBatchSelectOperation)
{
CulturesToGenerateHandle->NotifyPreChange();
}
CulturesToGenerateHandle->EnumerateRawData([IsSelected, &Culture](void* RawData, const int32 /*DataIndex*/, const int32 /*NumDatas*/)
{
TArray<FString>* RawCulturesToGenerateArray = reinterpret_cast<TArray<FString>*>(RawData);
if (IsSelected)
{
RawCulturesToGenerateArray->AddUnique(Culture->GetName());
}
else
{
RawCulturesToGenerateArray->Remove(Culture->GetName());
}
return true;
});
if (!CulturesToGenerate_IsInBatchSelectOperation)
{
CulturesToGenerateHandle->NotifyPostChange(IsSelected ? EPropertyChangeType::ArrayAdd : EPropertyChangeType::ArrayRemove);
CulturesToGenerateHandle->NotifyFinishedChangingProperties();
}
}
bool FUserGeneratedContentLocalizationDescriptorDetails::CulturesToGenerate_IsCultureSelected(FCulturePtr Culture) const
{
FString CultureName = Culture->GetName();
TSharedPtr<IPropertyHandleArray> CulturesToGenerateArray = CulturesToGenerateHandle->AsArray();
checkf(CulturesToGenerateArray, TEXT("CulturesToGenerate was not an array!"));
uint32 ElementCount = 0;
CulturesToGenerateArray->GetNumElements(ElementCount);
for (uint32 Index = 0; Index < ElementCount; ++Index)
{
const TSharedRef<IPropertyHandle> ElementPropertyHandle = CulturesToGenerateArray->GetElement(Index);
FString CultureNameAtIndex;
ElementPropertyHandle->GetValue(CultureNameAtIndex);
if (CultureNameAtIndex == CultureName)
{
return true;
}
}
return false;
}
#undef LOCTEXT_NAMESPACE