Files
UnrealEngineUWP/Engine/Plugins/Experimental/MeshModelingToolset/Source/ModelingComponents/Private/ModelingToolTargetUtil.cpp
Ryan Schmidt 6497a53181 ModelingComponents: Add DynamicMeshActor
- ADynamicMeshActor type has a UDynamicMeshComponent subobject (similar to StaticMeshActor)
- Add IPersistentDynamicMeshSource, a ToolTarget Interface for accessing a UDynamicMesh
- Add UDynamicMeshComponentToolTarget, a UToolTarget implementing the above as well as various standard interfaces, to allow Tools to operate on an external DynamicMeshComponent
- Update UE::ToolTarget:: helper functions that get/commit via DynamicMesh to handle IPersistentDynamicMeshSource directly, instead of going via existing MeshDescription/DynamicMesh interfaces. Add UE::ToolTarget::SetSourceObjectVisible() helper function.
- Add support for creating DynamicMeshActors in UCreateMeshObjectTypeProperties and UEditorModelingObjectsCreationAPI
- register UDynamicMeshComponentToolTargetFactory in ModelingToolsEditorMode
- Rename existing internal ADynamicMeshActor to AOldDynamicMeshActor. Does not appear to be in use and will be removed in a future CL.

#rb lonnie.li
#rnx
#jira none
#preflight 60d0effc367e6700014c2e89

[CL 16735093 by Ryan Schmidt in ue5-main branch]
2021-06-21 18:08:56 -04:00

356 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ModelingToolTargetUtil.h"
#include "ToolTargets/ToolTarget.h"
#include "TargetInterfaces/MaterialProvider.h"
#include "TargetInterfaces/MeshDescriptionCommitter.h"
#include "TargetInterfaces/MeshDescriptionProvider.h"
#include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
#include "TargetInterfaces/DynamicMeshSource.h"
#include "ModelingObjectsCreationAPI.h"
#include "Components/PrimitiveComponent.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/Volume.h"
#include "Components/DynamicMeshComponent.h"
#include "MeshConversionOptions.h"
#include "MeshDescriptionToDynamicMesh.h"
#include "DynamicMeshToMeshDescription.h"
#define LOCTEXT_NAMESPACE "ModelingToolTargetUtil"
using namespace UE::Geometry;
AActor* UE::ToolTarget::GetTargetActor(UToolTarget* Target)
{
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(Target);
if (TargetComponent)
{
return TargetComponent->GetOwnerActor();
}
ensure(false);
return nullptr;
}
UPrimitiveComponent* UE::ToolTarget::GetTargetComponent(UToolTarget* Target)
{
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(Target);
if (TargetComponent)
{
return TargetComponent->GetOwnerComponent();
}
ensure(false);
return nullptr;
}
bool UE::ToolTarget::HideSourceObject(UToolTarget* Target)
{
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(Target);
if (TargetComponent)
{
TargetComponent->SetOwnerVisibility(false);
return true;
}
ensure(false);
return false;
}
bool UE::ToolTarget::ShowSourceObject(UToolTarget* Target)
{
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(Target);
if (TargetComponent)
{
TargetComponent->SetOwnerVisibility(true);
return true;
}
ensure(false);
return false;
}
bool UE::ToolTarget::SetSourceObjectVisible(UToolTarget* Target, bool bVisible)
{
if (bVisible)
{
return ShowSourceObject(Target);
}
else
{
return HideSourceObject(Target);
}
}
FTransform3d UE::ToolTarget::GetLocalToWorldTransform(UToolTarget* Target)
{
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(Target);
if (TargetComponent)
{
return (FTransform3d)TargetComponent->GetWorldTransform();
}
ensure(false);
return FTransform3d();
}
FComponentMaterialSet UE::ToolTarget::GetMaterialSet(UToolTarget* Target, bool bPreferAssetMaterials)
{
FComponentMaterialSet MaterialSet;
IMaterialProvider* MaterialProvider = Cast<IMaterialProvider>(Target);
if (ensure(MaterialProvider))
{
MaterialProvider->GetMaterialSet(MaterialSet, bPreferAssetMaterials);
}
return MaterialSet;
}
bool UE::ToolTarget::CommitMaterialSetUpdate(
UToolTarget* Target,
const FComponentMaterialSet& UpdatedMaterials,
bool bApplyToAsset)
{
IMaterialProvider* MaterialProvider = Cast<IMaterialProvider>(Target);
if (MaterialProvider)
{
return MaterialProvider->CommitMaterialSetUpdate(UpdatedMaterials, bApplyToAsset);
}
return false;
}
const FMeshDescription* UE::ToolTarget::GetMeshDescription(UToolTarget* Target)
{
static FMeshDescription EmptyMeshDescription;
IMeshDescriptionProvider* MeshDescriptionProvider = Cast<IMeshDescriptionProvider>(Target);
if (MeshDescriptionProvider)
{
return MeshDescriptionProvider->GetMeshDescription();
}
ensure(false);
return &EmptyMeshDescription;
}
FMeshDescription UE::ToolTarget::GetMeshDescriptionCopy(UToolTarget* Target, bool bWantMeshTangents)
{
IMeshDescriptionProvider* MeshDescriptionProvider = Cast<IMeshDescriptionProvider>(Target);
if (MeshDescriptionProvider)
{
FMeshDescription NewMeshDescription = *MeshDescriptionProvider->GetMeshDescription();
if (bWantMeshTangents)
{
MeshDescriptionProvider->CalculateAutoGeneratedAttributes(NewMeshDescription);
}
return NewMeshDescription;
}
ensure(false);
return FMeshDescription();
}
FDynamicMesh3 UE::ToolTarget::GetDynamicMeshCopy(UToolTarget* Target, bool bWantMeshTangents)
{
IPersistentDynamicMeshSource* DynamicMeshSource = Cast<IPersistentDynamicMeshSource>(Target);
if (DynamicMeshSource)
{
UDynamicMesh* DynamicMesh = DynamicMeshSource->GetDynamicMeshContainer();
FDynamicMesh3 Mesh;
DynamicMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh) { Mesh = ReadMesh; });
return Mesh;
}
IMeshDescriptionProvider* MeshDescriptionProvider = Cast<IMeshDescriptionProvider>(Target);
FDynamicMesh3 Mesh(EMeshComponents::FaceGroups);
Mesh.EnableAttributes();
if (MeshDescriptionProvider)
{
FMeshDescriptionToDynamicMesh Converter;
if (bWantMeshTangents)
{
// Currently to auto-calculate attributes we must make a copy, because they are written
// directly to the input mesh
FMeshDescription MeshDescriptionCopy( *MeshDescriptionProvider->GetMeshDescription() );
MeshDescriptionProvider->CalculateAutoGeneratedAttributes(MeshDescriptionCopy);
Converter.Convert(&MeshDescriptionCopy, Mesh, bWantMeshTangents);
}
else
{
Converter.Convert(MeshDescriptionProvider->GetMeshDescription(), Mesh, bWantMeshTangents);
}
return Mesh;
}
ensure(false);
return Mesh;
}
UE::ToolTarget::EDynamicMeshUpdateResult UE::ToolTarget::CommitMeshDescriptionUpdate(UToolTarget* Target, const FMeshDescription* UpdatedMesh, const FComponentMaterialSet* UpdatedMaterials)
{
IMeshDescriptionCommitter* MeshDescriptionCommitter = Cast<IMeshDescriptionCommitter>(Target);
if (!ensure(MeshDescriptionCommitter))
{
return EDynamicMeshUpdateResult::Failed;
}
if (UpdatedMaterials != nullptr)
{
CommitMaterialSetUpdate(Target, *UpdatedMaterials, true);
}
EDynamicMeshUpdateResult Result = EDynamicMeshUpdateResult::Failed;
MeshDescriptionCommitter->CommitMeshDescription([UpdatedMesh, &Result](const IMeshDescriptionCommitter::FCommitterParams& CommitParams)
{
*CommitParams.MeshDescriptionOut = *UpdatedMesh;
Result = EDynamicMeshUpdateResult::Ok;
});
return Result;
}
UE::ToolTarget::EDynamicMeshUpdateResult UE::ToolTarget::CommitDynamicMeshUpdate(
UToolTarget* Target, const FDynamicMesh3& UpdatedMesh,
bool bHaveModifiedTopology,
const FConversionToMeshDescriptionOptions& ConversionOptions,
const FComponentMaterialSet* UpdatedMaterials)
{
IPersistentDynamicMeshSource* DynamicMeshSource = Cast<IPersistentDynamicMeshSource>(Target);
if (DynamicMeshSource)
{
UDynamicMesh* DynamicMesh = DynamicMeshSource->GetDynamicMeshContainer();
TUniquePtr<FDynamicMesh3> CurrentMesh = DynamicMesh->ExtractMesh();
TSharedPtr<FDynamicMesh3> CurrentMeshShared(CurrentMesh.Release());
DynamicMesh->EditMesh([&](FDynamicMesh3& EditMesh) { EditMesh = UpdatedMesh; });
TSharedPtr<FDynamicMesh3> NewMeshShared = MakeShared<FDynamicMesh3>();
DynamicMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh) { *NewMeshShared = ReadMesh; });
TUniquePtr<FMeshReplacementChange> ReplaceChange = MakeUnique<FMeshReplacementChange>(CurrentMeshShared, NewMeshShared);
DynamicMeshSource->CommitDynamicMeshChange(MoveTemp(ReplaceChange), LOCTEXT("CommitDynamicMeshUpdate_MeshSource", "Edit Mesh"));
// todo support bModifiedTopology flag?
return EDynamicMeshUpdateResult::Ok;
}
IMeshDescriptionCommitter* MeshDescriptionCommitter = Cast<IMeshDescriptionCommitter>(Target);
if (MeshDescriptionCommitter)
{
if (UpdatedMaterials != nullptr)
{
CommitMaterialSetUpdate(Target, *UpdatedMaterials, true);
}
EDynamicMeshUpdateResult Result = EDynamicMeshUpdateResult::Failed;
MeshDescriptionCommitter->CommitMeshDescription([&](const IMeshDescriptionCommitter::FCommitterParams& CommitParams)
{
FMeshDescription* MeshDescription = CommitParams.MeshDescriptionOut;
FDynamicMeshToMeshDescription Converter(ConversionOptions);
if (!bHaveModifiedTopology)
{
Converter.UpdateUsingConversionOptions(&UpdatedMesh, *MeshDescription);
Result = EDynamicMeshUpdateResult::Ok;
}
else
{
Converter.Convert(&UpdatedMesh, *MeshDescription);
Result = EDynamicMeshUpdateResult::Ok;
}
});
return Result;
}
ensure(false);
return EDynamicMeshUpdateResult::Failed;
}
UE::ToolTarget::EDynamicMeshUpdateResult UE::ToolTarget::CommitDynamicMeshUVUpdate(UToolTarget* Target, const UE::Geometry::FDynamicMesh3* UpdatedMesh)
{
IPersistentDynamicMeshSource* DynamicMeshSource = Cast<IPersistentDynamicMeshSource>(Target);
if (DynamicMeshSource)
{
// todo actually only update UVs?
UDynamicMesh* DynamicMesh = DynamicMeshSource->GetDynamicMeshContainer();
DynamicMesh->EditMesh([&](FDynamicMesh3& EditMesh) { EditMesh = *UpdatedMesh; });
return EDynamicMeshUpdateResult::Ok;
}
IMeshDescriptionCommitter* MeshDescriptionCommitter = Cast<IMeshDescriptionCommitter>(Target);
if (!ensure(MeshDescriptionCommitter))
{
return EDynamicMeshUpdateResult::Failed;
}
EDynamicMeshUpdateResult Result = EDynamicMeshUpdateResult::Failed;
MeshDescriptionCommitter->CommitMeshDescription([UpdatedMesh, &Result](const IMeshDescriptionCommitter::FCommitterParams& CommitParams)
{
FMeshDescription* MeshDescription = CommitParams.MeshDescriptionOut;
bool bVerticesOnly = false;
bool bAttributesOnly = true;
if (FDynamicMeshToMeshDescription::HaveMatchingElementCounts(UpdatedMesh, MeshDescription, bVerticesOnly, bAttributesOnly))
{
FDynamicMeshToMeshDescription Converter;
Converter.UpdateAttributes(UpdatedMesh, *MeshDescription, false, false, true/*update uvs*/);
Result = EDynamicMeshUpdateResult::Ok;
}
else
{
// must have been duplicate tris in the mesh description; we can't count on 1-to-1 mapping of TriangleIDs. Just convert
FDynamicMeshToMeshDescription Converter;
Converter.Convert(UpdatedMesh, *MeshDescription);
Result = EDynamicMeshUpdateResult::Ok_ForcedFullUpdate;
}
});
return Result;
}
bool UE::ToolTarget::ConfigureCreateMeshObjectParams(UToolTarget* SourceTarget, FCreateMeshObjectParams& DerivedParamsOut)
{
IPrimitiveComponentBackedTarget* ComponentTarget = Cast<IPrimitiveComponentBackedTarget>(SourceTarget);
if (ComponentTarget)
{
if (Cast<UStaticMeshComponent>(ComponentTarget->GetOwnerComponent()) != nullptr)
{
DerivedParamsOut.TypeHint = ECreateObjectTypeHint::StaticMesh;
return true;
}
if (Cast<UDynamicMeshComponent>(ComponentTarget->GetOwnerComponent()) != nullptr)
{
DerivedParamsOut.TypeHint = ECreateObjectTypeHint::DynamicMeshActor;
return true;
}
AVolume* VolumeActor = Cast<AVolume>(ComponentTarget->GetOwnerActor());
if (VolumeActor != nullptr)
{
DerivedParamsOut.TypeHint = ECreateObjectTypeHint::Volume;
DerivedParamsOut.TypeHintClass = VolumeActor->GetClass();
return true;
}
}
return false;
}
#undef LOCTEXT_NAMESPACE