You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- Move UCreateMeshObjectTypeProperties to ModelingComponents and update all include sites - Added Editor Modeling Mode settings to Enable/Disable showing DynamicMeshActor creation options, and select default mesh object type. Removed CVarEnableDynamicMeshActors. - Added optional 'Auto' output mesh type to UCreateMeshObjectTypeProperties. This can be used in Tools that have input objects and want to allow optional conversion, but default to 'just use input mesh object type'. - Added ConvertMeshesTool, this does in-place conversion between Mesh Object types for a set of selected objects (Duplicate tool can also do this, but only for a single object, and functionality is expected to further diverge) - Added SplitMeshesTool, decomposes a mesh into parts and creates a new output object for each part - CombineMeshesTool now supports variable output object type. Cleaned up internals. #rb none #rnx #jira none #preflight 60d3bc76b4bb42000195eccf [CL 16768010 by Ryan Schmidt in ue5-main branch]
356 lines
10 KiB
C++
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)
|
|
{
|
|
if (UpdatedMaterials != nullptr)
|
|
{
|
|
CommitMaterialSetUpdate(Target, *UpdatedMaterials, true);
|
|
}
|
|
|
|
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)
|
|
{
|
|
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 |