Files
UnrealEngineUWP/Engine/Source/Editor/DestructibleMeshEditor/Private/DestructibleMeshEditorModule.cpp
Ben Marsh 20bf0eb6a1 Updating copyright notices to 2017 (copying from //Tasks/UE4/Dev-Copyright-2017).
#rb none
#lockdown Nick.Penwarden

[CL 3226823 by Ben Marsh in Main branch]
2016-12-08 08:52:44 -05:00

159 lines
6.1 KiB
C++

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
#include "DestructibleMeshEditorModule.h"
#include "Misc/PackageName.h"
#include "Modules/ModuleManager.h"
#include "IDestructibleMeshEditor.h"
#include "DestructibleMeshEditor.h"
#include "Misc/MessageDialog.h"
#include "IAssetTools.h"
#include "AssetToolsModule.h"
#include "Engine/DestructibleMesh.h"
#include "Engine/StaticMesh.h"
#include "Materials/Material.h"
#include "Materials/MaterialExpressionSpeedTree.h"
IMPLEMENT_MODULE( FDestructibleMeshEditorModule, DestructibleMeshEditor );
#define LOCTEXT_NAMESPACE "DestructibleMeshEditor"
const FName DestructibleMeshEditorAppIdentifier = FName(TEXT("DestructibleMeshEditorApp"));
void FDestructibleMeshEditorModule::StartupModule()
{
MenuExtensibilityManager = MakeShareable(new FExtensibilityManager);
ToolBarExtensibilityManager = MakeShareable(new FExtensibilityManager);
}
void FDestructibleMeshEditorModule::ShutdownModule()
{
MenuExtensibilityManager.Reset();
ToolBarExtensibilityManager.Reset();
}
TSharedRef<IDestructibleMeshEditor> FDestructibleMeshEditorModule::CreateDestructibleMeshEditor( const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, UDestructibleMesh* Table )
{
TSharedRef< FDestructibleMeshEditor > NewDestructibleMeshEditor( new FDestructibleMeshEditor() );
NewDestructibleMeshEditor->InitDestructibleMeshEditor( Mode, InitToolkitHost, Table );
return NewDestructibleMeshEditor;
}
UDestructibleMesh* FDestructibleMeshEditorModule::CreateDestructibleMeshFromStaticMesh(UObject* InParent, UStaticMesh* StaticMesh, FName Name, EObjectFlags Flags, FText& OutErrorMsg)
{
if (StaticMesh == NULL)
{
OutErrorMsg = LOCTEXT( "StaticMeshInvalid", "Static Mesh is Invalid!" );
return NULL;
}
// We can't use any speedtree materials for destructibles due to UV requirements, so check the graph here
TArray<UMaterial*> SpeedTreeMaterials;
for(FStaticMaterial& StaticMaterial : StaticMesh->StaticMaterials)
{
UMaterialInterface* Mat = StaticMaterial.MaterialInterface;
UMaterial* BaseMat = Mat->GetBaseMaterial();
for(UMaterialExpression* Expression : BaseMat->Expressions)
{
if(Cast<UMaterialExpressionSpeedTree>(Expression))
{
SpeedTreeMaterials.Add(BaseMat);
break;
}
}
}
if(SpeedTreeMaterials.Num() > 0)
{
// Invalid, can't create a mesh from this
FTextBuilder TextBuilder;
TextBuilder.AppendLine(FText::Format(LOCTEXT("StaticMeshInvalid_SpeedTree", "The static mesh '{0}' uses SpeedTree materials which are not compatible with destructible meshes. Cannot create destructible.\n\nList of Materials:\n"), FText::FromString(StaticMesh->GetName())));
for(UMaterial* SpeedTreeMat : SpeedTreeMaterials)
{
TextBuilder.AppendLine(SpeedTreeMat->GetName());
}
FMessageDialog::Open(EAppMsgType::Ok, TextBuilder.ToText());
return nullptr;
}
FString DestructibleName;
if (Name == NAME_None)
{
DestructibleName = StaticMesh->GetName();
DestructibleName += TEXT("_DM");
}
else
{
DestructibleName = *Name.ToString();
}
UDestructibleMesh* DestructibleMesh = FindObject<UDestructibleMesh>( InParent, *DestructibleName );
// If there is an existing mesh, ask the user if they want to use the existing mesh, replace the existing mesh, or create a new mesh.
if (DestructibleMesh != NULL)
{
enum ENameConflictDialogReturnType
{
NCD_None = 0,
NCD_Use,
NCD_Replace,
NCD_Create
};
#if 0 // BRG - removed SSimpleDialog, needs replacing
FSimpleDialogModule& SimpleDialogModule = FModuleManager::LoadModuleChecked<FSimpleDialogModule>( TEXT("SimpleDialog") );
SimpleDialogModule.CreateSimpleDialog(NSLOCTEXT("SimpleDialogModule", "DestructibleMeshAlreadyExistsTitle", "DestructibleMesh Already Exists").ToString(), NSLOCTEXT("SimpleDialogModule", "DestructibleMeshAlreadyExistsMessage", "A DestructibleMesh by the same name already exists. Select an action.").ToString());
SimpleDialogModule.AddButton(NCD_Use, NSLOCTEXT("SimpleDialogModule", "UseExistingDestructibleMesh", "Use").ToString(), NSLOCTEXT("SimpleDialogModule", "UseExistingDestructibleMeshTip", "Open the DestructibleMesh editor with the existing mesh").ToString());
SimpleDialogModule.AddButton(NCD_Replace, NSLOCTEXT("SimpleDialogModule", "ReplaceExistingDestructibleMesh", "Replace").ToString(), NSLOCTEXT("SimpleDialogModule", "ReplaceExistingDestructibleMeshTip", "Replace the existing DestructibleMesh with a new one, and show in the DestructibleMesh editor").ToString());
SimpleDialogModule.AddButton(NCD_Create, NSLOCTEXT("SimpleDialogModule", "CreateNewDestructibleMesh", "Create").ToString(), NSLOCTEXT("SimpleDialogModule", "CreateNewDestructibleMeshTip", "Create a new DestructibleMesh with a different name, and show in the DestructibleMesh editor").ToString());
const uint32 UserResponse = SimpleDialogModule.ShowSimpleDialog();
#endif
const uint32 UserResponse = NCD_None;
CA_SUPPRESS(6326);
switch (UserResponse)
{
default: // Default to using the same mesh
case NCD_Use:
return DestructibleMesh;
case NCD_Replace:
break;
case NCD_Create:
Name = MakeUniqueObjectName(StaticMesh->GetOuter(), UDestructibleMesh::StaticClass(), Name);
DestructibleName = *Name.ToString();
DestructibleMesh = NULL; // So that one will be created
break;
}
}
// Create the new UDestructibleMesh object if we still haven't found one after a possible resolution above
if (DestructibleMesh == NULL)
{
FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");
DestructibleMesh = Cast<UDestructibleMesh>(AssetToolsModule.Get().CreateAsset(DestructibleName, FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetPathName()), UDestructibleMesh::StaticClass(), NULL));
if(!DestructibleMesh)
{
FFormatNamedArguments Arguments;
Arguments.Add(TEXT("Name"), FText::FromString( StaticMesh->GetName() ));
OutErrorMsg = FText::Format( LOCTEXT( "DestructibleMeshFailed", "Failed to Create Destructible Mesh Asset from {Name}!" ), Arguments );
return NULL;
}
}
DestructibleMesh->BuildFromStaticMesh(*StaticMesh);
return DestructibleMesh;
}
#undef LOCTEXT_NAMESPACE