Files

402 lines
13 KiB
C++
Raw Permalink Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CutMeshWithMeshTool.h"
#include "CompositionOps/BooleanMeshesOp.h"
#include "ToolSetupUtil.h"
Gizmos: refactor Modeling Mode gizmo creation out of InteractiveGizmoManager. Editor will use other "default" transform gizmo implementations, and so the UTransformGizmo creation helper functions do not belong in GizmoManager. Instead a UTransformGizmoContextObject now provides this functionality. ModelingToolsEditorMode (and any other modes/systems that want to use these gizmo convenience functions) creates an instance of UTransformGizmoContextObject and registers it with the ContextObjectStore. Calling code can spawn a new UTransformGizmo by looking this object up in the ContextStore and calling it's helper functions. Static versions of the helper functions in the UE::TransformGizmoUtil:: namespace provide a single-line interface that replaces the previous GizmoManager call sites in the MeshModelingTools library. IntervalGizmo is now just registered and unregistered as needed by the MeshSpaceDeformerTool, as this is the only place it is currently used. Previous implementation in InteractiveGizmoManager is left intact as there are a few uses outside of MeshModelingTools that need to be cleaned up before it can be deleted. UTransformGizmo now requires it's Builder to tell it which sub-gizmo identifier strings to pass to the GizmoManager to create axis/plane/rotation sub-gizmos (and the code that registers the Builder must then provide these strings). This cleans up previous explicit references to UInteractiveGizmoManager static strings from UTransformGizmo. #rb Christina.TempelaarL, david.hill #rnx #jira none [CL 16409673 by Ryan Schmidt in ue5-main branch]
2021-05-20 16:39:39 -04:00
#include "BaseGizmos/TransformGizmoUtil.h"
#include "Selection/ToolSelectionUtil.h"
#include "ModelingObjectsCreationAPI.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "DynamicMesh/MeshTransforms.h"
#include "MeshDescriptionToDynamicMesh.h"
#include "DynamicMeshToMeshDescription.h"
#include "Async/Async.h"
#include "TargetInterfaces/MaterialProvider.h"
#include "TargetInterfaces/MeshDescriptionCommitter.h"
#include "TargetInterfaces/MeshDescriptionProvider.h"
#include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
#include "TargetInterfaces/AssetBackedTarget.h"
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs. - Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module - move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module - Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options - Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs - Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget - Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation - Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate(). - Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets - Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high). - DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop #rb none #rnx #jira none #preflight 60ba50632c42ea0001cb54c5 [CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
#include "ModelingToolTargetUtil.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(CutMeshWithMeshTool)
using namespace UE::Geometry;
namespace
{
// probably should be something defined for the whole tool framework...
#if WITH_EDITOR
static EAsyncExecution CutMeshWithMeshToolAsyncExecTarget = EAsyncExecution::LargeThreadPool;
#else
static EAsyncExecution CutMeshWithMeshToolAsyncExecTarget = EAsyncExecution::ThreadPool;
#endif
}
#define LOCTEXT_NAMESPACE "UCutMeshWithMeshTool"
void UCutMeshWithMeshTool::SetupProperties()
{
Super::SetupProperties();
CutProperties = NewObject<UCutMeshWithMeshToolProperties>(this);
CutProperties->RestoreProperties(this);
AddToolPropertySource(CutProperties);
SetToolDisplayName(LOCTEXT("CutMeshWithMeshToolName", "Cut With Mesh"));
GetToolManager()->DisplayMessage(
LOCTEXT("OnStartTool", "Cut the first input mesh with the second input mesh. Use the transform gizmos to modify the position and orientation of the input objects."),
EToolMessageLevel::UserNotification);
// create intersection preview mesh object
IntersectPreviewMesh = NewObject<UPreviewMesh>(this);
IntersectPreviewMesh->CreateInWorld(GetTargetWorld(), FTransform::Identity);
ToolSetupUtil::ApplyRenderingConfigurationToPreview(IntersectPreviewMesh, nullptr);
IntersectPreviewMesh->SetVisible(true);
IntersectPreviewMesh->SetMaterial(ToolSetupUtil::GetDefaultBrushVolumeMaterial(GetToolManager()));
}
void UCutMeshWithMeshTool::SaveProperties()
{
Super::SaveProperties();
CutProperties->SaveProperties(this);
IntersectPreviewMesh->Disconnect();
}
void UCutMeshWithMeshTool::ConvertInputsAndSetPreviewMaterials(bool bSetPreviewMesh)
{
// disable output options
// (this property set is not registered yet in SetupProperties() above)
SetToolPropertySourceEnabled(HandleSourcesProperties, false);
SetToolPropertySourceEnabled(OutputTypeProperties, false);
FComponentMaterialSet AllMaterialSet;
TArray<TArray<int>> MaterialRemap; MaterialRemap.SetNum(Targets.Num());
if (!CutProperties->bUseFirstMeshMaterials)
{
TMap<UMaterialInterface*, int> KnownMaterials;
for (int ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
{
const FComponentMaterialSet ComponentMaterialSet = UE::ToolTarget::GetMaterialSet(Targets[ComponentIdx]);
for (UMaterialInterface* Mat : ComponentMaterialSet.Materials)
{
int* FoundMatIdx = KnownMaterials.Find(Mat);
int MatIdx;
if (FoundMatIdx)
{
MatIdx = *FoundMatIdx;
}
else
{
MatIdx = AllMaterialSet.Materials.Add(Mat);
KnownMaterials.Add(Mat, MatIdx);
}
MaterialRemap[ComponentIdx].Add(MatIdx);
}
}
}
else
{
AllMaterialSet = UE::ToolTarget::GetMaterialSet(Targets[0]);
for (int MatIdx = 0; MatIdx < AllMaterialSet.Materials.Num(); MatIdx++)
{
MaterialRemap[0].Add(MatIdx);
}
for (int ComponentIdx = 1; ComponentIdx < Targets.Num(); ComponentIdx++)
{
MaterialRemap[ComponentIdx].Init(0, Cast<IMaterialProvider>(Targets[ComponentIdx])->GetNumMaterials());
}
}
for (int ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
{
TSharedPtr<FDynamicMesh3, ESPMode::ThreadSafe> Mesh = MakeShared<FDynamicMesh3, ESPMode::ThreadSafe>();
FMeshDescriptionToDynamicMesh Converter;
Converter.Convert(UE::ToolTarget::GetMeshDescription(Targets[ComponentIdx]), *Mesh);
// ensure materials and attributes are always enabled
Mesh->EnableAttributes();
Mesh->Attributes()->EnableMaterialID();
FDynamicMeshMaterialAttribute* MaterialIDs = Mesh->Attributes()->GetMaterialID();
for (int TID : Mesh->TriangleIndicesItr())
{
MaterialIDs->SetValue(TID, MaterialRemap[ComponentIdx][MaterialIDs->GetValue(TID)]);
}
if (ComponentIdx == 0)
{
OriginalTargetMesh = Mesh;
}
else
{
OriginalCuttingMesh = Mesh;
}
}
Preview->ConfigureMaterials(AllMaterialSet.Materials, ToolSetupUtil::GetDefaultWorkingMaterial(GetToolManager()));
// check if we have the same mesh on both inputs
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs. - Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module - move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module - Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options - Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs - Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget - Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation - Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate(). - Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets - Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high). - DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop #rb none #rnx #jira none #preflight 60ba50632c42ea0001cb54c5 [CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
if (Cast<IAssetBackedTarget>(Targets[0]) != nullptr && Cast<IAssetBackedTarget>(Targets[0])->HasSameSourceData(Targets[1]))
{
GetToolManager()->DisplayMessage(
LOCTEXT("SameSourceError", "WARNING: Both input meshes have the same Asset; both inputs will be affected."),
EToolMessageLevel::UserWarning);
}
}
class FCutMeshWithMeshOp : public FDynamicMeshOperator
{
public:
virtual ~FCutMeshWithMeshOp() {}
TSharedPtr<const FDynamicMesh3, ESPMode::ThreadSafe> TargetMesh;
FTransform TargetMeshTransform;
TSharedPtr<const FDynamicMesh3, ESPMode::ThreadSafe> CuttingMesh;
FTransform CuttingMeshTransform;
bool bAttemptToFixHoles = true;
bool bCollapseExtraEdges = true;
double WindingThreshold = 0.5;
virtual void CalculateResult(FProgressCancel* Progress) override
{
TUniquePtr<FBooleanMeshesOp> SubtractOp = MakeUnique<FBooleanMeshesOp>();
SubtractOp->CSGOperation = ECSGOperation::DifferenceAB;
SubtractOp->bAttemptFixHoles = bAttemptToFixHoles;
SubtractOp->bTryCollapseExtraEdges = bCollapseExtraEdges;
SubtractOp->WindingThreshold = WindingThreshold;
SubtractOp->Meshes.Add(TargetMesh);
SubtractOp->Transforms.Add(TargetMeshTransform);
SubtractOp->Meshes.Add(CuttingMesh);
SubtractOp->Transforms.Add(CuttingMeshTransform);
TUniquePtr<FBooleanMeshesOp> IntersectOp = MakeUnique<FBooleanMeshesOp>();
IntersectOp->CSGOperation = ECSGOperation::Intersect;
IntersectOp->bAttemptFixHoles = bAttemptToFixHoles;
IntersectOp->bTryCollapseExtraEdges = bCollapseExtraEdges;
IntersectOp->WindingThreshold = WindingThreshold;
IntersectOp->Meshes.Add(TargetMesh);
IntersectOp->Transforms.Add(TargetMeshTransform);
IntersectOp->Meshes.Add(CuttingMesh);
IntersectOp->Transforms.Add(CuttingMeshTransform);
TFuture<void> SubtractFuture = Async(CutMeshWithMeshToolAsyncExecTarget, [&]()
{
SubtractOp->CalculateResult(Progress);
});
TFuture<void> IntersectFuture = Async(CutMeshWithMeshToolAsyncExecTarget, [&]()
{
IntersectOp->CalculateResult(Progress);
});
SubtractFuture.Wait();
IntersectFuture.Wait();
this->ResultMesh = SubtractOp->ExtractResult();
SetResultTransform(SubtractOp->GetResultTransform());
IntersectMesh = IntersectOp->ExtractResult();
CreatedSubtractBoundaryEdges = SubtractOp->GetCreatedBoundaryEdges();
CreatedIntersectBoundaryEdges = IntersectOp->GetCreatedBoundaryEdges();
}
TUniquePtr<FDynamicMesh3> IntersectMesh;
TArray<int> CreatedSubtractBoundaryEdges;
TArray<int> CreatedIntersectBoundaryEdges;
};
void UCutMeshWithMeshTool::SetPreviewCallbacks()
{
DrawnLineSet = NewObject<ULineSetComponent>(Preview->PreviewMesh->GetRootComponent());
DrawnLineSet->SetupAttachment(Preview->PreviewMesh->GetRootComponent());
DrawnLineSet->SetLineMaterial(ToolSetupUtil::GetDefaultLineComponentMaterial(GetToolManager()));
DrawnLineSet->RegisterComponent();
Preview->OnOpCompleted.AddLambda(
[this](const FDynamicMeshOperator* Op)
{
const FCutMeshWithMeshOp* CuttingOp = (const FCutMeshWithMeshOp*)(Op);
CreatedSubtractBoundaryEdges = CuttingOp->CreatedSubtractBoundaryEdges;
CreatedIntersectBoundaryEdges = CuttingOp->CreatedIntersectBoundaryEdges;
IntersectionMesh = *CuttingOp->IntersectMesh; // cannot steal this here because it is const...
IntersectPreviewMesh->UpdatePreview(&IntersectionMesh);
IntersectPreviewMesh->SetTransform((FTransform)Op->GetResultTransform());
}
);
Preview->OnMeshUpdated.AddLambda(
[this](const UMeshOpPreviewWithBackgroundCompute*)
{
GetToolManager()->PostInvalidation();
UpdateVisualization();
}
);
}
void UCutMeshWithMeshTool::UpdateVisualization()
{
constexpr FColor BoundaryEdgeColor(240, 15, 15);
constexpr float BoundaryEdgeThickness = 2.0;
constexpr float BoundaryEdgeDepthBias = 2.0f;
DrawnLineSet->Clear();
if (CutProperties->bShowNewBoundaries)
{
const FDynamicMesh3* TargetMesh = Preview->PreviewMesh->GetPreviewDynamicMesh();
FVector3d A, B;
for (int EID : CreatedSubtractBoundaryEdges)
{
TargetMesh->GetEdgeV(EID, A, B);
DrawnLineSet->AddLine((FVector)A, (FVector)B, BoundaryEdgeColor, BoundaryEdgeThickness, BoundaryEdgeDepthBias);
}
for (int EID : CreatedIntersectBoundaryEdges)
{
IntersectionMesh.GetEdgeV(EID, A, B);
DrawnLineSet->AddLine((FVector)A, (FVector)B, BoundaryEdgeColor, BoundaryEdgeThickness, BoundaryEdgeDepthBias);
}
}
}
TUniquePtr<FDynamicMeshOperator> UCutMeshWithMeshTool::MakeNewOperator()
{
TUniquePtr<FCutMeshWithMeshOp> CuttingOp = MakeUnique<FCutMeshWithMeshOp>();
CuttingOp->TargetMesh = OriginalTargetMesh;
CuttingOp->TargetMeshTransform = TransformProxies[0]->GetTransform();
CuttingOp->CuttingMesh = OriginalCuttingMesh;
CuttingOp->CuttingMeshTransform = TransformProxies[1]->GetTransform();
CuttingOp->bAttemptToFixHoles = CutProperties->bTryFixHoles;
CuttingOp->bCollapseExtraEdges = CutProperties->bTryCollapseEdges;
CuttingOp->WindingThreshold = CutProperties->WindingThreshold;
return CuttingOp;
}
void UCutMeshWithMeshTool::OnPropertyModified(UObject* PropertySet, FProperty* Property)
{
if (Property && (Property->GetFName() == GET_MEMBER_NAME_CHECKED(UCutMeshWithMeshToolProperties, bUseFirstMeshMaterials)))
{
if (!AreAllTargetsValid())
{
GetToolManager()->DisplayMessage(LOCTEXT("InvalidTargets", "Input meshes are no longer valid"), EToolMessageLevel::UserWarning);
return;
}
ConvertInputsAndSetPreviewMaterials(false);
Preview->InvalidateResult();
}
else if (Property && (Property->GetFName() == GET_MEMBER_NAME_CHECKED(UCutMeshWithMeshToolProperties, bShowNewBoundaries)))
{
GetToolManager()->PostInvalidation();
UpdateVisualization();
}
else
{
Super::OnPropertyModified(PropertySet, Property);
}
}
FString UCutMeshWithMeshTool::GetCreatedAssetName() const
{
return TEXT("Boolean");
}
FText UCutMeshWithMeshTool::GetActionName() const
{
return LOCTEXT("CutMeshWithMeshActionName", "Cut Mesh");
}
void UCutMeshWithMeshTool::OnShutdown(EToolShutdownType ShutdownType)
{
SaveProperties();
HandleSourcesProperties->SaveProperties(this);
TransformProperties->SaveProperties(this);
FDynamicMeshOpResult OpResult = Preview->Shutdown();
// Restore (unhide) the source meshes
for ( int32 ci = 0; ci < Targets.Num(); ++ci)
{
UE::ToolTarget::ShowSourceObject(Targets[ci]);
}
if (ShutdownType == EToolShutdownType::Accept)
{
GetToolManager()->BeginUndoTransaction(GetActionName());
TArray<AActor*> SelectActors;
FComponentMaterialSet MaterialSet;
MaterialSet.Materials = GetOutputMaterials();
// update subtract asset
FTransform3d TargetToWorld = UE::ToolTarget::GetLocalToWorldTransform(Targets[0]);
{
if (OpResult.Mesh->TriangleCount() > 0)
{
MeshTransforms::ApplyTransform(*OpResult.Mesh, OpResult.Transform, true);
MeshTransforms::ApplyTransformInverse(*OpResult.Mesh, TargetToWorld, true);
ModelingTools: Reduce surface area of MeshDescriptionProvider/Committer, replace with UE::ToolTarget:: calls where possible. Add new UE::ToolTarget::CommitMeshDescriptionUpdateViaDynamicMesh() function. This is being used for now to avoid potential regressions as UE::ToolTarget::CommitDynamicMeshUpdate will preferentially use DynamicMeshCommitter, and I am not certain it is functionally equivalent in all cases. Add new UE::ToolTarget::CommitDynamicMeshNormalsUpdate(), similar to existing UV version Add new Move-variant of UE::ToolTarget::CommitMeshDescriptionUpdate(), uses new Move-variant of IMeshDescriptionCommitter::CommitMeshDescription. Make existing IMeshDescriptionCommitter::CommitMeshDescription callback interface protected, to prevent usage of this function at public API level (will be removed in future). Tool updates should not change, just using cleaner APIs. EditNormalsTool now uses CommitDynamicMeshNormalsUpdate(), which does go via DynamicMeshCommitter preferentially, where it previously went via MeshDescriptionCommitter. In light testing the results appear equivalent. AttributeEditorTool now operates on MeshDescription copies in various update functions. These are not performance-critical. #rb rinat.abdrashitov #rnx #preflight 61ae45998358693a22c28d1b #ROBOMERGE-AUTHOR: ryan.schmidt #ROBOMERGE-SOURCE: CL 18384350 in //UE5/Release-5.0/... via CL 18384361 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18384373 by ryan schmidt in ue5-release-engine-test branch]
2021-12-06 12:42:19 -05:00
UE::ToolTarget::CommitMeshDescriptionUpdateViaDynamicMesh(Targets[0], *OpResult.Mesh, true);
Cast<IMaterialProvider>(Targets[0])->CommitMaterialSetUpdate(MaterialSet, true);
}
}
SelectActors.Add(UE::ToolTarget::GetTargetActor(Targets[0]));
// create intersection asset
if ( IntersectionMesh.TriangleCount() > 0)
{
MeshTransforms::ApplyTransform(IntersectionMesh, OpResult.Transform, true);
MeshTransforms::ApplyTransformInverse(IntersectionMesh, TargetToWorld, true);
FTransform3d NewTransform = TargetToWorld;
FString CurName = UE::Modeling::GetComponentAssetBaseName(UE::ToolTarget::GetTargetComponent(Targets[0]));
FString UseBaseName = FString::Printf(TEXT("%s_%s"), *CurName, TEXT("CutPart") );
FCreateMeshObjectParams NewMeshObjectParams;
NewMeshObjectParams.TargetWorld = GetTargetWorld();
NewMeshObjectParams.Transform = (FTransform)NewTransform;
NewMeshObjectParams.BaseName = UseBaseName;
NewMeshObjectParams.Materials = GetOutputMaterials();
NewMeshObjectParams.SetMesh(&IntersectionMesh);
// note: CutMeshWithMeshTool does not support converting types currently
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs. - Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module - move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module - Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options - Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs - Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget - Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation - Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate(). - Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets - Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high). - DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop #rb none #rnx #jira none #preflight 60ba50632c42ea0001cb54c5 [CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
UE::ToolTarget::ConfigureCreateMeshObjectParams(Targets[0], NewMeshObjectParams);
FCreateMeshObjectResult Result = UE::Modeling::CreateMeshObject(GetToolManager(), MoveTemp(NewMeshObjectParams));
if (Result.IsOK() && Result.NewActor != nullptr)
{
SelectActors.Add(Result.NewActor);
}
}
ToolSelectionUtil::SetNewActorSelection(GetToolManager(), SelectActors);
GetToolManager()->EndUndoTransaction();
}
UInteractiveGizmoManager* GizmoManager = GetToolManager()->GetPairedGizmoManager();
GizmoManager->DestroyAllGizmosByOwner(this);
}
#undef LOCTEXT_NAMESPACE