2020-01-08 17:11:23 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-12-19 18:07:47 -05:00
|
|
|
|
|
|
|
|
#include "UVLayoutTool.h"
|
|
|
|
|
#include "InteractiveToolManager.h"
|
|
|
|
|
#include "ToolBuilderUtil.h"
|
|
|
|
|
|
|
|
|
|
#include "ToolSetupUtil.h"
|
2021-11-23 09:42:40 -05:00
|
|
|
#include "ModelingToolTargetUtil.h"
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-06-13 00:36:02 -04:00
|
|
|
#include "DynamicMesh/DynamicMesh3.h"
|
2019-12-19 18:07:47 -05:00
|
|
|
|
|
|
|
|
#include "MeshDescriptionToDynamicMesh.h"
|
|
|
|
|
#include "DynamicMeshToMeshDescription.h"
|
|
|
|
|
|
|
|
|
|
#include "ParameterizationOps/UVLayoutOp.h"
|
2021-08-10 17:24:50 -04:00
|
|
|
#include "Properties/UVLayoutProperties.h"
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-12-06 12:42:19 -05:00
|
|
|
#include "ModelingToolTargetUtil.h"
|
2022-12-15 18:17:12 -05:00
|
|
|
#include "ToolTargetManager.h"
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
|
2022-09-28 01:06:15 -04:00
|
|
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(UVLayoutTool)
|
|
|
|
|
|
2021-03-09 19:33:56 -04:00
|
|
|
using namespace UE::Geometry;
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-03-09 19:33:56 -04:00
|
|
|
#define LOCTEXT_NAMESPACE "UUVLayoutTool"
|
2019-12-19 18:07:47 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ToolBuilder
|
|
|
|
|
*/
|
|
|
|
|
|
2021-11-23 09:42:40 -05:00
|
|
|
UMultiSelectionMeshEditingTool* UUVLayoutToolBuilder::CreateNewTool(const FToolBuilderState& SceneState) const
|
2021-03-11 11:40:03 -04:00
|
|
|
{
|
2021-11-23 09:42:40 -05:00
|
|
|
return NewObject<UUVLayoutTool>(SceneState.ToolManager);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
2022-12-15 18:17:12 -05:00
|
|
|
bool UUVLayoutToolBuilder::CanBuildTool(const FToolBuilderState& SceneState) const
|
|
|
|
|
{
|
|
|
|
|
return UMultiSelectionMeshEditingToolBuilder::CanBuildTool(SceneState) &&
|
|
|
|
|
SceneState.TargetManager->CountSelectedAndTargetableWithPredicate(SceneState, GetTargetRequirements(),
|
|
|
|
|
[](UActorComponent& Component) { return ToolBuilderUtil::ComponentTypeCouldHaveUVs(Component); }) > 0;
|
|
|
|
|
}
|
2019-12-19 18:07:47 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tool
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
UUVLayoutTool::UUVLayoutTool()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UUVLayoutTool::Setup()
|
|
|
|
|
{
|
|
|
|
|
UInteractiveTool::Setup();
|
|
|
|
|
|
|
|
|
|
// hide input StaticMeshComponent
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2021-11-23 09:42:40 -05:00
|
|
|
UE::ToolTarget::HideSourceObject(Targets[ComponentIdx]);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 13:26:23 -04:00
|
|
|
// if we only have one object, add ability to set UV channel
|
2021-03-11 11:40:03 -04:00
|
|
|
if (Targets.Num() == 1)
|
2021-02-02 13:26:23 -04:00
|
|
|
{
|
|
|
|
|
UVChannelProperties = NewObject<UMeshUVChannelProperties>(this);
|
|
|
|
|
UVChannelProperties->RestoreProperties(this);
|
2021-11-23 09:42:40 -05:00
|
|
|
UVChannelProperties->Initialize(UE::ToolTarget::GetMeshDescription(Targets[0]), false);
|
2021-02-02 13:26:23 -04:00
|
|
|
UVChannelProperties->ValidateSelection(true);
|
|
|
|
|
AddToolPropertySource(UVChannelProperties);
|
|
|
|
|
UVChannelProperties->WatchProperty(UVChannelProperties->UVChannel, [this](const FString& NewValue)
|
|
|
|
|
{
|
2021-11-18 20:41:17 -05:00
|
|
|
MaterialSettings->UpdateUVChannels(UVChannelProperties->UVChannelNamesList.IndexOfByKey(UVChannelProperties->UVChannel),
|
|
|
|
|
UVChannelProperties->UVChannelNamesList);
|
2021-10-25 20:05:28 -04:00
|
|
|
UpdateVisualization();
|
2021-02-02 13:26:23 -04:00
|
|
|
});
|
|
|
|
|
}
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-08-10 17:24:50 -04:00
|
|
|
BasicProperties = NewObject<UUVLayoutProperties>(this);
|
2021-02-02 13:26:23 -04:00
|
|
|
BasicProperties->RestoreProperties(this);
|
2022-10-21 19:03:38 -04:00
|
|
|
BasicProperties->bUDIMCVAREnabled = false;
|
|
|
|
|
BasicProperties->bEnableUDIMLayout = false;
|
2019-12-19 18:07:47 -05:00
|
|
|
AddToolPropertySource(BasicProperties);
|
|
|
|
|
|
|
|
|
|
MaterialSettings = NewObject<UExistingMeshMaterialProperties>(this);
|
2020-01-27 20:11:15 -05:00
|
|
|
MaterialSettings->RestoreProperties(this);
|
2019-12-19 18:07:47 -05:00
|
|
|
AddToolPropertySource(MaterialSettings);
|
|
|
|
|
|
2020-09-01 14:07:48 -04:00
|
|
|
// if we only have one object, add optional UV layout view
|
2021-03-11 11:40:03 -04:00
|
|
|
if (Targets.Num() == 1)
|
2020-09-01 14:07:48 -04:00
|
|
|
{
|
|
|
|
|
UVLayoutView = NewObject<UUVLayoutPreview>(this);
|
2022-01-28 10:18:10 -05:00
|
|
|
UVLayoutView->CreateInWorld(GetTargetWorld());
|
2020-09-01 14:07:48 -04:00
|
|
|
|
2021-11-23 09:42:40 -05:00
|
|
|
const FComponentMaterialSet MaterialSet = UE::ToolTarget::GetMaterialSet(Targets[0]);
|
2020-09-01 14:07:48 -04:00
|
|
|
UVLayoutView->SetSourceMaterials(MaterialSet);
|
|
|
|
|
|
2021-11-23 09:42:40 -05:00
|
|
|
const AActor* Actor = UE::ToolTarget::GetTargetActor(Targets[0]);
|
2020-09-01 14:07:48 -04:00
|
|
|
UVLayoutView->SetSourceWorldPosition(
|
2021-11-23 09:42:40 -05:00
|
|
|
Actor->GetTransform(),
|
|
|
|
|
Actor->GetComponentsBoundingBox());
|
2020-09-01 14:07:48 -04:00
|
|
|
|
|
|
|
|
UVLayoutView->Settings->RestoreProperties(this);
|
|
|
|
|
AddToolPropertySource(UVLayoutView->Settings);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-05 14:27:21 -05:00
|
|
|
UpdateVisualization();
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-02-08 17:02:09 -04:00
|
|
|
SetToolDisplayName(LOCTEXT("ToolName", "UV Layout"));
|
2021-02-02 13:26:23 -04:00
|
|
|
GetToolManager()->DisplayMessage(LOCTEXT("OnStartUVLayoutTool", "Transform/Rotate/Scale existing UV Charts using various strategies"),
|
2020-09-24 00:43:27 -04:00
|
|
|
EToolMessageLevel::UserNotification);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UUVLayoutTool::UpdateNumPreviews()
|
|
|
|
|
{
|
2021-11-18 20:41:17 -05:00
|
|
|
const int32 CurrentNumPreview = Previews.Num();
|
|
|
|
|
const int32 TargetNumPreview = Targets.Num();
|
2019-12-19 18:07:47 -05:00
|
|
|
if (TargetNumPreview < CurrentNumPreview)
|
|
|
|
|
{
|
|
|
|
|
for (int32 PreviewIdx = CurrentNumPreview - 1; PreviewIdx >= TargetNumPreview; PreviewIdx--)
|
|
|
|
|
{
|
|
|
|
|
Previews[PreviewIdx]->Cancel();
|
|
|
|
|
}
|
|
|
|
|
Previews.SetNum(TargetNumPreview);
|
|
|
|
|
OriginalDynamicMeshes.SetNum(TargetNumPreview);
|
2021-11-16 14:43:51 -05:00
|
|
|
Factories.SetNum(TargetNumPreview);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OriginalDynamicMeshes.SetNum(TargetNumPreview);
|
2021-11-16 14:43:51 -05:00
|
|
|
Factories.SetNum(TargetNumPreview);
|
2019-12-19 18:07:47 -05:00
|
|
|
for (int32 PreviewIdx = CurrentNumPreview; PreviewIdx < TargetNumPreview; PreviewIdx++)
|
|
|
|
|
{
|
2021-02-17 11:50:23 -04:00
|
|
|
OriginalDynamicMeshes[PreviewIdx] = MakeShared<FDynamicMesh3, ESPMode::ThreadSafe>();
|
2019-12-19 18:07:47 -05:00
|
|
|
FMeshDescriptionToDynamicMesh Converter;
|
2021-11-23 09:42:40 -05:00
|
|
|
Converter.Convert(UE::ToolTarget::GetMeshDescription(Targets[PreviewIdx]), *OriginalDynamicMeshes[PreviewIdx]);
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-11-16 14:43:51 -05:00
|
|
|
Factories[PreviewIdx]= NewObject<UUVLayoutOperatorFactory>();
|
|
|
|
|
Factories[PreviewIdx]->OriginalMesh = OriginalDynamicMeshes[PreviewIdx];
|
|
|
|
|
Factories[PreviewIdx]->Settings = BasicProperties;
|
2021-11-23 09:42:40 -05:00
|
|
|
Factories[PreviewIdx]->TargetTransform = (FTransform) UE::ToolTarget::GetLocalToWorldTransform(Targets[PreviewIdx]);
|
2021-11-16 14:43:51 -05:00
|
|
|
Factories[PreviewIdx]->GetSelectedUVChannel = [this]() { return GetSelectedUVChannel(); };
|
2021-08-10 17:24:50 -04:00
|
|
|
|
2021-11-16 14:43:51 -05:00
|
|
|
UMeshOpPreviewWithBackgroundCompute* Preview = Previews.Add_GetRef(NewObject<UMeshOpPreviewWithBackgroundCompute>(Factories[PreviewIdx], "Preview"));
|
2022-01-28 10:18:10 -05:00
|
|
|
Preview->Setup(GetTargetWorld(), Factories[PreviewIdx]);
|
2021-10-07 22:25:54 -04:00
|
|
|
ToolSetupUtil::ApplyRenderingConfigurationToPreview(Preview->PreviewMesh, Targets[PreviewIdx]);
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-11-23 09:42:40 -05:00
|
|
|
const FComponentMaterialSet MaterialSet = UE::ToolTarget::GetMaterialSet(Targets[PreviewIdx]);
|
2019-12-19 18:07:47 -05:00
|
|
|
Preview->ConfigureMaterials(MaterialSet.Materials,
|
|
|
|
|
ToolSetupUtil::GetDefaultWorkingMaterial(GetToolManager())
|
|
|
|
|
);
|
2020-01-27 20:11:15 -05:00
|
|
|
Preview->PreviewMesh->UpdatePreview(OriginalDynamicMeshes[PreviewIdx].Get());
|
2021-11-23 09:42:40 -05:00
|
|
|
Preview->PreviewMesh->SetTransform((FTransform) UE::ToolTarget::GetLocalToWorldTransform(Targets[PreviewIdx]));
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2020-09-01 14:07:48 -04:00
|
|
|
Preview->OnMeshUpdated.AddLambda([this](UMeshOpPreviewWithBackgroundCompute* Compute)
|
|
|
|
|
{
|
|
|
|
|
OnPreviewMeshUpdated(Compute);
|
|
|
|
|
});
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
Preview->SetVisibility(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-01-28 18:40:54 -05:00
|
|
|
void UUVLayoutTool::OnShutdown(EToolShutdownType ShutdownType)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2020-09-01 14:07:48 -04:00
|
|
|
if (UVLayoutView)
|
|
|
|
|
{
|
|
|
|
|
UVLayoutView->Settings->SaveProperties(this);
|
|
|
|
|
UVLayoutView->Disconnect();
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-27 20:11:15 -05:00
|
|
|
BasicProperties->SaveProperties(this);
|
|
|
|
|
MaterialSettings->SaveProperties(this);
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
// Restore (unhide) the source meshes
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2021-11-23 09:42:40 -05:00
|
|
|
UE::ToolTarget::ShowSourceObject(Targets[ComponentIdx]);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TArray<FDynamicMeshOpResult> Results;
|
|
|
|
|
for (UMeshOpPreviewWithBackgroundCompute* Preview : Previews)
|
|
|
|
|
{
|
|
|
|
|
Results.Emplace(Preview->Shutdown());
|
|
|
|
|
}
|
|
|
|
|
if (ShutdownType == EToolShutdownType::Accept)
|
|
|
|
|
{
|
|
|
|
|
GenerateAsset(Results);
|
|
|
|
|
}
|
2021-11-16 14:43:51 -05:00
|
|
|
for (int32 TargetIndex = 0; TargetIndex < Targets.Num(); ++TargetIndex)
|
|
|
|
|
{
|
|
|
|
|
Factories[TargetIndex] = nullptr;
|
|
|
|
|
}
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
2021-02-02 13:26:23 -04:00
|
|
|
int32 UUVLayoutTool::GetSelectedUVChannel() const
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
return UVChannelProperties ? UVChannelProperties->GetSelectedChannelIndex(true) : 0;
|
2021-02-02 13:26:23 -04:00
|
|
|
}
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
|
|
|
|
|
void UUVLayoutTool::Render(IToolsContextRenderAPI* RenderAPI)
|
|
|
|
|
{
|
2020-09-01 14:07:48 -04:00
|
|
|
GetToolManager()->GetContextQueriesAPI()->GetCurrentViewState(CameraState);
|
|
|
|
|
|
|
|
|
|
if (UVLayoutView)
|
|
|
|
|
{
|
|
|
|
|
UVLayoutView->Render(RenderAPI);
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-04-18 18:42:59 -04:00
|
|
|
void UUVLayoutTool::OnTick(float DeltaTime)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
|
|
|
|
for (UMeshOpPreviewWithBackgroundCompute* Preview : Previews)
|
|
|
|
|
{
|
|
|
|
|
Preview->Tick(DeltaTime);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-01 14:07:48 -04:00
|
|
|
if (UVLayoutView)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2020-09-01 14:07:48 -04:00
|
|
|
UVLayoutView->OnTick(DeltaTime);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
2020-09-01 14:07:48 -04:00
|
|
|
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
2020-09-01 14:07:48 -04:00
|
|
|
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2020-01-08 13:26:18 -05:00
|
|
|
void UUVLayoutTool::OnPropertyModified(UObject* PropertySet, FProperty* Property)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2021-02-02 13:26:23 -04:00
|
|
|
if (PropertySet == BasicProperties || PropertySet == UVChannelProperties)
|
2020-09-01 14:07:48 -04:00
|
|
|
{
|
|
|
|
|
UpdateNumPreviews();
|
|
|
|
|
for (UMeshOpPreviewWithBackgroundCompute* Preview : Previews)
|
|
|
|
|
{
|
|
|
|
|
Preview->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (PropertySet == MaterialSettings)
|
|
|
|
|
{
|
|
|
|
|
// if we don't know what changed, or we know checker density changed, update checker material
|
2021-12-10 01:51:34 -05:00
|
|
|
UpdatePreviewMaterial();
|
2020-09-01 14:07:48 -04:00
|
|
|
}
|
2020-03-05 14:27:21 -05:00
|
|
|
}
|
|
|
|
|
|
2020-09-01 14:07:48 -04:00
|
|
|
|
|
|
|
|
void UUVLayoutTool::OnPreviewMeshUpdated(UMeshOpPreviewWithBackgroundCompute* Compute)
|
|
|
|
|
{
|
|
|
|
|
if (UVLayoutView)
|
|
|
|
|
{
|
|
|
|
|
FDynamicMesh3 ResultMesh;
|
|
|
|
|
if (Compute->GetCurrentResultCopy(ResultMesh, false) == false)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-02-02 13:26:23 -04:00
|
|
|
UVLayoutView->UpdateUVMesh(&ResultMesh, GetSelectedUVChannel());
|
2020-09-01 14:07:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 01:51:34 -05:00
|
|
|
void UUVLayoutTool::UpdatePreviewMaterial()
|
2020-03-05 14:27:21 -05:00
|
|
|
{
|
2019-12-19 18:07:47 -05:00
|
|
|
MaterialSettings->UpdateMaterials();
|
2020-03-05 14:27:21 -05:00
|
|
|
UpdateNumPreviews();
|
2019-12-19 18:07:47 -05:00
|
|
|
for (int PreviewIdx = 0; PreviewIdx < Previews.Num(); PreviewIdx++)
|
|
|
|
|
{
|
|
|
|
|
UMeshOpPreviewWithBackgroundCompute* Preview = Previews[PreviewIdx];
|
|
|
|
|
Preview->OverrideMaterial = MaterialSettings->GetActiveOverrideMaterial();
|
|
|
|
|
}
|
2021-12-10 01:51:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UUVLayoutTool::UpdateVisualization()
|
|
|
|
|
{
|
|
|
|
|
UpdatePreviewMaterial();
|
2020-03-05 14:27:21 -05:00
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
for (UMeshOpPreviewWithBackgroundCompute* Preview : Previews)
|
|
|
|
|
{
|
|
|
|
|
Preview->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UUVLayoutTool::CanAccept() const
|
|
|
|
|
{
|
2021-11-18 20:41:17 -05:00
|
|
|
for (const UMeshOpPreviewWithBackgroundCompute* Preview : Previews)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
|
|
|
|
if (!Preview->HaveValidResult())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-24 18:42:39 -04:00
|
|
|
return Super::CanAccept();
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UUVLayoutTool::GenerateAsset(const TArray<FDynamicMeshOpResult>& Results)
|
|
|
|
|
{
|
|
|
|
|
GetToolManager()->BeginUndoTransaction(LOCTEXT("UVLayoutToolTransactionName", "UV Layout Tool"));
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
check(Results.Num() == Targets.Num());
|
2019-12-19 18:07:47 -05:00
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2019-12-19 18:07:47 -05:00
|
|
|
{
|
2021-12-06 12:42:19 -05:00
|
|
|
const FDynamicMesh3* DynamicMesh = Results[ComponentIdx].Mesh.Get();
|
|
|
|
|
check(DynamicMesh != nullptr);
|
|
|
|
|
UE::ToolTarget::CommitDynamicMeshUVUpdate(Targets[ComponentIdx], DynamicMesh);
|
2019-12-19 18:07:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetToolManager()->EndUndoTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|
2022-09-28 01:06:15 -04:00
|
|
|
|