๐งโโ๏ธ Library Wizard
Short Description
The Library Wizard is a dynamic asset browsing and creation interface that lets users explore categorized templates and generate new assets via the Gorgeous Setup Wizard. It pairs searchable, filterable library views with template-driven creation workflows.
Long Description
The Library Wizard organizes editor-facing templates and assets into named categories and exposes them in a tiled browser. Participants (plugin modules) register categories and templates; tiles can open a multi-page Setup Wizard driven by UGorgeousSystemTemplate_DA + UGorgeousSetupWizardPayload classes. The system supports advanced filtering, custom icons, and per-category actions to streamline common creation tasks.
Quick start (for plugin authors)
- Create a
UGorgeousSystemTemplate_DAsubclass describing the template (title, icon, asset class to create, and payload page classes). - Provide one or more
UGorgeousSetupWizardPayloadsubclasses to render wizard pages and validate input. - Implement an
IGorgeousLibraryParticipantin your module and return category descriptors viaGetLibraryCategories(). - Ensure your module exposes a
LibraryParticipantpointer (set on startup) soSGorgeousLibraryViewdiscovers it. - Test in-editor: open the Library, select a template tile, fill pages, and finish to create the target asset.
How the wizard flow works
- User clicks a template tile (tile detected via Asset Registry query using
AssetClassPath). - If
bOpensSetupWizardis true the Library opensSGorgeousSetupWizard. - The wizard instantiates each configured
ConfigurationPayloadClassesas page objects and renders them viaIDetailsView. - On Finish: the wizard creates an instance of
AssetClassToCreate(aUPrimaryDataAssetsubclass), saves it, and callsExecuteTemplateGeneration()on the generated asset with the payload objects.
Creating a template (example)
UCLASS()
class UGorgeousInventoryTemplate_DA : public UGorgeousSystemTemplate_DA
{
GENERATED_BODY()
public:
UGorgeousInventoryTemplate_DA()
{
TemplateTitle = NSLOCTEXT("GorgeousInventory", "Template_Title", "Inventory Setup");
TemplateDescription = NSLOCTEXT("GorgeousInventory", "Template_Desc", "Create a basic inventory configuration.");
// TemplateIcon: assign a UTexture2D in the editor
AssetClassToCreate = UGorgeousInventoryConfig_DA::StaticClass(); // example asset class
ConfigurationPayloadClasses = { UGorgeousInventoryPayload::StaticClass() };
}
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-type">bool</span> <span class="hljs-title">ExecuteTemplateGeneration_Implementation</span><span class="hljs-params">(UObject* GeneratedAsset, <span class="hljs-type">const</span> TArray<UObject*>& PayloadData)</span> <span class="hljs-type">const</span> <span class="hljs-keyword">override</span>
</span>{
<span class="hljs-keyword">if</span> (UGorgeousInventoryConfig_DA* Config = <span class="hljs-built_in">Cast</span><UGorgeousInventoryConfig_DA>(GeneratedAsset))
{
<span class="hljs-comment">// Populate Config from PayloadData (cast payloads as needed)</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
};
Wizard payload pages
Payload classes render as wizard pages and provide validation hooks.
Auto-mapping: The Library Wizard will attempt to copy property values from payload objects onto the generated asset when a payload UPROPERTY name and type match a property on the asset to create. This automatic mapping uses Unreal's reflection system (UPROPERTY/FProperty) to assign values so simple configuration fields commonly transfer without custom code. To customize or opt out of automatic copying, override PostCreate() in the payload or perform mapping manually inside ExecuteTemplateGeneration() on the generated asset.
UCLASS(Blueprintable, EditInlineNew)
class UGorgeousInventoryPayload : public UGorgeousSetupWizardPayload
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "Setup")
int32 DefaultStackSize = 100;
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-type">bool</span> <span class="hljs-title">PreCreate_Implementation</span><span class="hljs-params">(FString& OutFailureReason)</span> <span class="hljs-keyword">override</span>
</span>{
<span class="hljs-keyword">if</span> (DefaultStackSize <= <span class="hljs-number">0</span>) { OutFailureReason = <span class="hljs-built_in">TEXT</span>(<span class="hljs-string">"Default stack size must be > 0"</span>); <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; }
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-type">bool</span> <span class="hljs-title">PostCreate_Implementation</span><span class="hljs-params">(UObject* CreatedAsset, FString& OutFailureReason)</span> <span class="hljs-keyword">override</span>
</span>{
<span class="hljs-comment">// Finalize the generated asset after save</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
};
Implementing an IGorgeousLibraryParticipant
Participants expose categories, custom icons, and optional behaviors (context menu, double-click). Return a list of FGorgeousLibraryCategoryDescriptor via GetLibraryCategories().
class FMyLibraryParticipant : public IGorgeousLibraryParticipant
{
public:
virtual FName GetParticipantName() const override { return TEXT("MyPlugin"); }
virtual FText GetParticipantDisplayName() const override { return NSLOCTEXT("MyPlugin","DisplayName","My Plugin"); }
<span class="hljs-function"><span class="hljs-keyword">virtual</span> TArray<FGorgeousLibraryCategoryDescriptor> <span class="hljs-title">GetLibraryCategories</span><span class="hljs-params">()</span> <span class="hljs-type">const</span> <span class="hljs-keyword">override</span>
</span>{
FGorgeousLibraryCategoryDescriptor Cat;
Cat.CategoryId = <span class="hljs-built_in">TEXT</span>(<span class="hljs-string">"MyTemplates"</span>);
Cat.DisplayName = <span class="hljs-built_in">NSLOCTEXT</span>(<span class="hljs-string">"MyPlugin"</span>,<span class="hljs-string">"Templates"</span>,<span class="hljs-string">"Templates"</span>);
Cat.AssetClassPath = <span class="hljs-built_in">FTopLevelAssetPath</span>(<span class="hljs-built_in">TEXT</span>(<span class="hljs-string">"/Script/MyPlugin"</span>), <span class="hljs-built_in">TEXT</span>(<span class="hljs-string">"MyTemplate_DA"</span>));
Cat.bOpensSetupWizard = <span class="hljs-literal">true</span>;
Cat.ViewMode = EGorgeousLibraryViewMode::Grid;
Cat.bHasSearchFilter = <span class="hljs-literal">true</span>;
Cat.bEnableAdvancedFiltering = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">return</span> { Cat };
}
};
In your module's startup assign your participant instance so the library can discover it (mirror pattern used by IGorgeousThingsModuleInterface).
Filters & actions
- Use
GetFilters(CategoryId)to provideFGorgeousLibraryFiltertags that appear as toggles. - Populate
CategoryActionswithFGorgeousLibraryCategoryActionto show header buttons (e.g., Create, +).
Iconography & tiles
- Templates may provide
TemplateIcon(aUTexture2D) โGetAssetIcon()will use it if present. - Provide meaningful
TemplateTitleandTemplateDescriptionfor discoverability.
Best practices
- Mark templates as editor-only (
IsEditorOnly()returns true) โ templates are not shipped into runtime builds. - Keep
ExecuteTemplateGeneration()idempotent and robust: validate payload types and return false with a clear error if generation fails. - Keep wizard pages focused and validate user input in
PreCreate()to avoid blocking finish flows.
Troubleshooting
- Tile not appearing: verify
AssetClassPathand that assets are saved where the Asset Registry can find them. - Wizard refuses to finish: check
PreCreate()return values andOutFailureReasonstrings. - Created asset missing values: ensure
ExecuteTemplateGeneration()copies payload values and marks the asset dirty if necessary (Modify()).
Plugins participating must override IGorgeousLibraryParticipant and set the reference in their module interface as described above.