You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
[REVIEW] [at]Vincent.Gauthier [at]ui-tech-design #rb [at]Patrick.Boutot [at]Vincent.Gauthier [at]Adrienne.Pugh #rnx #tests: Ran a preflight build #preflight 627bf7ab1e749933439c5760 #ROBOMERGE-AUTHOR: simon.girard #ROBOMERGE-SOURCE: CL 20440008 via CL 20440035 via CL 20440039 #ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v949-20362246) [CL 20448769 by simon girard in ue5-main branch]
303 lines
10 KiB
C++
303 lines
10 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Customizations/SlateFontInfoCustomization.h"
|
|
#include "Engine/Font.h"
|
|
#include "PropertyHandle.h"
|
|
#include "IDetailChildrenBuilder.h"
|
|
#include "AssetRegistry/AssetData.h"
|
|
#include "PropertyCustomizationHelpers.h"
|
|
#include "DetailLayoutBuilder.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "SlateFontInfo"
|
|
|
|
TSharedRef<IPropertyTypeCustomization> FSlateFontInfoStructCustomization::MakeInstance()
|
|
{
|
|
return MakeShareable(new FSlateFontInfoStructCustomization());
|
|
}
|
|
|
|
void FSlateFontInfoStructCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& InHeaderRow, IPropertyTypeCustomizationUtils& InStructCustomizationUtils)
|
|
{
|
|
StructPropertyHandle = InStructPropertyHandle;
|
|
|
|
static const FName FontObjectPropertyName = GET_MEMBER_NAME_CHECKED(FSlateFontInfo, FontObject);
|
|
static const FName TypefaceFontNamePropertyName = GET_MEMBER_NAME_CHECKED(FSlateFontInfo, TypefaceFontName);
|
|
static const FName SizePropertyName = GET_MEMBER_NAME_CHECKED(FSlateFontInfo, Size);
|
|
|
|
FontObjectProperty = StructPropertyHandle->GetChildHandle(FontObjectPropertyName);
|
|
check(FontObjectProperty.IsValid());
|
|
|
|
TypefaceFontNameProperty = StructPropertyHandle->GetChildHandle(TypefaceFontNamePropertyName);
|
|
check(TypefaceFontNameProperty.IsValid());
|
|
|
|
FontSizeProperty = StructPropertyHandle->GetChildHandle(SizePropertyName);
|
|
check(FontSizeProperty.IsValid());
|
|
|
|
InHeaderRow
|
|
.NameContent()
|
|
[
|
|
InStructPropertyHandle->CreatePropertyNameWidget()
|
|
]
|
|
.ValueContent()
|
|
.MinDesiredWidth(0)
|
|
.MaxDesiredWidth(0)
|
|
[
|
|
InStructPropertyHandle->CreatePropertyValueWidget()
|
|
];
|
|
}
|
|
|
|
void FSlateFontInfoStructCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& InStructBuilder, IPropertyTypeCustomizationUtils& InStructCustomizationUtils)
|
|
{
|
|
IDetailPropertyRow& FontObjectRow = InStructBuilder.AddProperty(FontObjectProperty.ToSharedRef());
|
|
|
|
FontObjectRow.CustomWidget()
|
|
.NameContent()
|
|
[
|
|
FontObjectProperty->CreatePropertyNameWidget()
|
|
]
|
|
.ValueContent()
|
|
.MinDesiredWidth(200.f)
|
|
.MaxDesiredWidth(300.f)
|
|
[
|
|
SNew(SObjectPropertyEntryBox)
|
|
.PropertyHandle(FontObjectProperty)
|
|
.AllowedClass(UFont::StaticClass())
|
|
.OnShouldFilterAsset(FOnShouldFilterAsset::CreateStatic(&FSlateFontInfoStructCustomization::OnFilterFontAsset))
|
|
.OnObjectChanged(this, &FSlateFontInfoStructCustomization::OnFontChanged)
|
|
.DisplayUseSelected(true)
|
|
.DisplayBrowse(true)
|
|
];
|
|
|
|
IDetailPropertyRow& TypefaceRow = InStructBuilder.AddProperty(TypefaceFontNameProperty.ToSharedRef());
|
|
|
|
TypefaceRow.CustomWidget()
|
|
.NameContent()
|
|
[
|
|
TypefaceFontNameProperty->CreatePropertyNameWidget()
|
|
]
|
|
.ValueContent()
|
|
[
|
|
SAssignNew(FontEntryCombo, SComboBox<TSharedPtr<FName>>)
|
|
.OptionsSource(&FontEntryComboData)
|
|
.IsEnabled(this, &FSlateFontInfoStructCustomization::IsFontEntryComboEnabled)
|
|
.OnComboBoxOpening(this, &FSlateFontInfoStructCustomization::OnFontEntryComboOpening)
|
|
.OnSelectionChanged(this, &FSlateFontInfoStructCustomization::OnFontEntrySelectionChanged)
|
|
.OnGenerateWidget(this, &FSlateFontInfoStructCustomization::MakeFontEntryWidget)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(this, &FSlateFontInfoStructCustomization::GetFontEntryComboText)
|
|
.Font(IDetailLayoutBuilder::GetDetailFont())
|
|
]
|
|
];
|
|
|
|
InStructBuilder.AddProperty(FontSizeProperty.ToSharedRef());
|
|
|
|
InStructBuilder.AddProperty(InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FSlateFontInfo, LetterSpacing)).ToSharedRef());
|
|
|
|
InStructBuilder.AddProperty(InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FSlateFontInfo, SkewAmount)).ToSharedRef());
|
|
|
|
InStructBuilder.AddProperty(InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FSlateFontInfo, FontMaterial)).ToSharedRef());
|
|
|
|
InStructBuilder.AddProperty(InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FSlateFontInfo, OutlineSettings)).ToSharedRef());
|
|
}
|
|
|
|
bool FSlateFontInfoStructCustomization::OnFilterFontAsset(const FAssetData& InAssetData)
|
|
{
|
|
// We want to filter font assets that aren't valid to use with Slate/UMG
|
|
return Cast<const UFont>(InAssetData.GetAsset())->FontCacheType != EFontCacheType::Runtime;
|
|
}
|
|
|
|
void FSlateFontInfoStructCustomization::OnFontChanged(const FAssetData& InAssetData)
|
|
{
|
|
const UFont* const FontAsset = Cast<const UFont>(InAssetData.GetAsset());
|
|
const FName FirstFontName = (FontAsset && FontAsset->CompositeFont.DefaultTypeface.Fonts.Num()) ? FontAsset->CompositeFont.DefaultTypeface.Fonts[0].Name : NAME_None;
|
|
|
|
TArray<FSlateFontInfo*> SlateFontInfoStructs = GetFontInfoBeingEdited();
|
|
for(FSlateFontInfo* FontInfo : SlateFontInfoStructs)
|
|
{
|
|
// The font has been updated in the editor, so clear the non-UObject pointer so that the two don't conflict
|
|
FontInfo->CompositeFont.Reset();
|
|
|
|
// We've changed (or cleared) the font asset, so make sure and update the typeface entry name being used by the font info
|
|
TypefaceFontNameProperty->SetValue(FirstFontName);
|
|
}
|
|
|
|
if(!FontAsset)
|
|
{
|
|
const FString PropertyPath = FontObjectProperty->GeneratePathToProperty();
|
|
TArray<UObject*> PropertyOuterObjects;
|
|
FontObjectProperty->GetOuterObjects(PropertyOuterObjects);
|
|
for(const UObject* OuterObject : PropertyOuterObjects)
|
|
{
|
|
UE_LOG(LogSlate, Warning, TEXT("FSlateFontInfo property '%s' on object '%s' was set to use a null UFont. Slate will be forced to use the fallback font path which may be slower."), *PropertyPath, *OuterObject->GetPathName());
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FSlateFontInfoStructCustomization::IsFontEntryComboEnabled() const
|
|
{
|
|
TArray<const FSlateFontInfo*> SlateFontInfoStructs = GetFontInfoBeingEdited();
|
|
if(SlateFontInfoStructs.Num() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const FSlateFontInfo* const FirstSlateFontInfo = SlateFontInfoStructs[0];
|
|
const UFont* const FontObject = Cast<const UFont>(FirstSlateFontInfo->FontObject);
|
|
if(!FontObject)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Only let people pick an entry if every struct being edited is using the same font object
|
|
for(int32 FontInfoIndex = 1; FontInfoIndex < SlateFontInfoStructs.Num(); ++FontInfoIndex)
|
|
{
|
|
const FSlateFontInfo* const OtherSlateFontInfo = SlateFontInfoStructs[FontInfoIndex];
|
|
const UFont* const OtherFontObject = Cast<const UFont>(OtherSlateFontInfo->FontObject);
|
|
if(FontObject != OtherFontObject)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void FSlateFontInfoStructCustomization::OnFontEntryComboOpening()
|
|
{
|
|
TArray<FSlateFontInfo*> SlateFontInfoStructs = GetFontInfoBeingEdited();
|
|
|
|
FontEntryComboData.Empty();
|
|
|
|
if(SlateFontInfoStructs.Num() > 0)
|
|
{
|
|
const FSlateFontInfo* const FirstSlateFontInfo = SlateFontInfoStructs[0];
|
|
const UFont* const FontObject = Cast<const UFont>(FirstSlateFontInfo->FontObject);
|
|
check(FontObject);
|
|
|
|
const FName ActiveFontEntry = GetActiveFontEntry();
|
|
TSharedPtr<FName> SelectedNamePtr;
|
|
|
|
for(const FTypefaceEntry& TypefaceEntry : FontObject->CompositeFont.DefaultTypeface.Fonts)
|
|
{
|
|
TSharedPtr<FName> NameEntryPtr = MakeShareable(new FName(TypefaceEntry.Name));
|
|
FontEntryComboData.Add(NameEntryPtr);
|
|
|
|
if(!TypefaceEntry.Name.IsNone() && TypefaceEntry.Name == ActiveFontEntry)
|
|
{
|
|
SelectedNamePtr = NameEntryPtr;
|
|
}
|
|
}
|
|
|
|
FontEntryComboData.Sort([](const TSharedPtr<FName>& One, const TSharedPtr<FName>& Two) -> bool
|
|
{
|
|
return One->ToString() < Two->ToString();
|
|
});
|
|
|
|
FontEntryCombo->ClearSelection();
|
|
FontEntryCombo->RefreshOptions();
|
|
FontEntryCombo->SetSelectedItem(SelectedNamePtr);
|
|
}
|
|
else
|
|
{
|
|
FontEntryCombo->ClearSelection();
|
|
FontEntryCombo->RefreshOptions();
|
|
}
|
|
}
|
|
|
|
void FSlateFontInfoStructCustomization::OnFontEntrySelectionChanged(TSharedPtr<FName> InNewSelection, ESelectInfo::Type)
|
|
{
|
|
if(InNewSelection.IsValid())
|
|
{
|
|
TArray<FSlateFontInfo*> SlateFontInfoStructs = GetFontInfoBeingEdited();
|
|
if(SlateFontInfoStructs.Num() > 0)
|
|
{
|
|
const FSlateFontInfo* const FirstSlateFontInfo = SlateFontInfoStructs[0];
|
|
if(FirstSlateFontInfo->TypefaceFontName != *InNewSelection)
|
|
{
|
|
TypefaceFontNameProperty->SetValue(*InNewSelection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TSharedRef<SWidget> FSlateFontInfoStructCustomization::MakeFontEntryWidget(TSharedPtr<FName> InFontEntry)
|
|
{
|
|
return
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(*InFontEntry))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")));
|
|
}
|
|
|
|
FText FSlateFontInfoStructCustomization::GetFontEntryComboText() const
|
|
{
|
|
return FText::FromName(GetActiveFontEntry());
|
|
}
|
|
|
|
FName FSlateFontInfoStructCustomization::GetActiveFontEntry() const
|
|
{
|
|
TArray<const FSlateFontInfo*> SlateFontInfoStructs = GetFontInfoBeingEdited();
|
|
if(SlateFontInfoStructs.Num() > 0)
|
|
{
|
|
const FSlateFontInfo* const FirstSlateFontInfo = SlateFontInfoStructs[0];
|
|
const UFont* const FontObject = Cast<const UFont>(FirstSlateFontInfo->FontObject);
|
|
if(FontObject)
|
|
{
|
|
return (FirstSlateFontInfo->TypefaceFontName.IsNone() && FontObject->CompositeFont.DefaultTypeface.Fonts.Num())
|
|
? FontObject->CompositeFont.DefaultTypeface.Fonts[0].Name
|
|
: FirstSlateFontInfo->TypefaceFontName;
|
|
}
|
|
}
|
|
|
|
return NAME_None;
|
|
}
|
|
|
|
TArray<FSlateFontInfo*> FSlateFontInfoStructCustomization::GetFontInfoBeingEdited()
|
|
{
|
|
TArray<FSlateFontInfo*> SlateFontInfoStructs;
|
|
|
|
if(StructPropertyHandle->IsValidHandle())
|
|
{
|
|
TArray<void*> StructPtrs;
|
|
StructPropertyHandle->AccessRawData(StructPtrs);
|
|
SlateFontInfoStructs.Reserve(StructPtrs.Num());
|
|
|
|
for(auto It = StructPtrs.CreateConstIterator(); It; ++It)
|
|
{
|
|
void* RawPtr = *It;
|
|
if(RawPtr)
|
|
{
|
|
FSlateFontInfo* const SlateFontInfo = reinterpret_cast<FSlateFontInfo*>(RawPtr);
|
|
SlateFontInfoStructs.Add(SlateFontInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
return SlateFontInfoStructs;
|
|
}
|
|
|
|
TArray<const FSlateFontInfo*> FSlateFontInfoStructCustomization::GetFontInfoBeingEdited() const
|
|
{
|
|
TArray<const FSlateFontInfo*> SlateFontInfoStructs;
|
|
|
|
if(StructPropertyHandle->IsValidHandle())
|
|
{
|
|
TArray<const void*> StructPtrs;
|
|
StructPropertyHandle->AccessRawData(StructPtrs);
|
|
SlateFontInfoStructs.Reserve(StructPtrs.Num());
|
|
|
|
for(auto It = StructPtrs.CreateConstIterator(); It; ++It)
|
|
{
|
|
const void* RawPtr = *It;
|
|
if(RawPtr)
|
|
{
|
|
const FSlateFontInfo* const SlateFontInfo = reinterpret_cast<const FSlateFontInfo*>(RawPtr);
|
|
SlateFontInfoStructs.Add(SlateFontInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
return SlateFontInfoStructs;
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|