Files
UnrealEngineUWP/Engine/Source/Editor/DetailCustomizations/Private/StringAssetReferenceCustomization.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

93 lines
3.1 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "DetailCustomizationsPrivatePCH.h"
#include "StringAssetReferenceCustomization.h"
#include "AssetData.h"
void FStringAssetReferenceCustomization::CustomizeStructHeader( TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IStructCustomizationUtils& StructCustomizationUtils )
{
StructPropertyHandle = InStructPropertyHandle;
FString ClassFilterString = StructPropertyHandle->GetMetaData("AllowedClasses");
if( !ClassFilterString.IsEmpty() )
{
TArray<FString> CustomClassFilterNames;
ClassFilterString.ParseIntoArray(&CustomClassFilterNames, TEXT(","), true);
for(auto It = CustomClassFilterNames.CreateConstIterator(); It; ++It)
{
const FString& ClassName = *It;
UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName);
if(!Class)
{
Class = LoadObject<UClass>(nullptr, *ClassName);
}
if(Class)
{
CustomClassFilters.Add(Class);
}
}
}
bExactClass = StructPropertyHandle->GetBoolMetaData("ExactClass");
FOnShouldFilterAsset AssetFilter;
UClass* ClassFilter = UObject::StaticClass();
if(CustomClassFilters.Num() == 1 && !bExactClass)
{
// If we only have one class to filter on, set it as the class type filter rather than use a filter callback
// We can only do this if we don't need an exact match, as the class filter also allows derived types
// The class filter is much faster than the callback as we're not performing two different sets of type tests
// (one against UObject, one against the actual type)
ClassFilter = CustomClassFilters[0];
}
else if(CustomClassFilters.Num() > 0)
{
// Only bind the filter if we have classes that need filtering
AssetFilter.BindSP(this, &FStringAssetReferenceCustomization::OnShouldFilterAsset);
}
// Can the field be cleared
const bool bAllowClear = !(StructPropertyHandle->GetMetaDataProperty()->PropertyFlags & CPF_NoClear);
HeaderRow
.NameContent()
[
InStructPropertyHandle->CreatePropertyNameWidget()
]
.ValueContent()
.MinDesiredWidth(250.0f)
.MaxDesiredWidth(0.0f)
[
// Add an object entry box. Even though this isn't an object entry, we will simulate one
SNew( SObjectPropertyEntryBox )
.PropertyHandle( InStructPropertyHandle )
.ThumbnailPool( StructCustomizationUtils.GetThumbnailPool() )
.AllowedClass( ClassFilter )
.OnShouldFilterAsset( AssetFilter )
.AllowClear( bAllowClear )
];
}
void FStringAssetReferenceCustomization::CustomizeStructChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IStructCustomizationUtils& StructCustomizationUtils)
{
}
bool FStringAssetReferenceCustomization::OnShouldFilterAsset( const FAssetData& InAssetData ) const
{
// Only bound if we have classes to filter on, so we don't need to test for an empty array here
UClass* const AssetClass = InAssetData.GetClass();
for(auto It = CustomClassFilters.CreateConstIterator(); It; ++It)
{
UClass* const FilterClass = *It;
const bool bMatchesFilter = (bExactClass) ? AssetClass == FilterClass : AssetClass->IsChildOf(FilterClass);
if(bMatchesFilter)
{
return false;
}
}
return true;
}