-
-
Save ekinertac/c4ce1cf430f61cd9eb941cb7cfbb2748 to your computer and use it in GitHub Desktop.
Automatically adding category sections to editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// add this code to your StartupModule() function of your EDITOR module | |
// if it doesnt work, try setting loading phase to "postdefault" -- no idea if this will produce side effects though. | |
// basically idea is looping all CDOs (i.e. UClasses) and their properties, getting their "category" meta value and registering them to | |
// property sections | |
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor"); | |
static constexpr bool bAddSubcategories = false; // you probably want this to be false | |
auto ProcessCategory = [&PropertyModule](const FName ClassName, const FString& Category) | |
{ | |
const TSharedRef<FPropertySection> Section = PropertyModule.FindOrCreateSection(ClassName, *Category, FText::FromString(Category)); | |
if (!Section->HasAddedCategory(*Category)) | |
{ | |
Section->AddCategory(*Category); | |
} | |
}; | |
auto IsValidCategory = [](const FString& Category) | |
{ | |
return !Category.IsEmpty() && Category != TEXT("None"); | |
}; | |
auto IsPropertyAllowed = [](const FProperty* Property) | |
{ | |
return Property->HasAnyPropertyFlags(CPF_BlueprintVisible | CPF_Edit); | |
}; | |
for (TObjectIterator<UClass> ClassIterator; ClassIterator; ++ClassIterator) | |
{ | |
const UClass* Class = *ClassIterator; | |
if (Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated | CLASS_NewerVersionExists)) | |
{ | |
continue; | |
} | |
for (const FProperty* Property = Class->PropertyLink; Property != nullptr; Property = Property->PropertyLinkNext) | |
{ | |
if (IsPropertyAllowed(Property)) | |
{ | |
// prepare values | |
const FName ClassName = Property->GetOwnerUObject()->GetFName(); | |
const FString CategoryString = Property->GetMetaData("Category"); | |
if (!IsValidCategory(CategoryString)) // skip empty categories | |
{ | |
continue; | |
} | |
// if we have sub categories, parse it into array and add them individually | |
TArray<FString> Subcategories; | |
if (CategoryString.ParseIntoArray(Subcategories, TEXT("|")) > 0) | |
{ | |
if (bAddSubcategories) | |
{ | |
for (const FString& Subcategory : Subcategories) | |
{ | |
if (IsValidCategory(Subcategory)) | |
{ | |
ProcessCategory(ClassName, Subcategory); | |
} | |
} | |
} | |
else | |
{ | |
FString Subcategory = Subcategories[0]; // just use first subcategory | |
if (IsValidCategory(Subcategory)) | |
{ | |
ProcessCategory(ClassName, Subcategory); | |
} | |
} | |
} | |
else // otherwise just process single category | |
{ | |
ProcessCategory(ClassName, CategoryString); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment