// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "DynamicMesh/DynamicMesh3.h" #include "TargetInterfaces/MeshTargetInterfaceTypes.h" #include "TargetInterfaces/MaterialProvider.h" // FComponentMaterialSet #include "MeshConversionOptions.h" class UStaticMesh; class USkeletalMesh; class UToolTarget; class UPrimitiveComponent; class USceneComponent; class AActor; class UBodySetup; class IInterface_CollisionDataProvider; struct FMeshDescription; struct FCreateMeshObjectParams; class IPersistentDynamicMeshSource; // // UE::ToolTarget:: namespace contains utility/helper functions for interacting with UToolTargets. // Generally these are meant to be used by UInteractiveTools to handle standard tasks that would // otherwise require each Tool to figure out things like which ToolTargetInterface to cast to, etc. // Using these functions ideally avoids all the boilerplate inherent in the ToolTarget system. // // However, the cost is that it is not necessarily the most efficient, as each one of these functions // may potentially do many repeated Cast<>'s internally. So, use sparingly, or cache the outputs. // namespace UE { namespace ToolTarget { /** * @return the AActor backing a ToolTarget, or nullptr if there is no such Actor */ MODELINGCOMPONENTS_API AActor* GetTargetActor(UToolTarget* Target); /** * @return the UPrimitiveComponent backing a ToolTarget, or nullptr if there is no such Component */ MODELINGCOMPONENTS_API UPrimitiveComponent* GetTargetComponent(UToolTarget* Target); /** * @return the UActorComponent backing a ToolTarget, or nullptr if there is no such Component */ MODELINGCOMPONENTS_API USceneComponent* GetTargetSceneComponent(UToolTarget* Target); /** * @return a human readable identifier for a ToolTarget, based on the underlying nature of it. */ MODELINGCOMPONENTS_API FString GetHumanReadableName(UToolTarget* Target); /** * Hide the "Source Object" (eg PrimitiveComponent, Actor, etc) backing a ToolTarget * @return true on success */ MODELINGCOMPONENTS_API bool HideSourceObject(UToolTarget* Target); /** * Show the "Source Object" (eg PrimitiveComponent, Actor, etc) backing a ToolTarget * @return true on success */ MODELINGCOMPONENTS_API bool ShowSourceObject(UToolTarget* Target); /** * Show or Hide the "Source Object" (eg PrimitiveComponent, Actor, etc) backing a ToolTarget * @return true on success */ MODELINGCOMPONENTS_API bool SetSourceObjectVisible(UToolTarget* Target, bool bVisible); /** * @return the local-to-world Transform underlying a ToolTarget, eg the Component or Actor transform */ MODELINGCOMPONENTS_API FTransform3d GetLocalToWorldTransform(UToolTarget* Target); /** * Fetch the Material Set on the object underlying a ToolTarget. In cases where there are (eg) * separate Component and Asset material sets, prefers the Component material set * @param bPreferAssetMaterials if true, prefer an Asset material set, if available * @return a valid MaterialSet */ MODELINGCOMPONENTS_API FComponentMaterialSet GetMaterialSet(UToolTarget* Target, bool bPreferAssetMaterials = false); /** * Update the material set of the Target * @param bApplyToAsset In situations where the Target has both Component-level and Asset-level materials, this specifies which should be updated (this flag is passed to the IMaterialProvider, which may or may not respect it) */ MODELINGCOMPONENTS_API bool CommitMaterialSetUpdate( UToolTarget* Target, const FComponentMaterialSet& UpdatedMaterials, bool bApplyToAsset = true); /** * @param Target The tool target to query for LODs * @param bOutTargetSupportsLODs Will be set to 'false' if the target does not support querying MeshDescriptions with LODs * @param bOnlyReturnDefaultLOD If true, always return an array of just the Default LOD * @param bExcludeAutoGeneratedLODs If true, exclude any auto-generated LODs (which have no associated Mesh Description) from the LOD list * @return An array of valid LODs for the mesh data underlying the ToolTarget, or just the Default LOD if the target doesn't support LODs or bOnlyReturnDefaultLOD is true */ MODELINGCOMPONENTS_API TArray GetMeshDescriptionLODs( UToolTarget* Target, bool& bOutTargetSupportsLODs, bool bOnlyReturnDefaultLOD = false, bool bExcludeAutoGeneratedLODs = true); /** * Return identifier for the mesh LOD that a ToolTarget represents, if defined for the given ToolTarget * @param Target The tool target to query for LODs * @param bOutTargetSupportsLODs Will be set to 'false' if the target does not support querying MeshDescriptions with LODs * @return LODIdentifier for current LOD that would be provided/edited by the ToolTarget, or the Default LODIdentifier if the target doesn't support LODs or bOnlyReturnDefaultLOD is true */ MODELINGCOMPONENTS_API EMeshLODIdentifier GetTargetMeshDescriptionLOD( UToolTarget* Target, bool& bOutTargetSupportsLODs); /** * @return the MeshDescription underlying a ToolTarget, if it has such a mesh. May be generated internally by the ToolTarget. May be nullptr if the Target does not have a mesh. */ MODELINGCOMPONENTS_API const FMeshDescription* GetMeshDescription( UToolTarget* Target, const FGetMeshParameters& GetMeshParams = FGetMeshParameters()); /** * @return an empty MeshDescription with attributes already registered appropriate to the target. */ MODELINGCOMPONENTS_API FMeshDescription GetEmptyMeshDescription( UToolTarget* Target); /** * Return a copy of the MeshDescription underlying a ToolTarget * @return a new MeshDescription, which may be empty if the Target doesn't have a mesh */ MODELINGCOMPONENTS_API FMeshDescription GetMeshDescriptionCopy( UToolTarget* Target, const FGetMeshParameters& GetMeshParams = FGetMeshParameters()); /** * Fetch a DynamicMesh3 representing the given ToolTarget. This may be a conversion of the output of GetMeshDescription(). * This function returns a copy, so the caller can take ownership of this Mesh. * @param bWantMeshTangents if true, tangents will be returned if the target has them available. This may require that they be auto-calculated in some cases (which may be expensive) * @return a created DynamicMesh3, which may be empty if the Target doesn't have a mesh */ UE_DEPRECATED(5.5, "Use GetDynamicMeshCopy which takes a FGetMeshParameters instead.") MODELINGCOMPONENTS_API UE::Geometry::FDynamicMesh3 GetDynamicMeshCopy(UToolTarget* Target, bool bWantMeshTangents); /** * Fetch a DynamicMesh3 representing the given ToolTarget. This may be a conversion of the output of GetMeshDescription(). * This function returns a copy, so the caller can take ownership of this Mesh. * @param InGetMeshParams to specify various options like specific LOD and/or tangents on the returned mesh. * if InGetMeshParams.bWantMeshTangents is true, tangents will be returned if the target has them available. This may require that they be auto-calculated in some cases (which may be expensive) * @return a created DynamicMesh3, which may be empty if the Target doesn't have a mesh */ MODELINGCOMPONENTS_API UE::Geometry::FDynamicMesh3 GetDynamicMeshCopy( UToolTarget* Target, const FGetMeshParameters& InGetMeshParams = FGetMeshParameters()); /** @return The triangle count of Target's persistent dynamic mesh or its mesh description, if available, or 0 otherwise */ MODELINGCOMPONENTS_API int32 GetTriangleCount(UToolTarget* Target); /** * EDynamicMeshUpdateResult is returned by functions below that update a ToolTarget with a new Mesh */ enum class EDynamicMeshUpdateResult { /** Update was successful */ Ok = 0, /** Update failed */ Failed = 1, /** Update was successful, but required that the entire target mesh be replaced, instead of a (requested) partial update */ Ok_ForcedFullUpdate = 2 }; /** * Update the Mesh in a ToolTarget based on the provided MeshDescription, and optional material set * @return EDynamicMeshUpdateResult::Ok on success */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitMeshDescriptionUpdate( UToolTarget* Target, const FMeshDescription* UpdatedMesh, const FComponentMaterialSet* UpdatedMaterials = nullptr, const FCommitMeshParameters& CommitParams = FCommitMeshParameters()); /** * Update the Mesh in a ToolTarget based on the provided MeshDescription, and optional material set * @return EDynamicMeshUpdateResult::Ok on success */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitMeshDescriptionUpdate( UToolTarget* Target, FMeshDescription&& UpdatedMesh, const FCommitMeshParameters& CommitParams = FCommitMeshParameters()); /** * Update the Mesh in a ToolTarget based on the provided MeshDescription, and optional material set * @return EDynamicMeshUpdateResult::Ok on success */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitMeshDescriptionUpdateViaDynamicMesh( UToolTarget* Target, const UE::Geometry::FDynamicMesh3& UpdatedMesh, bool bHaveModifiedTopology, const FCommitMeshParameters& CommitParams = FCommitMeshParameters()); /** * Update the Mesh in a ToolTarget based on the provided DynamicMesh, and optional material set * @param bHaveModifiedTopology If the update only changes vertex or attribute values (but not counts), then in some cases a more efficient and/or less destructive update can be applied to the Target * @param ConversionOptions if the commit to the Target involves conversion to MeshDescription, these options can configure that conversion * @param UpdatedMaterials optional new material set that will be applied to the updated Target, and the Target Asset if available. If more control is needed use CommitMaterialSetUpdate() * @return EDynamicMeshUpdateResult::Ok on success */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitDynamicMeshUpdate( UToolTarget* Target, const UE::Geometry::FDynamicMesh3& UpdatedMesh, bool bHaveModifiedTopology, const FConversionToMeshDescriptionOptions& ConversionOptions = FConversionToMeshDescriptionOptions(), const FComponentMaterialSet* UpdatedMaterials = nullptr); /** * Update the UV sets of the ToolTarget's mesh (assuming it has one) based on the provided UpdatedMesh. * @todo: support updating a specific UV set/index, rather than all sets * @return EDynamicMeshUpdateResult::Ok on success, or Ok_ForcedFullUpdate if any dependent mesh topology was modified */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitDynamicMeshUVUpdate(UToolTarget* Target, const UE::Geometry::FDynamicMesh3* UpdatedMesh); /** * Update the Normals/Tangents of the ToolTarget's mesh (assuming it has one) based on the provided UpdatedMesh. * @return EDynamicMeshUpdateResult::Ok on success, or Ok_ForcedFullUpdate if any dependent mesh topology was modified */ MODELINGCOMPONENTS_API EDynamicMeshUpdateResult CommitDynamicMeshNormalsUpdate(UToolTarget* Target, const UE::Geometry::FDynamicMesh3* UpdatedMesh, bool bUpdateTangents = false); /** * @return true if ToolTarget can be directly updated via an incremental edits, ie if it is acceptable to call ApplyIncrementalMeshEditChange() on the target */ MODELINGCOMPONENTS_API bool SupportsIncrementalMeshChanges(UToolTarget* Target); /** * Apply an incremental mesh edit (MeshEditingFunc) to the ToolTarget. Tools/etc can use this to directly * modify the ToolTarget's internal DynamicMesh, while (presumably) also emitting a FChange transaction that * represents that Edit. This allows for undoable edits directly to a DynamicMeshComponent/etc in the level. * @return true if the incremental edit succeeds */ MODELINGCOMPONENTS_API bool ApplyIncrementalMeshEditChange( UToolTarget* Target, TFunctionRef MeshEditingFunc ); /** * FCreateMeshObjectParams::TypeHint is used by the ModelingObjectsCreationAPI to suggest what type of mesh object to create * inside various Tools. This should often be derived from the input mesh object type (eg if you plane-cut a Volume, the output * should be Volumes). This function interrogates the ToolTarget to try to determine this information * @return true if a known type was detected and configured in FCreateMeshObjectParams::TypeHint (and possibly FCreateMeshObjectParams::TypeHintClass) */ MODELINGCOMPONENTS_API bool ConfigureCreateMeshObjectParams(UToolTarget* SourceTarget, FCreateMeshObjectParams& DerivedParamsOut); namespace Internal { /** * Not intended for direct use by tools, just for use by tool target util functions and tool target * implementations that may need to do this operation. Uses the IPersistentDynamicMeshSource interface * to perform an update of the dynamic mesh. * Currently ignores bHaveModifiedTopology. */ MODELINGCOMPONENTS_API void CommitDynamicMeshViaIPersistentDynamicMeshSource( IPersistentDynamicMeshSource& DynamicMeshSource, const UE::Geometry::FDynamicMesh3& UpdatedMesh, bool bHaveModifiedTopology); #if WITH_EDITOR /** * Internal path for use by tool targets to invoke PostEditChange with conditional capture for undo * transactions. This capture is controlled by the CVar 'modeling.CapturePostEditChangeInTransactions'. * * PostEditChange can include arbitrary user code which can lead to a tool transaction capturing data * beyond the modifications the tool has made, opening up the risk of various side effects. It is * recommended that PostEditChange is not included in a transaction scope since PostEditUndo will * reinvoke PostEditChange and provide the user code the opportunity to reapply its changes in response * to the data modifications being made. * * That said, not all user code in PostEditChange is well behaved and deterministic so we provide the CVar * to toggle this behavior. */ MODELINGCOMPONENTS_API void PostEditChangeWithConditionalUndo(UObject* Object); #endif } /** * @return the Physics UBodySetup for the given ToolTarget, or nullptr if it does not exist */ MODELINGCOMPONENTS_API UBodySetup* GetPhysicsBodySetup(UToolTarget* Target); /** * @return the Physics CollisionDataProvider (ie Complex Collision source) for the given ToolTarget, or nullptr if it does not exist */ MODELINGCOMPONENTS_API IInterface_CollisionDataProvider* GetPhysicsCollisionDataProvider(UToolTarget* Target); /** @return StaticMesh from a tool target */ MODELINGCOMPONENTS_API UStaticMesh* GetStaticMeshFromTargetIfAvailable(UToolTarget* Target); /** @return SkeletalMesh from a tool target */ MODELINGCOMPONENTS_API USkeletalMesh* GetSkeletalMeshFromTargetIfAvailable(UToolTarget* Target); } // end namespace ToolTarget } // end namespace UE