Files
UnrealEngineUWP/Engine/Plugins/Runtime/MeshModelingToolset/Source/MeshModelingTools/Private/RecomputeUVsTool.cpp
nathan mitchell a25fa64667 ModelingTools: Fix handling of UV Unwrap tool to correctly take into account user selection for PolyGroup layer. Additionally fixes issue for the UV Unwrap tool in the UV Editor as well as cleaning up tooltip language about the option.
#rb semion.piskarev
#rnx
#jira UE-137942
#preflight 61e53d580c34e9a5ae5f4642

#ROBOMERGE-AUTHOR: nathan.mitchell
#ROBOMERGE-SOURCE: CL 18695310 in //UE5/Release-5.0/... via CL 18695322 via CL 18695346
#ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v903-18687472)

[CL 18695382 by nathan mitchell in ue5-main branch]
2022-01-21 15:43:07 -05:00

249 lines
7.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "RecomputeUVsTool.h"
#include "InteractiveToolManager.h"
#include "ToolBuilderUtil.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "Polygroups/PolygroupUtil.h"
#include "ToolSetupUtil.h"
#include "ModelingToolTargetUtil.h"
#include "ParameterizationOps/RecomputeUVsOp.h"
using namespace UE::Geometry;
#define LOCTEXT_NAMESPACE "URecomputeUVsTool"
/*
* ToolBuilder
*/
USingleSelectionMeshEditingTool* URecomputeUVsToolBuilder::CreateNewTool(const FToolBuilderState& SceneState) const
{
URecomputeUVsTool* NewTool = NewObject<URecomputeUVsTool>(SceneState.ToolManager);
return NewTool;
}
/*
* Tool
*/
void URecomputeUVsTool::Setup()
{
UInteractiveTool::Setup();
InputMesh = MakeShared<FDynamicMesh3, ESPMode::ThreadSafe>();
*InputMesh = UE::ToolTarget::GetDynamicMeshCopy(Target);
FComponentMaterialSet MaterialSet = UE::ToolTarget::GetMaterialSet(Target);
FTransform TargetTransform = (FTransform)UE::ToolTarget::GetLocalToWorldTransform(Target);
// initialize our properties
Settings = NewObject<URecomputeUVsToolProperties>(this);
Settings->RestoreProperties(this);
AddToolPropertySource(Settings);
UVChannelProperties = NewObject<UMeshUVChannelProperties>(this);
UVChannelProperties->RestoreProperties(this);
UVChannelProperties->Initialize(InputMesh.Get(), false);
UVChannelProperties->ValidateSelection(true);
UVChannelProperties->WatchProperty(UVChannelProperties->UVChannel, [this](const FString& NewValue)
{
MaterialSettings->UpdateUVChannels(UVChannelProperties->UVChannelNamesList.IndexOfByKey(UVChannelProperties->UVChannel),
UVChannelProperties->UVChannelNamesList);
});
AddToolPropertySource(UVChannelProperties);
PolygroupLayerProperties = NewObject<UPolygroupLayersProperties>(this);
PolygroupLayerProperties->RestoreProperties(this, TEXT("RecomputeUVsTool"));
PolygroupLayerProperties->InitializeGroupLayers(InputMesh.Get());
PolygroupLayerProperties->WatchProperty(PolygroupLayerProperties->ActiveGroupLayer, [&](FName) { OnSelectedGroupLayerChanged(); });
AddToolPropertySource(PolygroupLayerProperties);
UpdateActiveGroupLayer();
MaterialSettings = NewObject<UExistingMeshMaterialProperties>(this);
MaterialSettings->MaterialMode = ESetMeshMaterialMode::Checkerboard;
MaterialSettings->RestoreProperties(this, TEXT("ModelingUVTools"));
AddToolPropertySource(MaterialSettings);
UE::ToolTarget::HideSourceObject(Target);
// force update
MaterialSettings->UpdateMaterials();
RecomputeUVsOpFactory = NewObject<URecomputeUVsOpFactory>();
RecomputeUVsOpFactory->OriginalMesh = InputMesh;
RecomputeUVsOpFactory->InputGroups = ActiveGroupSet;
RecomputeUVsOpFactory->Settings = Settings;
RecomputeUVsOpFactory->TargetTransform = UE::ToolTarget::GetLocalToWorldTransform(Target);
RecomputeUVsOpFactory->GetSelectedUVChannel = [this]() { return GetSelectedUVChannel(); };
Preview = NewObject<UMeshOpPreviewWithBackgroundCompute>(this);
Preview->Setup(this->TargetWorld, RecomputeUVsOpFactory);
ToolSetupUtil::ApplyRenderingConfigurationToPreview(Preview->PreviewMesh, Target);
Preview->PreviewMesh->SetTangentsMode(EDynamicMeshComponentTangentsMode::AutoCalculated);
Preview->PreviewMesh->ReplaceMesh(*InputMesh);
Preview->ConfigureMaterials(MaterialSet.Materials, ToolSetupUtil::GetDefaultWorkingMaterial(GetToolManager()));
Preview->PreviewMesh->SetTransform(TargetTransform);
Preview->OnMeshUpdated.AddLambda([this](UMeshOpPreviewWithBackgroundCompute* Op)
{
OnPreviewMeshUpdated();
});
Preview->OverrideMaterial = MaterialSettings->GetActiveOverrideMaterial();
if (bCreateUVLayoutViewOnSetup)
{
UVLayoutView = NewObject<UUVLayoutPreview>(this);
UVLayoutView->CreateInWorld(TargetWorld);
UVLayoutView->SetSourceMaterials(MaterialSet);
UVLayoutView->SetSourceWorldPosition(TargetTransform, UE::ToolTarget::GetTargetActor(Target)->GetComponentsBoundingBox());
UVLayoutView->Settings->bEnabled = false;
UVLayoutView->Settings->bShowWireframe = false;
UVLayoutView->Settings->RestoreProperties(this, TEXT("RecomputeUVsTool"));
AddToolPropertySource(UVLayoutView->Settings);
}
Preview->InvalidateResult(); // start compute
SetToolDisplayName(LOCTEXT("ToolNameLocal", "UV Unwrap"));
GetToolManager()->DisplayMessage(
LOCTEXT("OnStartTool_Regions", "Generate UVs for PolyGroups or existing UV islands of the mesh using various strategies."),
EToolMessageLevel::UserNotification);
}
void URecomputeUVsTool::OnPropertyModified(UObject* PropertySet, FProperty* Property)
{
bool bForceMaterialUpdate = false;
if (PropertySet == Settings || PropertySet == UVChannelProperties)
{
// One of the UV generation properties must have changed. Dirty the result to force a recompute
Preview->InvalidateResult();
bForceMaterialUpdate = true;
}
if (PropertySet == MaterialSettings || bForceMaterialUpdate)
{
MaterialSettings->UpdateMaterials();
Preview->OverrideMaterial = MaterialSettings->GetActiveOverrideMaterial();
}
}
void URecomputeUVsTool::Shutdown(EToolShutdownType ShutdownType)
{
if (UVLayoutView)
{
UVLayoutView->Settings->SaveProperties(this, TEXT("RecomputeUVsTool"));
UVLayoutView->Disconnect();
}
UVChannelProperties->SaveProperties(this);
Settings->SaveProperties(this);
PolygroupLayerProperties->RestoreProperties(this, TEXT("RecomputeUVsTool"));
MaterialSettings->SaveProperties(this, TEXT("ModelingUVTools"));
UE::ToolTarget::ShowSourceObject(Target);
FDynamicMeshOpResult Result = Preview->Shutdown();
if (ShutdownType == EToolShutdownType::Accept)
{
GetToolManager()->BeginUndoTransaction(LOCTEXT("RecomputeUVs", "Recompute UVs"));
FDynamicMesh3* NewDynamicMesh = Result.Mesh.Get();
if (ensure(NewDynamicMesh))
{
UE::ToolTarget::CommitDynamicMeshUVUpdate(Target, NewDynamicMesh);
}
GetToolManager()->EndUndoTransaction();
}
if (RecomputeUVsOpFactory)
{
RecomputeUVsOpFactory = nullptr;
}
}
void URecomputeUVsTool::Render(IToolsContextRenderAPI* RenderAPI)
{
if (UVLayoutView)
{
UVLayoutView->Render(RenderAPI);
}
}
void URecomputeUVsTool::OnTick(float DeltaTime)
{
Preview->Tick(DeltaTime);
if (UVLayoutView)
{
UVLayoutView->OnTick(DeltaTime);
}
}
bool URecomputeUVsTool::CanAccept() const
{
return Super::CanAccept() && Preview->HaveValidResult();
}
int32 URecomputeUVsTool::GetSelectedUVChannel() const
{
return UVChannelProperties ? UVChannelProperties->GetSelectedChannelIndex(true) : 0;
}
void URecomputeUVsTool::OnSelectedGroupLayerChanged()
{
UpdateActiveGroupLayer();
Preview->InvalidateResult();
}
void URecomputeUVsTool::UpdateActiveGroupLayer()
{
if (PolygroupLayerProperties->HasSelectedPolygroup() == false)
{
ActiveGroupSet = MakeShared<UE::Geometry::FPolygroupSet, ESPMode::ThreadSafe>(InputMesh.Get());
}
else
{
FName SelectedName = PolygroupLayerProperties->ActiveGroupLayer;
FDynamicMeshPolygroupAttribute* FoundAttrib = UE::Geometry::FindPolygroupLayerByName(*InputMesh, SelectedName);
ensureMsgf(FoundAttrib, TEXT("Selected Attribute Not Found! Falling back to Default group layer."));
ActiveGroupSet = MakeShared<UE::Geometry::FPolygroupSet, ESPMode::ThreadSafe>(InputMesh.Get(), FoundAttrib);
}
if (RecomputeUVsOpFactory)
{
RecomputeUVsOpFactory->InputGroups = ActiveGroupSet;
}
}
void URecomputeUVsTool::OnPreviewMeshUpdated()
{
if (UVLayoutView)
{
int32 UVChannel = UVChannelProperties ? UVChannelProperties->GetSelectedChannelIndex(true) : 0;
Preview->PreviewMesh->ProcessMesh([&](const FDynamicMesh3& NewMesh)
{
UVLayoutView->UpdateUVMesh(&NewMesh, UVChannel);
});
}
if (MaterialSettings)
{
MaterialSettings->UpdateMaterials();
}
}
#undef LOCTEXT_NAMESPACE