Files
UnrealEngineUWP/Engine/Source/Editor/DetailCustomizations/Private/StringClassReferenceCustomization.cpp
Jaroslaw Palczynski 3fd16f9649 FStringClassReference's customization was accessing internal property of FStringAssetReference and was setting it without checking if path is "None". FStringClassReference is inheriting FStringAssetReference::ImportTextItem, which is checking for that special case. This method is used when customization treats the property as a whole (without accessing internal property). Fixed UE-4538.
Also fixed assert+crash when user tried to use FStringClassReference, without specifying "MetaClass" in UPROPERTY macro. UHT allowed it, but the editor was crashing. Now when it's missing it is assumed it is UClass.

#codereview Robert.Manuszewski

[CL 2385157 by Jaroslaw Palczynski in Main branch]
2014-12-11 02:58:57 -05:00

68 lines
2.5 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "DetailCustomizationsPrivatePCH.h"
#include "StringClassReferenceCustomization.h"
#include "EditorClassUtils.h"
void FStringClassReferenceCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> InPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
PropertyHandle = InPropertyHandle;
const FString& MetaClassName = PropertyHandle->GetMetaData("MetaClass");
const FString& RequiredInterfaceName = PropertyHandle->GetMetaData("RequiredInterface");
const bool bAllowAbstract = PropertyHandle->GetBoolMetaData("AllowAbstract");
const bool bIsBlueprintBaseOnly = PropertyHandle->GetBoolMetaData("IsBlueprintBaseOnly");
const bool bAllowNone = !(PropertyHandle->GetMetaDataProperty()->PropertyFlags & CPF_NoClear);
const UClass* const MetaClass = !MetaClassName.IsEmpty()
? FEditorClassUtils::GetClassFromString(MetaClassName)
: UClass::StaticClass();
const UClass* const RequiredInterface = FEditorClassUtils::GetClassFromString(RequiredInterfaceName);
HeaderRow
.NameContent()
[
InPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.MinDesiredWidth(250.0f)
.MaxDesiredWidth(0.0f)
[
// Add a class entry box. Even though this isn't an class entry, we will simulate one
SNew(SClassPropertyEntryBox)
.MetaClass(MetaClass)
.RequiredInterface(RequiredInterface)
.AllowAbstract(bAllowAbstract)
.IsBlueprintBaseOnly(bIsBlueprintBaseOnly)
.AllowNone(bAllowNone)
.SelectedClass(this, &FStringClassReferenceCustomization::OnGetClass)
.OnSetClass(this, &FStringClassReferenceCustomization::OnSetClass)
];
}
void FStringClassReferenceCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
}
const UClass* FStringClassReferenceCustomization::OnGetClass() const
{
FString ClassName;
PropertyHandle->GetValueAsFormattedString(ClassName);
// Do we have a valid cached class pointer?
const UClass* Class = CachedClassPtr.Get();
if(!Class || Class->GetPathName() != ClassName)
{
Class = FEditorClassUtils::GetClassFromString(ClassName);
CachedClassPtr = Class;
}
return Class;
}
void FStringClassReferenceCustomization::OnSetClass(const UClass* NewClass)
{
if (PropertyHandle->SetValueFromFormattedString((NewClass) ? NewClass->GetPathName() : "None") == FPropertyAccess::Result::Success)
{
CachedClassPtr = NewClass;
}
}