2019-12-27 09:26:59 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-09-12 13:55:17 -04:00
# include "MergeMeshesTool.h"
# include "InteractiveToolManager.h"
# include "ToolBuilderUtil.h"
2019-10-24 16:45:51 -04:00
# include "ToolSetupUtil.h"
2021-06-02 15:58:00 -04:00
# include "ModelingObjectsCreationAPI.h"
2021-11-23 09:42:40 -05:00
# include "ModelingToolTargetUtil.h"
2019-09-12 13:55:17 -04:00
# include "Selection/ToolSelectionUtil.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/DynamicMesh3.h"
2019-09-12 13:55:17 -04:00
# include "MeshDescriptionToDynamicMesh.h"
# include "CompositionOps/VoxelMergeMeshesOp.h"
2021-03-11 11:40:03 -04:00
# include "TargetInterfaces/MeshDescriptionProvider.h"
# include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
# include "ToolTargetManager.h"
2021-03-09 19:33:56 -04:00
using namespace UE : : Geometry ;
2019-09-12 13:55:17 -04:00
# define LOCTEXT_NAMESPACE "UMergeMeshesTool"
/*
* ToolBuilder
*/
2021-03-11 11:40:03 -04:00
const FToolTargetTypeRequirements & UMergeMeshesToolBuilder : : GetTargetRequirements ( ) const
{
static FToolTargetTypeRequirements TypeRequirements ( {
UMeshDescriptionProvider : : StaticClass ( ) ,
UPrimitiveComponentBackedTarget : : StaticClass ( )
} ) ;
return TypeRequirements ;
}
2019-09-12 13:55:17 -04:00
bool UMergeMeshesToolBuilder : : CanBuildTool ( const FToolBuilderState & SceneState ) const
{
2021-11-23 09:42:40 -05:00
constexpr int32 MinRequiredComponents = 1 ;
2021-03-11 11:40:03 -04:00
const bool bHasComponents = SceneState . TargetManager - > CountSelectedAndTargetable ( SceneState , GetTargetRequirements ( ) ) > = MinRequiredComponents ;
2021-06-02 15:58:00 -04:00
return ( bHasComponents ) ;
2019-09-12 13:55:17 -04:00
}
2021-11-23 09:42:40 -05:00
UMultiSelectionMeshEditingTool * UMergeMeshesToolBuilder : : CreateNewTool ( const FToolBuilderState & SceneState ) const
2019-09-12 13:55:17 -04:00
{
2021-11-23 09:42:40 -05:00
return NewObject < UMergeMeshesTool > ( SceneState . ToolManager ) ;
2019-09-12 13:55:17 -04:00
}
/*
* Tool
*/
UMergeMeshesTool : : UMergeMeshesTool ( )
{
}
void UMergeMeshesTool : : Setup ( )
{
UInteractiveTool : : Setup ( ) ;
MergeProps = NewObject < UMergeMeshesToolProperties > ( ) ;
2020-04-21 23:51:57 -04:00
MergeProps - > RestoreProperties ( this ) ;
2019-09-12 13:55:17 -04:00
AddToolPropertySource ( MergeProps ) ;
2019-09-24 13:12:06 -04:00
MeshStatisticsProperties = NewObject < UMeshStatisticsProperties > ( this ) ;
AddToolPropertySource ( MeshStatisticsProperties ) ;
2020-04-21 23:51:57 -04:00
HandleSourcesProperties = NewObject < UOnAcceptHandleSourcesProperties > ( this ) ;
HandleSourcesProperties - > RestoreProperties ( this ) ;
AddToolPropertySource ( HandleSourcesProperties ) ;
2019-09-12 13:55:17 -04:00
// Hide the source meshes
2021-03-11 11:40:03 -04:00
for ( int32 ComponentIdx = 0 ; ComponentIdx < Targets . Num ( ) ; ComponentIdx + + )
2019-09-12 13:55:17 -04:00
{
2021-11-23 09:42:40 -05:00
UE : : ToolTarget : : HideSourceObject ( Targets [ ComponentIdx ] ) ;
2019-09-12 13:55:17 -04:00
}
// save transformed version of input meshes (maybe this could happen in the Operator?)
CacheInputMeshes ( ) ;
// initialize the PreviewMesh+BackgroundCompute object
Preview = NewObject < UMeshOpPreviewWithBackgroundCompute > ( this , " Preview " ) ;
2022-01-28 10:18:10 -05:00
Preview - > Setup ( GetTargetWorld ( ) , this ) ;
2019-09-24 13:12:06 -04:00
Preview - > OnMeshUpdated . AddLambda ( [ this ] ( UMeshOpPreviewWithBackgroundCompute * Compute ) {
MeshStatisticsProperties - > Update ( * Compute - > PreviewMesh - > GetPreviewDynamicMesh ( ) ) ;
2021-02-05 16:33:02 -04:00
UpdateAcceptWarnings ( Compute - > HaveEmptyResult ( ) ? EAcceptWarning : : EmptyForbidden : EAcceptWarning : : NoWarning ) ;
2019-09-24 13:12:06 -04:00
} ) ;
2021-10-07 22:25:54 -04:00
ToolSetupUtil : : ApplyRenderingConfigurationToPreview ( Preview - > PreviewMesh , nullptr ) ;
2019-09-23 16:41:56 -04:00
CreateLowQualityPreview ( ) ; // update the preview with a low-quality result
2019-09-12 13:55:17 -04:00
Preview - > ConfigureMaterials (
2020-03-19 13:03:45 -04:00
ToolSetupUtil : : GetDefaultSculptMaterial ( GetToolManager ( ) ) ,
2019-09-12 13:55:17 -04:00
ToolSetupUtil : : GetDefaultWorkingMaterial ( GetToolManager ( ) )
) ;
2019-09-23 16:41:56 -04:00
2019-09-12 13:55:17 -04:00
Preview - > InvalidateResult ( ) ; // start compute
2019-09-24 13:12:06 -04:00
2020-03-10 14:00:36 -04:00
2021-02-08 17:02:09 -04:00
SetToolDisplayName ( LOCTEXT ( " ToolName " , " Voxel Merge " ) ) ;
2020-03-10 14:00:36 -04:00
GetToolManager ( ) - > DisplayMessage (
2021-02-08 17:02:09 -04:00
LOCTEXT ( " OnStartTool " , " Combine the input meshes into closed solids using voxelization techniques. UVs, sharp edges, and small/thin features will be lost. Increase Voxel Count to enhance accuracy. " ) ,
2020-03-10 14:00:36 -04:00
EToolMessageLevel : : UserNotification ) ;
2019-09-12 13:55:17 -04:00
}
2022-01-28 18:40:54 -05:00
void UMergeMeshesTool : : OnShutdown ( EToolShutdownType ShutdownType )
2019-09-12 13:55:17 -04:00
{
2020-04-21 23:51:57 -04:00
MergeProps - > SaveProperties ( this ) ;
HandleSourcesProperties - > SaveProperties ( this ) ;
2019-10-02 12:05:44 -04:00
FDynamicMeshOpResult Result = Preview - > Shutdown ( ) ;
2020-04-21 23:51:57 -04:00
// Restore (unhide) the source meshes
2021-03-11 11:40:03 -04:00
for ( int32 ComponentIdx = 0 ; ComponentIdx < Targets . Num ( ) ; ComponentIdx + + )
2020-04-21 23:51:57 -04:00
{
2021-11-23 09:42:40 -05:00
UE : : ToolTarget : : ShowSourceObject ( Targets [ ComponentIdx ] ) ;
2020-04-21 23:51:57 -04:00
}
2019-09-12 13:55:17 -04:00
if ( ShutdownType = = EToolShutdownType : : Accept )
{
2020-08-11 01:36:57 -04:00
GetToolManager ( ) - > BeginUndoTransaction ( LOCTEXT ( " MergeMeshes " , " Merge Meshes " ) ) ;
2019-10-04 16:15:53 -04:00
// Generate the result
2020-08-11 01:36:57 -04:00
GenerateAsset ( Result ) ;
2019-09-20 16:16:09 -04:00
2020-04-21 23:51:57 -04:00
TArray < AActor * > Actors ;
2021-03-11 11:40:03 -04:00
for ( int32 ComponentIdx = 0 ; ComponentIdx < Targets . Num ( ) ; ComponentIdx + + )
2019-09-20 15:16:56 -04:00
{
2021-11-23 09:42:40 -05:00
Actors . Add ( UE : : ToolTarget : : GetTargetActor ( Targets [ ComponentIdx ] ) ) ;
2019-09-20 15:16:56 -04:00
}
2020-04-21 23:51:57 -04:00
HandleSourcesProperties - > ApplyMethod ( Actors , GetToolManager ( ) ) ;
2020-08-11 01:36:57 -04:00
GetToolManager ( ) - > EndUndoTransaction ( ) ;
2019-09-12 13:55:17 -04:00
}
}
2020-04-18 18:42:59 -04:00
void UMergeMeshesTool : : OnTick ( float DeltaTime )
2019-09-12 13:55:17 -04:00
{
Preview - > Tick ( DeltaTime ) ;
}
bool UMergeMeshesTool : : CanAccept ( ) const
{
2021-02-05 16:33:02 -04:00
return Super : : CanAccept ( ) & & Preview - > HaveValidNonEmptyResult ( ) ;
2019-09-12 13:55:17 -04:00
}
2020-01-07 15:54:23 -05:00
void UMergeMeshesTool : : OnPropertyModified ( UObject * PropertySet , FProperty * Property )
2019-09-12 13:55:17 -04:00
{
Preview - > InvalidateResult ( ) ;
}
2019-10-04 14:13:21 -04:00
TUniquePtr < FDynamicMeshOperator > UMergeMeshesTool : : MakeNewOperator ( )
2019-09-12 13:55:17 -04:00
{
2019-10-04 14:13:21 -04:00
TUniquePtr < FVoxelMergeMeshesOp > MergeOp = MakeUnique < FVoxelMergeMeshesOp > ( ) ;
2019-09-13 14:24:58 -04:00
MergeOp - > VoxelCount = MergeProps - > VoxelCount ;
2019-09-24 13:12:06 -04:00
MergeOp - > AdaptivityD = MergeProps - > MeshAdaptivity ;
MergeOp - > IsoSurfaceD = MergeProps - > OffsetDistance ;
2019-09-13 14:24:58 -04:00
MergeOp - > bAutoSimplify = MergeProps - > bAutoSimplify ;
2019-09-12 13:55:17 -04:00
MergeOp - > InputMeshArray = InputMeshes ;
return MergeOp ;
}
void UMergeMeshesTool : : CacheInputMeshes ( )
{
2021-07-15 19:06:07 -04:00
InputMeshes . Reset ( ) ;
2019-09-12 13:55:17 -04:00
// Package the selected meshes and transforms for consumption by the CSGTool
2021-03-11 11:40:03 -04:00
for ( int32 ComponentIdx = 0 ; ComponentIdx < Targets . Num ( ) ; ComponentIdx + + )
2019-09-12 13:55:17 -04:00
{
2021-07-15 19:06:07 -04:00
UE : : Geometry : : FVoxelMergeMeshesOp : : FInputMesh InputMesh ;
2021-11-23 09:42:40 -05:00
InputMesh . Mesh = UE : : ToolTarget : : GetMeshDescription ( Targets [ ComponentIdx ] ) ;
InputMesh . Transform = ( FTransform ) UE : : ToolTarget : : GetLocalToWorldTransform ( Targets [ ComponentIdx ] ) ;
2021-07-15 19:06:07 -04:00
InputMeshes . Add ( InputMesh ) ;
2019-09-12 13:55:17 -04:00
}
}
2019-09-23 16:41:56 -04:00
void UMergeMeshesTool : : CreateLowQualityPreview ( )
{
FProgressCancel NullInterrupter ;
FVoxelMergeMeshesOp MergeMeshesOp ;
MergeMeshesOp . VoxelCount = 12 ;
MergeMeshesOp . AdaptivityD = 0.001 ;
MergeMeshesOp . bAutoSimplify = true ;
MergeMeshesOp . InputMeshArray = InputMeshes ;
MergeMeshesOp . CalculateResult ( & NullInterrupter ) ;
TUniquePtr < FDynamicMesh3 > FastPreviewMesh = MergeMeshesOp . ExtractResult ( ) ;
Preview - > PreviewMesh - > SetTransform ( ( FTransform ) MergeMeshesOp . GetResultTransform ( ) ) ;
Preview - > PreviewMesh - > UpdatePreview ( FastPreviewMesh . Get ( ) ) ; // copies the mesh @todo we could just give ownership to the Preview!
Preview - > SetVisibility ( true ) ;
}
2019-09-12 13:55:17 -04:00
2021-06-02 15:58:00 -04:00
void UMergeMeshesTool : : GenerateAsset ( const FDynamicMeshOpResult & OpResult )
2019-09-12 13:55:17 -04:00
{
2021-06-02 15:58:00 -04:00
check ( OpResult . Mesh . Get ( ) ! = nullptr ) ;
2019-09-20 16:16:09 -04:00
2021-06-02 15:58:00 -04:00
FCreateMeshObjectParams NewMeshObjectParams ;
2022-01-28 10:18:10 -05:00
NewMeshObjectParams . TargetWorld = GetTargetWorld ( ) ;
2021-06-02 15:58:00 -04:00
NewMeshObjectParams . Transform = ( FTransform ) OpResult . Transform ;
NewMeshObjectParams . BaseName = TEXT ( " MergedMesh " ) ;
NewMeshObjectParams . Materials . Add ( ToolSetupUtil : : GetDefaultMaterial ( ) ) ;
NewMeshObjectParams . SetMesh ( OpResult . Mesh . Get ( ) ) ;
FCreateMeshObjectResult Result = UE : : Modeling : : CreateMeshObject ( GetToolManager ( ) , MoveTemp ( NewMeshObjectParams ) ) ;
if ( Result . IsOK ( ) & & Result . NewActor ! = nullptr )
2020-01-27 20:11:15 -05:00
{
2021-06-02 15:58:00 -04:00
ToolSelectionUtil : : SetNewActorSelection ( GetToolManager ( ) , Result . NewActor ) ;
2020-01-27 20:11:15 -05:00
}
2021-06-02 15:58:00 -04:00
2019-09-12 13:55:17 -04:00
}
# undef LOCTEXT_NAMESPACE