// Copyright Epic Games, Inc. All Rights Reserved. #include "ParameterizeMeshTool.h" #include "InteractiveToolManager.h" #include "ToolBuilderUtil.h" #include "ToolSetupUtil.h" #include "ModelingToolTargetUtil.h" #include "DynamicMesh/DynamicMesh3.h" #include "FaceGroupUtil.h" #include "ParameterizationOps/ParameterizeMeshOp.h" #include "ExplicitUseGeometryMathTypes.h" // using UE::Geometry::(math types) using namespace UE::Geometry; #define LOCTEXT_NAMESPACE "UParameterizeMeshTool" /* * ToolBuilder */ USingleSelectionMeshEditingTool* UParameterizeMeshToolBuilder::CreateNewTool(const FToolBuilderState& SceneState) const { UParameterizeMeshTool* NewTool = NewObject(SceneState.ToolManager); return NewTool; } /* * Tool */ void UParameterizeMeshTool::Setup() { UInteractiveTool::Setup(); InputMesh = MakeShared(); *InputMesh = UE::ToolTarget::GetDynamicMeshCopy(Target); Preview = NewObject(this); Preview->Setup(this->TargetWorld, this); Preview->PreviewMesh->SetTangentsMode(EDynamicMeshComponentTangentsMode::AutoCalculated); Preview->PreviewMesh->ReplaceMesh(*InputMesh); Preview->ConfigureMaterials(UE::ToolTarget::GetMaterialSet(Target).Materials, ToolSetupUtil::GetDefaultWorkingMaterial(GetToolManager())); Preview->PreviewMesh->SetTransform((FTransform)UE::ToolTarget::GetLocalToWorldTransform(Target)); Preview->OnMeshUpdated.AddLambda([this](UMeshOpPreviewWithBackgroundCompute* Op) { MaterialSettings->UpdateMaterials(); }); UE::ToolTarget::HideSourceObject(Target); // initialize our properties UVChannelProperties = NewObject(this); UVChannelProperties->RestoreProperties(this); UVChannelProperties->Initialize(InputMesh.Get(), false); UVChannelProperties->ValidateSelection(true); UVChannelProperties->WatchProperty(UVChannelProperties->UVChannel, [this](const FString& NewValue) { MaterialSettings->UVChannel = UVChannelProperties->GetSelectedChannelIndex(true); }); AddToolPropertySource(UVChannelProperties); Settings = NewObject(this); Settings->RestoreProperties(this); AddToolPropertySource(Settings); Settings->WatchProperty(Settings->Method, [&](EParameterizeMeshUVMethod) { OnMethodTypeChanged(); }); UVAtlasProperties = NewObject(this); UVAtlasProperties->RestoreProperties(this); AddToolPropertySource(UVAtlasProperties); SetToolPropertySourceEnabled(UVAtlasProperties, false); XAtlasProperties = NewObject(this); XAtlasProperties->RestoreProperties(this); AddToolPropertySource(XAtlasProperties); SetToolPropertySourceEnabled(XAtlasProperties, false); MaterialSettings = NewObject(this); MaterialSettings->MaterialMode = ESetMeshMaterialMode::Checkerboard; MaterialSettings->RestoreProperties(this, TEXT("ModelingUVTools")); AddToolPropertySource(MaterialSettings); // force update MaterialSettings->UpdateMaterials(); Preview->OverrideMaterial = MaterialSettings->GetActiveOverrideMaterial(); Preview->InvalidateResult(); // start compute SetToolDisplayName(LOCTEXT("ToolNameGlobal", "AutoUV")); GetToolManager()->DisplayMessage( LOCTEXT("OnStartTool_Global", "Automatically partition the selected Mesh into UV islands, flatten, and pack into a single UV chart"), EToolMessageLevel::UserNotification); } void UParameterizeMeshTool::OnPropertyModified(UObject* PropertySet, FProperty* Property) { if (PropertySet != MaterialSettings) { Preview->InvalidateResult(); } MaterialSettings->UpdateMaterials(); Preview->OverrideMaterial = MaterialSettings->GetActiveOverrideMaterial(); } void UParameterizeMeshTool::OnMethodTypeChanged() { SetToolPropertySourceEnabled(UVAtlasProperties, Settings->Method == EParameterizeMeshUVMethod::UVAtlas); SetToolPropertySourceEnabled(XAtlasProperties, Settings->Method == EParameterizeMeshUVMethod::XAtlas); Preview->InvalidateResult(); } void UParameterizeMeshTool::Shutdown(EToolShutdownType ShutdownType) { UVChannelProperties->SaveProperties(this); Settings->SaveProperties(this); MaterialSettings->SaveProperties(this, TEXT("ModelingUVTools")); FDynamicMeshOpResult Result = Preview->Shutdown(); // Restore (unhide) the source meshes UE::ToolTarget::ShowSourceObject(Target); if (ShutdownType == EToolShutdownType::Accept) { GetToolManager()->BeginUndoTransaction(LOCTEXT("ParameterizeMesh", "Auto UVs")); FDynamicMesh3* NewDynamicMesh = Result.Mesh.Get(); if (ensure(NewDynamicMesh)) { UE::ToolTarget::CommitDynamicMeshUVUpdate(Target, NewDynamicMesh); } GetToolManager()->EndUndoTransaction(); } } void UParameterizeMeshTool::OnTick(float DeltaTime) { Preview->Tick(DeltaTime); } bool UParameterizeMeshTool::CanAccept() const { return Super::CanAccept() && Preview->HaveValidResult(); } TUniquePtr UParameterizeMeshTool::MakeNewOperator() { FAxisAlignedBox3d MeshBounds = Preview->PreviewMesh->GetMesh()->GetBounds(); TUniquePtr ParameterizeMeshOp = MakeUnique(); ParameterizeMeshOp->InputMesh = InputMesh; ParameterizeMeshOp->UVLayer = UVChannelProperties->GetSelectedChannelIndex(true); ParameterizeMeshOp->Method = (EParamOpBackend)(int)Settings->Method; // uvatlas options ParameterizeMeshOp->Stretch = UVAtlasProperties->ChartStretch; ParameterizeMeshOp->NumCharts = UVAtlasProperties->NumCharts; // xatlas options ParameterizeMeshOp->XAtlasMaxIterations = XAtlasProperties->MaxIterations; ParameterizeMeshOp->SetTransform(UE::ToolTarget::GetLocalToWorldTransform(Target)); return ParameterizeMeshOp; } #undef LOCTEXT_NAMESPACE