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"
2019-09-12 13:55:17 -04:00
# include "Selection/ToolSelectionUtil.h"
2021-06-13 00:35:22 -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
# include "ExplicitUseGeometryMathTypes.h" // using UE::Geometry::(math types)
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
{
2019-10-04 15:16:18 -04:00
const 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
}
UInteractiveTool * UMergeMeshesToolBuilder : : BuildTool ( const FToolBuilderState & SceneState ) const
{
UMergeMeshesTool * NewTool = NewObject < UMergeMeshesTool > ( SceneState . ToolManager ) ;
2021-03-11 11:40:03 -04:00
TArray < TObjectPtr < UToolTarget > > Targets = SceneState . TargetManager - > BuildAllSelectedTargetable ( SceneState , GetTargetRequirements ( ) ) ;
NewTool - > SetTargets ( MoveTemp ( Targets ) ) ;
2019-09-12 13:55:17 -04:00
NewTool - > SetWorld ( SceneState . World ) ;
return NewTool ;
}
/*
* Tool
*/
UMergeMeshesTool : : UMergeMeshesTool ( )
{
}
void UMergeMeshesTool : : SetWorld ( UWorld * World )
{
this - > TargetWorld = World ;
}
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-03-11 11:40:03 -04:00
TargetComponentInterface ( ComponentIdx ) - > SetOwnerVisibility ( false ) ;
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 " ) ;
Preview - > Setup ( this - > TargetWorld , 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
} ) ;
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
}
void UMergeMeshesTool : : Shutdown ( EToolShutdownType ShutdownType )
{
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-03-11 11:40:03 -04:00
TargetComponentInterface ( ComponentIdx ) - > SetOwnerVisibility ( true ) ;
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-03-11 11:40:03 -04:00
Actors . Add ( TargetComponentInterface ( ComponentIdx ) - > GetOwnerActor ( ) ) ;
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 ( )
{
InputMeshes = MakeShared < TArray < IVoxelBasedCSG : : FPlacedMesh > > ( ) ;
// 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
{
IVoxelBasedCSG : : FPlacedMesh PlacedMesh ;
2021-03-11 11:40:03 -04:00
PlacedMesh . Mesh = TargetMeshProviderInterface ( ComponentIdx ) - > GetMeshDescription ( ) ;
PlacedMesh . Transform = TargetComponentInterface ( ComponentIdx ) - > GetWorldTransform ( ) ;
2019-09-12 13:55:17 -04:00
InputMeshes - > Add ( PlacedMesh ) ;
}
}
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 ;
NewMeshObjectParams . TargetWorld = TargetWorld ;
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