CelticCraft/Plugins/VoxelFree/Source/VoxelEditor/Private/VoxelEditorModule.cpp

561 lines
No EOL
26 KiB
C++

// Copyright 2020 Phyronnaz
#include "VoxelEditorModule.h"
#include "VoxelMinimal.h"
#include "Interfaces/IPluginManager.h"
#include "IPlacementModeModule.h"
#include "PropertyEditorModule.h"
#include "Styling/SlateStyle.h"
#include "Styling/SlateStyleRegistry.h"
#include "EditorModeRegistry.h"
#include "EditorSupportDelegates.h"
#include "LevelEditor.h"
#include "EngineUtils.h"
#include "MessageLogModule.h"
#include "EditorReimportHandler.h"
#include "Framework/Commands/Commands.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "WorkspaceMenuStructure.h"
#include "WorkspaceMenuStructureModule.h"
#include "VoxelGraphGenerator.h"
#include "IVoxelPool.h"
#include "VoxelWorld.h"
#include "VoxelTexture.h"
#include "VoxelMessages.h"
#include "VoxelBoolVector.h"
#include "VoxelMessagesEditor.h"
#include "VoxelEditorDelegates.h"
#include "VoxelOpenAssetsOnStartup.h"
#include "VoxelConvertLandscapeMaterial.h"
#include "VoxelTools/VoxelPaintMaterial.h"
#include "VoxelNodes/VoxelOptimizationNodes.h"
#include "VoxelPlaceableItems/Actors/VoxelAssetActor.h"
#include "VoxelPlaceableItems/Actors/VoxelDisableEditsBox.h"
#include "AssetTools/AssetTypeActions_VoxelDataAsset.h"
#include "AssetTools/AssetTypeActions_VoxelHeightmapAsset.h"
#include "AssetTools/AssetTypeActions_VoxelGraphGenerator.h"
#include "AssetTools/AssetTypeActions_VoxelGraphOutputsConfig.h"
#include "AssetTools/AssetTypeActions_VoxelGraphDataItemConfig.h"
#include "AssetTools/AssetTypeActions_VoxelSpawnerConfig.h"
#include "AssetTools/AssetTypeActions_VoxelSpawners.h"
#include "AssetTools/AssetTypeActions_VoxelGraphMacro.h"
#include "AssetTools/AssetTypeActions_VoxelWorldSaveObject.h"
#include "AssetTools/AssetTypeActions_VoxelMaterialCollection.h"
#include "Thumbnails/VoxelGraphGeneratorThumbnailRenderer.h"
#include "Thumbnails/VoxelSpawnersThumbnailRenderer.h"
#include "Thumbnails/VoxelDataAssetThumbnailRenderer.h"
#include "Thumbnails/VoxelHeightmapAssetThumbnailRenderer.h"
#include "DataAssetEditor/VoxelDataAssetEditorToolkit.h"
#include "EdMode/VoxelEdMode.h"
#include "VoxelToolsCommands.h"
#include "ActorFactoryVoxelWorld.h"
#include "ActorFactoryVoxelPlaceableItems.h"
#include "ActorFactoryVoxelMeshImporter.h"
#include "Details/VoxelWorldDetails.h"
#include "Details/VoxelLandscapeImporterDetails.h"
#include "Details/VoxelMeshImporterDetails.h"
#include "Details/VoxelAssetActorDetails.h"
#include "Details/VoxelGeneratorPickerCustomization.h"
#include "Details/RangeAnalysisDebuggerDetails.h"
#include "Details/VoxelPaintMaterialCustomization.h"
#include "Details/VoxelMeshSpawnerBaseDetails.h"
#include "Details/VoxelBasicSpawnerScaleSettingsCustomization.h"
#include "Details/VoxelSpawnerOutputNameCustomization.h"
#include "Details/VoxelSpawnerDensityCustomization.h"
#include "Details/VoxelSpawnerConfigSpawnerCustomization.h"
#include "Details/VoxelGraphOutputCustomization.h"
#include "Details/VoxelInt32IntervalCustomization.h"
#include "Details/VoxelBoolVectorCustomization.h"
#include "VoxelImporters/VoxelMeshImporter.h"
#include "VoxelImporters/VoxelLandscapeImporter.h"
#include "VoxelComponents/VoxelInvokerComponent.h"
#include "Factories/VoxelWorldSaveObjectFactory.h"
#include "VoxelEditorDetailsUtilities.h"
#include "VoxelDebugEditor.h"
#include "VoxelScopedTransaction.h"
#include "VoxelWorldEditorControls.h"
const FVector2D Icon14x14(14.0f, 14.0f);
const FVector2D Icon16x16(16.0f, 16.0f);
const FVector2D Icon20x20(20.0f, 20.0f);
const FVector2D Icon40x40(40.0f, 40.0f);
const FVector2D Icon64x64(64.0f, 64.0f);
const FVector2D Icon512x512(512.0f, 512.0f);
class FVoxelEditorCommands : public TCommands<FVoxelEditorCommands>
{
public:
FVoxelEditorCommands()
: TCommands<FVoxelEditorCommands>
(
"VoxelEditor", // Context name for icons
VOXEL_LOCTEXT("Voxel Editor"), // Localized context name for displaying
NAME_None, // Parent
"VoxelStyle" // Icon Style Set
)
{
}
TSharedPtr<FUICommandInfo> RefreshVoxelWorlds;
#define LOCTEXT_NAMESPACE "Voxel"
virtual void RegisterCommands() override
{
UI_COMMAND(
RefreshVoxelWorlds,
"Retoggle",
"Retoggle the voxel worlds",
EUserInterfaceActionType::Button,
FInputChord(EModifierKey::Control, EKeys::F5));
}
#undef LOCTEXT_NAMESPACE
};
static void RefreshVoxelWorlds_Execute(UObject* MatchingGenerator = nullptr)
{
FViewport* Viewport = GEditor->GetActiveViewport();
if (Viewport)
{
FViewportClient* Client = Viewport->GetClient();
if (Client)
{
UWorld* World = Client->GetWorld();
if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
{
for (TActorIterator<AVoxelWorld> It(World); It; ++It)
{
if (It->IsCreated() && (!MatchingGenerator || It->Generator.GetObject() == MatchingGenerator))
{
It->Toggle();
It->Toggle();
}
}
for (TActorIterator<AVoxelAssetActor> It(World); It; ++It)
{
It->UpdatePreview();
}
}
}
}
}
static void BindEditorDelegates(IVoxelEditorDelegatesInterface* Interface, UObject* Object)
{
check(Interface && Object);
if (!FEditorDelegates::PreSaveWorld.IsBoundToObject(Object))
{
FEditorDelegates::PreSaveWorld.AddWeakLambda(Object, [=](uint32 SaveFlags, UWorld* World) { Interface->OnPreSaveWorld(SaveFlags, World); });
}
if (!FEditorDelegates::PreBeginPIE.IsBoundToObject(Object))
{
FEditorDelegates::PreBeginPIE.AddWeakLambda(Object, [=](bool bIsSimulating) { Interface->OnPreBeginPIE(bIsSimulating); });
}
if (!FEditorDelegates::EndPIE.IsBoundToObject(Object))
{
FEditorDelegates::EndPIE.AddWeakLambda(Object, [=](bool bIsSimulating) { Interface->OnEndPIE(bIsSimulating); });
}
if (!FEditorDelegates::OnApplyObjectToActor.IsBoundToObject(Object))
{
FEditorDelegates::OnApplyObjectToActor.AddWeakLambda(Object, [=](UObject* InObject, AActor* InActor) { Interface->OnApplyObjectToActor(InObject, InActor); });
}
if (!FEditorSupportDelegates::PrepareToCleanseEditorObject.IsBoundToObject(Object))
{
FEditorSupportDelegates::PrepareToCleanseEditorObject.AddWeakLambda(Object, [=](UObject* InObject) { Interface->OnPrepareToCleanseEditorObject(InObject); });
}
if (!FCoreDelegates::OnPreExit.IsBoundToObject(Object))
{
FCoreDelegates::OnPreExit.AddWeakLambda(Object, [=]() { Interface->OnPreExit(); });
}
}
class FVoxelWorldEditor : public IVoxelWorldEditor
{
public:
FVoxelWorldEditor() = default;
virtual UVoxelWorldSaveObject* CreateSaveObject() override
{
return Cast<UVoxelWorldSaveObject>(FVoxelEditorUtilities::CreateAssetWithDialog(UVoxelWorldSaveObject::StaticClass(), NewObject<UVoxelWorldSaveObjectFactory>()));
}
virtual UClass* GetVoxelWorldEditorClass() override
{
return AVoxelWorldEditorControls::StaticClass();
}
virtual void RegisterTransaction(AVoxelWorld* VoxelWorld, FName Name) override
{
FVoxelScopedTransaction Transaction(VoxelWorld, Name, EVoxelChangeType::Edit);
}
};
/**
* Implements the VoxelEditor module.
*/
class FVoxelEditorModule : public IVoxelEditorModule
{
public:
virtual void StartupModule() override
{
UVoxelOpenAssetsOnStartup::Init();
FVoxelConvertLandscapeMaterial::Init();
// Voxel World Editor
if (!IVoxelWorldEditor::GetVoxelWorldEditor())
{
IVoxelWorldEditor::SetVoxelWorldEditor(MakeShared<FVoxelWorldEditor>());
}
FVoxelEditorDelegates::FixVoxelLandscapeMaterial.AddStatic(&FVoxelConvertLandscapeMaterial::ConvertMaterial);
// Destroy global pool on end PIE
FEditorDelegates::EndPIE.AddLambda([](bool bIsSimulating)
{
if (IVoxelPool::GetGlobalPool())
{
IVoxelPool::DestroyGlobalPool();
}
});
// Clear texture cache on reimport
FReimportManager::Instance()->OnPostReimport().AddLambda([](UObject*, bool) { FVoxelTextureUtilities::ClearCache(); });
// Global commands
FVoxelEditorCommands::Register();
FVoxelToolsCommands::Register();
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
LevelEditorModule.GetGlobalLevelEditorActions()->MapAction(
FVoxelEditorCommands::Get().RefreshVoxelWorlds,
FExecuteAction::CreateStatic(&RefreshVoxelWorlds_Execute, (UObject*)nullptr),
FCanExecuteAction());
IVoxelEditorDelegatesInterface::BindEditorDelegatesDelegate.AddStatic(&BindEditorDelegates);
// Blueprint errors
FVoxelMessages::LogMessageDelegate.AddStatic(&FVoxelMessagesEditor::LogMessage);
FVoxelMessages::ShowNotificationDelegate.AddStatic(&FVoxelMessagesEditor::ShowNotification);
FMessageLogModule& MessageLogModule = FModuleManager::LoadModuleChecked<FMessageLogModule>("MessageLog");
FMessageLogInitializationOptions InitOptions;
InitOptions.bShowFilters = true;
InitOptions.bShowPages = false;
InitOptions.bAllowClear = true;
MessageLogModule.RegisterLogListing("Voxel", VOXEL_LOCTEXT("Voxel"), InitOptions);
// Voxel asset category
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
VoxelAssetCategoryBit = AssetTools.RegisterAdvancedAssetCategory("Voxel", VOXEL_LOCTEXT("Voxel"));
RegisterPlacementModeExtensions();
RegisterCustomClassLayouts();
RegisterAssetTools();
// Thumbnails
auto& ThumbnailManager = UThumbnailManager::Get();
ThumbnailManager.RegisterCustomRenderer(UVoxelGraphGenerator ::StaticClass(), UVoxelGraphGeneratorThumbnailRenderer ::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelDataAsset ::StaticClass(), UVoxelDataAssetThumbnailRenderer ::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelHeightmapAsset ::StaticClass(), UVoxelHeightmapAssetThumbnailRenderer ::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelMeshSpawner ::StaticClass(), UVoxelMeshSpawnerThumbnailRenderer ::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelMeshSpawnerGroup::StaticClass(), UVoxelMeshSpawnerGroupThumbnailRenderer::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelAssetSpawner ::StaticClass(), UVoxelAssetSpawnerThumbnailRenderer ::StaticClass());
ThumbnailManager.RegisterCustomRenderer(UVoxelSpawnerGroup ::StaticClass(), UVoxelSpawnerGroupThumbnailRenderer ::StaticClass());
// Icons
{
FString ContentDir = IPluginManager::Get().FindPlugin(VOXEL_PLUGIN_NAME)->GetContentDir() + "/";
StyleSet = MakeShareable(new FSlateStyleSet("VoxelStyle"));
StyleSet->SetContentRoot(FPaths::EngineContentDir() / TEXT("Editor/Slate"));
StyleSet->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate"));
// For menus
StyleSet->Set("VoxelIcon" , new FSlateImageBrush(ContentDir + TEXT("Editor/UIIcons/mode_40.png"), Icon16x16));
// VoxelWorld
StyleSet->Set("ClassThumbnail.VoxelWorld" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/World_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelWorld" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/World_16x.png"), Icon16x16));
// Voxel Material Collection
StyleSet->Set("ClassThumbnail.VoxelMaterialCollectionBase" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/MaterialCollection_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelMaterialCollectionBase" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/MaterialCollection_16x.png"), Icon16x16));
// Importers
StyleSet->Set("ClassThumbnail.VoxelLandscapeImporter" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Import_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelLandscapeImporter" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Import_16x.png"), Icon16x16));
StyleSet->Set("ClassThumbnail.VoxelMeshImporter" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Import_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelMeshImporter" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Import_16x.png"), Icon16x16));
// Spawners
StyleSet->Set("ClassThumbnail.VoxelSpawnerConfig" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerConfig_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelSpawnerConfig" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerConfig_16x.png"), Icon16x16));
StyleSet->Set("ClassThumbnail.VoxelSpawner" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Spawner_64x.png") , Icon64x64));
StyleSet->Set("ClassIcon.VoxelSpawner" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Spawner_16x.png") , Icon16x16));
StyleSet->Set("ClassThumbnail.VoxelSpawnerGroup" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerGroup_64x.png") , Icon64x64));
StyleSet->Set("ClassIcon.VoxelSpawnerGroup" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerGroup_16x.png") , Icon16x16));
StyleSet->Set("ClassThumbnail.VoxelMeshSpawnerGroup" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerGroup_64x.png") , Icon64x64));
StyleSet->Set("ClassIcon.VoxelMeshSpawnerGroup" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/SpawnerGroup_16x.png") , Icon16x16));
// Voxel Graph
StyleSet->Set("ClassThumbnail.VoxelGraphGenerator" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/VoxelGraph_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelGraphGenerator" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/VoxelGraph_16x.png"), Icon16x16));
// Data Asset
StyleSet->Set("ClassThumbnail.VoxelDataAsset" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/DataAsset_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelDataAsset" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/DataAsset_16x.png"), Icon16x16));
// Landscape asset
StyleSet->Set("ClassThumbnail.VoxelLandscapeAsset" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Landscape_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelLandscapeAsset" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Landscape_16x.png"), Icon16x16));
// Data Asset Editor
StyleSet->Set("VoxelDataAssetEditor.InvertDataAsset" , new FSlateImageBrush(ContentDir + TEXT("Editor/UIIcons/InvertDataAsset_40x.png"), Icon40x40));
StyleSet->Set("VoxelDataAssetEditor.InvertDataAsset.Small" , new FSlateImageBrush(ContentDir + TEXT("Editor/UIIcons/InvertDataAsset_16x.png"), Icon16x16));
// Voxel Editor Tools
StyleSet->Set("VoxelTools.Tab" , new FSlateImageBrush(ContentDir + TEXT("Editor/UIIcons/mode_40.png"), Icon40x40));
StyleSet->Set("VoxelTools.Tab.Small" , new FSlateImageBrush(ContentDir + TEXT("Editor/UIIcons/mode_40.png"), Icon16x16));
// Generator
StyleSet->Set("ClassThumbnail.VoxelGenerator" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Generator_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelGenerator" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/Generator_16x.png"), Icon16x16));
// Voxel World Object Save
StyleSet->Set("ClassThumbnail.VoxelWorldSaveObject" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/VoxelWorldSaveObject_64x.png"), Icon64x64));
StyleSet->Set("ClassIcon.VoxelWorldSaveObject" , new FSlateImageBrush(ContentDir + TEXT("Editor/AssetIcons/VoxelWorldSaveObject_16x.png"), Icon16x16));
// Tools
const auto AddTool = [&](const FString& Name)
{
StyleSet->Set(*("VoxelTools." + Name), new FSlateImageBrush(ContentDir + "Editor/UIIcons/Tools/" + Name + "_40.png", Icon40x40));
StyleSet->Set(*("VoxelTools." + Name + ".Small"), new FSlateImageBrush(ContentDir + "Editor/UIIcons/Tools/" + Name + "_40.png", Icon16x16));
};
AddTool("FlattenTool");
AddTool("LevelTool");
AddTool("MeshTool");
AddTool("RevertTool");
AddTool("SmoothTool");
AddTool("SphereTool");
AddTool("SurfaceTool");
AddTool("TrimTool");
FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
}
{
FTabSpawnerEntry& SpawnerEntry = FGlobalTabmanager::Get()->RegisterNomadTabSpawner("VoxelDebug", FOnSpawnTab::CreateStatic(&FVoxelDebugEditor::CreateTab))
.SetDisplayName(VOXEL_LOCTEXT("Voxel Debug"))
.SetIcon(FSlateIcon(StyleSet->GetStyleSetName(), "VoxelIcon"));
SpawnerEntry.SetGroup(WorkspaceMenu::GetMenuStructure().GetDeveloperToolsMiscCategory());
}
// Voxel Editor Tools
FEditorModeRegistry::Get().RegisterMode<FEdModeVoxel>(FEdModeVoxel::EM_Voxel, VOXEL_LOCTEXT("Voxels"), FSlateIcon("VoxelStyle", "VoxelTools.Tab", "VoxelTools.Tab.Small"), true);
}
virtual void ShutdownModule() override
{
FEditorModeRegistry::Get().UnregisterMode(FEdModeVoxel::EM_Voxel);
if (UObjectInitialized())
{
auto& ThumbnailManager = UThumbnailManager::Get();
ThumbnailManager.UnregisterCustomRenderer(UVoxelGraphGenerator::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelDataAsset::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelHeightmapAsset::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelMeshSpawner::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelMeshSpawnerGroup::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelAssetSpawner::StaticClass());
ThumbnailManager.UnregisterCustomRenderer(UVoxelSpawnerGroup::StaticClass());
}
UnregisterPlacementModeExtensions();
UnregisterClassLayout();
UnregisterAssetTools();
if (StyleSet.IsValid())
{
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet.Get());
StyleSet.Reset();
}
}
virtual bool SupportsDynamicReloading() override
{
return true;
}
private:
template<typename T>
void RegisterPlacementModeExtension(IPlacementModeModule& PlacementModeModule, UActorFactory* Factory = nullptr)
{
PlacementModeModule.RegisterPlaceableItem(PlacementCategoryInfo.UniqueHandle, MakeShared<FPlaceableItem>(Factory, FAssetData(T::StaticClass())));
}
void RegisterPlacementModeExtensions()
{
IPlacementModeModule& PlacementModeModule = IPlacementModeModule::Get();
PlacementModeModule.RegisterPlacementCategory(PlacementCategoryInfo);
RegisterPlacementModeExtension<AVoxelWorld >(PlacementModeModule, GetMutableDefault<UActorFactoryVoxelWorld >());
RegisterPlacementModeExtension<AVoxelDisableEditsBox>(PlacementModeModule, GetMutableDefault<UActorFactoryVoxelDisableEditsBox>());
RegisterPlacementModeExtension<AVoxelAssetActor >(PlacementModeModule, GetMutableDefault<UActorFactoryVoxelAssetActor >());
RegisterPlacementModeExtension<AVoxelMeshImporter >(PlacementModeModule, GetMutableDefault<UActorFactoryVoxelMeshImporter >());
RegisterPlacementModeExtension<AVoxelLODVolume>(PlacementModeModule);
RegisterPlacementModeExtension<AVoxelLandscapeImporter>(PlacementModeModule);
PlacementModeModule.RegenerateItemsForCategory(FBuiltInPlacementCategories::AllClasses());
}
void UnregisterPlacementModeExtensions()
{
if (IPlacementModeModule::IsAvailable())
{
IPlacementModeModule::Get().UnregisterPlacementCategory(PlacementCategoryInfo.UniqueHandle);
}
}
private:
template<typename TDetails, typename TClass>
void RegisterCustomClassLayout()
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
const FName Name = TClass::StaticClass()->GetFName();
PropertyModule.RegisterCustomClassLayout(Name, FOnGetDetailCustomizationInstance::CreateLambda([]() { return MakeShared<TDetails>(); }));
RegisteredCustomClassLayouts.Add(Name);
}
template<typename TDetails, typename TStruct>
void RegisterCustomPropertyLayout()
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
const FName Name = TStruct::StaticStruct()->GetFName();
PropertyModule.RegisterCustomPropertyTypeLayout(Name, FOnGetPropertyTypeCustomizationInstance::CreateLambda([]() { return MakeShared<TDetails>(); }));
RegisteredCustomPropertyLayouts.Add(Name);
}
void RegisterCustomClassLayouts()
{
RegisterCustomClassLayout<FVoxelWorldDetails , AVoxelWorld >();
RegisterCustomClassLayout<FVoxelLandscapeImporterDetails, AVoxelLandscapeImporter >();
RegisterCustomClassLayout<FVoxelMeshImporterDetails , AVoxelMeshImporter >();
RegisterCustomClassLayout<FVoxelAssetActorDetails , AVoxelAssetActor >();
RegisterCustomClassLayout<FRangeAnalysisDebuggerDetails , UVoxelNode_RangeAnalysisDebuggerFloat>();
RegisterCustomClassLayout<FVoxelMeshSpawnerBaseDetails , UVoxelMeshSpawnerBase >();
RegisterCustomPropertyLayout<FVoxelGeneratorPickerCustomization , FVoxelGeneratorPicker >();
RegisterCustomPropertyLayout<FVoxelGeneratorPickerCustomization , FVoxelTransformableGeneratorPicker >();
RegisterCustomPropertyLayout<FVoxelPaintMaterialCustomization , FVoxelPaintMaterial >();
RegisterCustomPropertyLayout<FVoxelPaintMaterial_MaterialCollectionChannelCustomization, FVoxelPaintMaterial_MaterialCollectionChannel>();
RegisterCustomPropertyLayout<FVoxelBoolVectorCustomization , FVoxelBoolVector >();
RegisterCustomPropertyLayout<FVoxelBasicSpawnerScaleSettingsCustomization , FVoxelBasicSpawnerScaleSettings >();
RegisterCustomPropertyLayout<FVoxelSpawnerOutputNameCustomization , FVoxelSpawnerOutputName >();
RegisterCustomPropertyLayout<FVoxelSpawnerDensityCustomization , FVoxelSpawnerDensity >();
RegisterCustomPropertyLayout<FVoxelSpawnerConfigSpawnerCustomization , FVoxelSpawnerConfigSpawner >();
RegisterCustomPropertyLayout<FVoxelGraphOutputCustomization , FVoxelGraphOutput >();
RegisterCustomPropertyLayout<FVoxelInt32IntervalCustomization , FVoxelInt32Interval >();
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.NotifyCustomizationModuleChanged();
}
void UnregisterClassLayout()
{
if (auto* PropertyModule = FModuleManager::GetModulePtr<FPropertyEditorModule>("PropertyEditor"))
{
for (auto& Name : RegisteredCustomClassLayouts)
{
PropertyModule->UnregisterCustomClassLayout(Name);
}
for (auto& Name : RegisteredCustomPropertyLayouts)
{
PropertyModule->UnregisterCustomPropertyTypeLayout(Name);
}
PropertyModule->NotifyCustomizationModuleChanged();
}
}
private:
template<typename T>
void RegisterAssetTypeAction()
{
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
auto Action = MakeShared<T>(VoxelAssetCategoryBit);
AssetTools.RegisterAssetTypeActions(Action);
RegisteredAssetTypeActions.Add(Action);
}
void RegisterAssetTools()
{
RegisterAssetTypeAction<FAssetTypeActions_VoxelWorldSaveObject>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelBasicMaterialCollection>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelInstancedMaterialCollectionTemplates>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelInstancedMaterialCollection>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelInstancedMaterialCollectionInstance>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelLandscapeMaterialCollection>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelDataAsset>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelSpawnerConfig>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelAssetSpawner>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelMeshSpawner>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelMeshSpawnerGroup>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelSpawnerGroup>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelHeightmapAsset>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelGraphGenerator>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelGraphMacro>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelGraphOutputsConfig>();
RegisterAssetTypeAction<FAssetTypeActions_VoxelGraphDataItemConfig>();
}
void UnregisterAssetTools()
{
if (auto* AssetToolsModule = FModuleManager::GetModulePtr<FAssetToolsModule>("AssetTools"))
{
IAssetTools& AssetTools = AssetToolsModule->Get();
for (auto& Action : RegisteredAssetTypeActions)
{
AssetTools.UnregisterAssetTypeActions(Action);
}
}
}
public:
virtual void CreateVoxelDataAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UVoxelDataAsset* DataAsset) override
{
TSharedRef<FVoxelDataAssetEditorToolkit> NewVoxelEditor(new FVoxelDataAssetEditorToolkit());
NewVoxelEditor->InitVoxelEditor(Mode, InitToolkitHost, DataAsset);
}
virtual void RefreshVoxelWorlds(UObject* MatchingGenerator) override
{
RefreshVoxelWorlds_Execute(MatchingGenerator);
}
virtual EAssetTypeCategories::Type GetVoxelAssetTypeCategory() const override
{
return VoxelAssetCategoryBit;
}
private:
/** The collection of registered asset type actions. */
TArray<TSharedRef<IAssetTypeActions>> RegisteredAssetTypeActions;
TArray<FName> RegisteredCustomClassLayouts;
TArray<FName> RegisteredCustomPropertyLayouts;
EAssetTypeCategories::Type VoxelAssetCategoryBit = EAssetTypeCategories::None;
FPlacementCategoryInfo PlacementCategoryInfo = FPlacementCategoryInfo(VOXEL_LOCTEXT("Voxel"), "Voxel", TEXT("PMVoxel"), 25);
TSharedPtr<FSlateStyleSet> StyleSet;
};
IMPLEMENT_MODULE(FVoxelEditorModule, VoxelEditor);