Files
UnrealEngineUWP/Engine/Source/Editor/DetailCustomizations/Private/StringClassReferenceCustomization.cpp
Jamie Dale 3ea331525b UAT now uses the game INI files to add additional directories to cook and stage.
TTP# 335070 - Add GUI based way to specify additional non-asset files or paths to package

CookCommandlet now uses the project settings to work out which additional directories it should cook (this removes the need for the editor to pass this information to that UAT via the command line). I've left the COOKDIR option in the UAT/CookCommandlet as, while non of our projects seem to be using it, I'm not comfortable removing it in case any scripts are using it.

CopyBuildToStagingDirectory also uses these project settings to work out which additional directories it should stage when producing the staging manifest (these are split into UFS and non-UFS directories). This allows users to define additional directories in the editor (or directly in the settings file) which will always be staged regardless of how UAT is invoked.

All of these paths are specified in the settings file as relative to the project Content directory, and the editor will enforce this fact when using the directory picker.

Also mirrored the meta-data interface from UField on IPropertyHandle. This takes care of accessing the meta-data from the correct property, even when you're accessing an element inside an array (MattK approved!).

ReviewedBy Thomas.Sarkanen, Robert.Manuszewski, Max.Preussner

[CL 2088172 by Jamie Dale in Main branch]
2014-05-29 17:38:00 -04:00

85 lines
2.8 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "DetailCustomizationsPrivatePCH.h"
#include "StringClassReferenceCustomization.h"
void FStringClassReferenceCustomization::CustomizeStructHeader(TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IStructCustomizationUtils& StructCustomizationUtils)
{
StructPropertyHandle = InStructPropertyHandle;
ClassNamePropertyHandle = InStructPropertyHandle->GetChildHandle("ClassName");
check(ClassNamePropertyHandle.IsValid());
const FString& MetaClassName = StructPropertyHandle->GetMetaData("MetaClass");
const FString& RequiredInterfaceName = StructPropertyHandle->GetMetaData("RequiredInterface");
const bool bAllowAbstract = StructPropertyHandle->GetBoolMetaData("AllowAbstract");
const bool bIsBlueprintBaseOnly = StructPropertyHandle->GetBoolMetaData("IsBlueprintBaseOnly");
const bool bAllowNone = !(StructPropertyHandle->GetMetaDataProperty()->PropertyFlags & CPF_NoClear);
check(!MetaClassName.IsEmpty());
const UClass* const MetaClass = StringToClass(MetaClassName);
const UClass* const RequiredInterface = StringToClass(RequiredInterfaceName);
HeaderRow
.NameContent()
[
InStructPropertyHandle->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::CustomizeStructChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IStructCustomizationUtils& StructCustomizationUtils)
{
}
const UClass* FStringClassReferenceCustomization::OnGetClass() const
{
FString ClassName;
ClassNamePropertyHandle->GetValue(ClassName);
// Do we have a valid cached class pointer?
const UClass* Class = CachedClassPtr.Get();
if(!Class || Class->GetPathName() != ClassName)
{
Class = StringToClass(ClassName);
CachedClassPtr = Class;
}
return Class;
}
void FStringClassReferenceCustomization::OnSetClass(const UClass* NewClass)
{
if(ClassNamePropertyHandle->SetValueFromFormattedString((NewClass) ? NewClass->GetPathName() : "None") == FPropertyAccess::Result::Success)
{
CachedClassPtr = NewClass;
}
}
const UClass* FStringClassReferenceCustomization::StringToClass(const FString& ClassName)
{
if(ClassName.IsEmpty() || ClassName == "None")
{
return nullptr;
}
const UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName);
if(!Class)
{
Class = LoadObject<UClass>(nullptr, *ClassName);
}
return Class;
}