// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Math/Vector.h" #include "Logging/LogMacros.h" #include "Templates/SharedPointer.h" struct FManagedArrayCollection; struct FMeshBuildSettings; struct FMeshDescription; struct FDataflowNode; class FSkeletalMeshLODModel; class FString; class IPropertyHandle; namespace UE::Chaos::ClothAsset { /** * Tools shared by cloth dataflow nodes */ struct FClothDataflowTools { static void AddRenderPatternFromSkeletalMeshSection(const TSharedRef& ClothCollection, const FSkeletalMeshLODModel& SkeletalMeshModel, const int32 SectionIndex, const FString& RenderMaterialPathName); static void AddSimPatternsFromSkeletalMeshSection(const TSharedRef& ClothCollection, const FSkeletalMeshLODModel& SkeletalMeshModel, const int32 SectionIndex, const int32 UVChannelIndex, const FVector2f& UVScale, bool bImportNormals = false, TArray* OutSim2DToSourceVertex = nullptr); static void LogAndToastWarning(const FDataflowNode& DataflowNode, const FText& Headline, const FText& Details); /** * Turn a string into a valid collection group or attribute name. * The resulting name won't contains spaces and any other special characters as listed in * INVALID_OBJECTNAME_CHARACTERS (currently "',/.:|&!~\n\r\t@#(){}[]=;^%$`). * It will also have all leading underscore removed, as these names are reserved for internal use. * @param InOutString The string to turn into a valid collection name. * @return Whether the InOutString was already a valid collection name. */ static bool MakeCollectionName(FString& InOutString); static bool BuildSkeletalMeshModelFromMeshDescription(const FMeshDescription* const InMeshDescription, const FMeshBuildSettings& InBuildSettings, FSkeletalMeshLODModel& SkeletalMeshModel); /** Return the Dataflow node owning by this property, and cast it to the desired node type. */ template static T* GetPropertyOwnerDataflowNode(const TSharedPtr& PropertyHandle) { return static_cast(GetPropertyOwnerDataflowNode(PropertyHandle, T::StaticStruct())); } /** Simulation mesh cleanup tools. */ struct FSimMeshCleanup { TArray TriangleToVertexIndex; TArray RestPositions2D; TArray DrapedPositions3D; TArray> OriginalTriangles; // New to original face index lookup TArray> OriginalVertices; // New to original vertex index lookup FSimMeshCleanup( const TArray& InTriangleToVertexIndex, const TArray& InRestPositions2D, const TArray& InDrapedPositions3D); bool RemoveDegenerateTriangles(); bool RemoveDuplicateTriangles(); }; /** Returns the inverse mapping from a reduced set of original indices to the new indices. */ template> || std::is_same_v>)> static TArray GetOriginalToNewIndices(const TConstArrayView& NewToOriginals, int32 NumOriginalIndices); UE_DEPRECATED(5.6, "Use FSimMeshCleanup instead.") static bool RemoveDegenerateTriangles( const TArray& TriangleToVertexIndex, const TArray& RestPositions2D, const TArray& DrapedPositions3D, TArray& OutTriangleToVertexIndex, TArray& OutRestPositions2D, TArray& OutDrapedPositions3D, TArray& OutIndices); // Old to new vertices lookup UE_DEPRECATED(5.6, "Use FSimMeshCleanup instead.") static bool RemoveDuplicateTriangles(TArray& TriangleToVertexIndex) { FSimMeshCleanup SimMeshCleanup(TriangleToVertexIndex, TArray(), TArray()); const bool bHasDuplicateTriangles = SimMeshCleanup.RemoveDuplicateTriangles(); TriangleToVertexIndex = MoveTemp(SimMeshCleanup.TriangleToVertexIndex); return bHasDuplicateTriangles; } static bool RemoveDuplicateStitches(TArray>& SeamStitches); private: /** Return the Dataflow node owning by this property. */ static FDataflowNode* GetPropertyOwnerDataflowNode(const TSharedPtr& PropertyHandle, const UStruct* DataflowNodeStruct); }; } // End namespace UE::Chaos::ClothAsset DECLARE_LOG_CATEGORY_EXTERN(LogChaosClothAssetDataflowNodes, Log, All);