Integrating CL# 9735441 from Dev-Enterprise

Dataprep: Combining operators "Enable Lightmaps UVs" and "Compute Lightmap Resolution" into "Setup Static Lighting"

#jira UEENT-3012
#rb JeanLuc.Corenthin

#ROBOMERGE-OWNER: patrick.boutot
#ROBOMERGE-AUTHOR: benoit.deschenes
#ROBOMERGE-SOURCE: CL 9759326 in //UE4/Release-4.24/... via CL 9759356 via CL 9819286
#ROBOMERGE-BOT: TOOLS (Dev-Tools-Staging -> Dev-VirtualProduction) (v546-9757112)

[CL 9820117 by benoit deschenes in Dev-VirtualProduction branch]
This commit is contained in:
benoit deschenes
2019-10-24 14:58:56 -04:00
8 changed files with 219 additions and 211 deletions

View File

@@ -21,6 +21,7 @@
#include "Engine/World.h"
#include "GameFramework/Actor.h"
#include "HAL/FileManager.h"
#include "MeshExport.h"
#include "Misc/PackageName.h"
#include "PackageTools.h"
#include "UObject/Package.h"
@@ -30,18 +31,15 @@
#define LOCTEXT_NAMESPACE "DatasmithBlueprintLibrary"
DEFINE_LOG_CATEGORY_STATIC(LogSetupStaticLighting, Log, All);
namespace DatasmithStaticMeshBlueprintLibraryUtil
{
void EnsureLightmapUVsAreAvailable( UStaticMesh* StaticMesh )
void EnsureLightmapSourceUVsAreAvailable( UStaticMesh* StaticMesh )
{
if ( FMeshDescription* MeshDescription = StaticMesh->GetMeshDescription( 0 ) )
if ( StaticMesh->GetNumSourceModels() > 0 && StaticMesh->GetSourceModel(0).BuildSettings.bGenerateLightmapUVs )
{
const bool bAreLightmapUVsAvailable = DatasmithMeshHelper::HasUVData( *MeshDescription, StaticMesh->LightMapCoordinateIndex );
if ( !bAreLightmapUVsAvailable )
{
FDatasmithStaticMeshImporter::PreBuildStaticMesh( StaticMesh );
}
FDatasmithStaticMeshImporter::PreBuildStaticMesh( StaticMesh );
}
}
@@ -52,6 +50,43 @@ namespace DatasmithStaticMeshBlueprintLibraryUtil
return Area;
}
//Used for creating a mapping of StaticMeshes and the StaticMeshComponents that references them in the given list.
TMap< UStaticMesh*, TSet< UStaticMeshComponent* > > GetStaticMeshComponentMap(const TArray< UObject* >& Objects)
{
TMap< UStaticMesh*, TSet< UStaticMeshComponent* > > StaticMeshMap;
for (UObject* Object : Objects)
{
if (AActor* Actor = Cast< AActor >(Object))
{
TInlineComponentArray<UStaticMeshComponent*> StaticMeshComponents(Actor);
for (UStaticMeshComponent* StaticMeshComponent : StaticMeshComponents)
{
if (StaticMeshComponent && StaticMeshComponent->GetStaticMesh())
{
TSet<UStaticMeshComponent*>& Components = StaticMeshMap.FindOrAdd(StaticMeshComponent->GetStaticMesh());
Components.Add(StaticMeshComponent);
}
}
}
else if (UStaticMeshComponent* StaticMeshComponent = Cast< UStaticMeshComponent >(Object))
{
if (UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh())
{
TSet<UStaticMeshComponent*>& Components = StaticMeshMap.FindOrAdd(StaticMesh);
Components.Add(StaticMeshComponent);
}
}
else if (UStaticMesh* StaticMesh = Cast< UStaticMesh >(Object))
{
TSet<UStaticMeshComponent*>& Components = StaticMeshMap.FindOrAdd(StaticMesh);
Components.Add(nullptr);
}
}
return StaticMeshMap;
}
}
namespace DatasmithBlueprintLibraryImpl
@@ -235,34 +270,83 @@ void UDatasmithSceneElement::DestroyScene()
Reset();
}
void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution( const TArray< UObject* >& Objects, bool bApplyChanges, float IdealRatio )
void UDatasmithStaticMeshBlueprintLibrary::SetupStaticLighting(const TArray< UObject* >& Objects, bool bApplyChanges, bool bGenerateLightmapUVs, float LightmapResolutionIdealRatio)
{
// Collect all the static meshes and static mesh components to compute lightmap resolution for
TMap< UStaticMesh*, TSet< UStaticMeshComponent* > > StaticMeshMap(DatasmithStaticMeshBlueprintLibraryUtil::GetStaticMeshComponentMap(Objects));
for (const auto& StaticMeshPair : StaticMeshMap)
{
UStaticMesh* StaticMesh = StaticMeshPair.Key;
if (bApplyChanges)
{
StaticMesh->Modify();
}
for (int32 LODIndex = 0; LODIndex < StaticMesh->GetNumSourceModels(); ++LODIndex)
{
FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(LODIndex);
const bool bDidChangeSettings = SourceModel.BuildSettings.bGenerateLightmapUVs != bGenerateLightmapUVs;
SourceModel.BuildSettings.bGenerateLightmapUVs = bGenerateLightmapUVs;
if (LODIndex == 0)
{
int32 MaxBiggestUVChannel = Lightmass::MAX_TEXCOORDS;
if (const FMeshDescription* MeshDescription = SourceModel.MeshDescription.Get())
{
FStaticMeshConstAttributes Attributes(*MeshDescription);
// 3 is the maximum that lightmass accept. Defined in MeshExport.h : MAX_TEXCOORDS .
MaxBiggestUVChannel = FMath::Min(MaxBiggestUVChannel, Attributes.GetVertexInstanceUVs().GetNumIndices() - 1);
}
if (bGenerateLightmapUVs)
{
const int32 GeneratedLightmapChannel = SourceModel.BuildSettings.DstLightmapIndex;
if (GeneratedLightmapChannel < Lightmass::MAX_TEXCOORDS)
{
StaticMesh->LightMapCoordinateIndex = GeneratedLightmapChannel;
}
else
{
UE_LOG(LogSetupStaticLighting, Warning, TEXT("Could not complete the static lighting setup for static mesh %s as the generated lightmap UV is set to be in channel #%i while the maximum lightmap channel is %i"), *StaticMesh->GetName(), GeneratedLightmapChannel, Lightmass::MAX_TEXCOORDS);
break;
}
}
else if (StaticMesh->LightMapCoordinateIndex > MaxBiggestUVChannel && bDidChangeSettings)
{
// If we are not generating the lightmap anymore make sure we are selecting a valid lightmap index.
StaticMesh->LightMapCoordinateIndex = MaxBiggestUVChannel;
}
}
}
}
// Compute the lightmap resolution, do not apply the changes so that the computation is done on multiple threads
// We'll directly call PostEditChange() at the end of the function so that we also get the StaticLightingSetup changes.
ComputeLightmapResolution(StaticMeshMap, /* bApplyChange */false, LightmapResolutionIdealRatio);
for (const auto& StaticMeshPair : StaticMeshMap)
{
StaticMeshPair.Key->PostEditChange();
}
}
void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution(const TArray< UObject* >& Objects, bool bApplyChanges, float IdealRatio)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution)
// Collect all the static meshes and static mesh components to compute lightmap resolution for
TMap< UStaticMesh*, TSet< UStaticMeshComponent* > > WorkingSet;
TMap< UStaticMesh*, TSet< UStaticMeshComponent* > > StaticMeshMap(DatasmithStaticMeshBlueprintLibraryUtil::GetStaticMeshComponentMap(Objects));
for ( UObject* Object : Objects )
{
if ( AActor* Actor = Cast< AActor >( Object ) )
{
TInlineComponentArray<UStaticMeshComponent*> StaticMeshComponents(Actor);
for (UStaticMeshComponent* StaticMeshComponent : StaticMeshComponents)
{
if(StaticMeshComponent && StaticMeshComponent->GetStaticMesh())
{
TSet<UStaticMeshComponent*>& Components = WorkingSet.FindOrAdd( StaticMeshComponent->GetStaticMesh() );
Components.Add( StaticMeshComponent );
}
}
}
else if ( UStaticMesh* StaticMesh = Cast< UStaticMesh >( Object ) )
{
TSet<UStaticMeshComponent*>& Components = WorkingSet.FindOrAdd(StaticMesh);
Components.Add( nullptr );
}
}
ComputeLightmapResolution(StaticMeshMap, bApplyChanges, IdealRatio);
}
void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution(const TMap< UStaticMesh*, TSet< UStaticMeshComponent* > >& StaticMeshMap, bool bApplyChanges, float IdealRatio)
{
// The actual work
auto Compute = [&](UStaticMesh* StaticMesh, const TSet<UStaticMeshComponent*>& Components)
{
@@ -326,20 +410,31 @@ void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution( const TArr
// If no need to notify changes, multi-thread the computing
if(!bApplyChanges)
{
TArray< UStaticMesh* > WorkingSetKeys;
WorkingSet.GenerateKeyArray( WorkingSetKeys );
TArray< UStaticMesh* > StaticMeshes;
StaticMeshMap.GenerateKeyArray( StaticMeshes );
// Start with the biggest mesh first to help balancing tasks on threads
Algo::SortBy(
WorkingSetKeys,
StaticMeshes,
[](const UStaticMesh* Mesh){ return Mesh->IsMeshDescriptionValid(0) ? Mesh->GetMeshDescription(0)->Vertices().Num() : 0; },
TGreater<>()
);
ParallelFor( WorkingSetKeys.Num(),
ParallelFor(StaticMeshes.Num(),
[&](int32 Index)
{
// We need to ensure the source UVs for generated lightmaps are available before generating then in the UStaticMesh::BatchBuild().
DatasmithStaticMeshBlueprintLibraryUtil::EnsureLightmapSourceUVsAreAvailable(StaticMeshes[Index]);
},
EParallelForFlags::Unbalanced
);
UStaticMesh::BatchBuild( StaticMeshes, true);
ParallelFor( StaticMeshes.Num(),
[&]( int32 Index )
{
Compute( WorkingSetKeys[Index], WorkingSet[WorkingSetKeys[Index]] );
Compute( StaticMeshes[Index], StaticMeshMap[StaticMeshes[Index]] );
},
EParallelForFlags::Unbalanced
);
@@ -347,7 +442,7 @@ void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution( const TArr
// Do not take any chance, compute sequentially
else
{
for(TPair< UStaticMesh*, TSet< UStaticMeshComponent* > >& Entry : WorkingSet)
for(const TPair< UStaticMesh*, TSet< UStaticMeshComponent* > >& Entry : StaticMeshMap)
{
Compute( Entry.Key, Entry.Value );
}
@@ -356,82 +451,63 @@ void UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution( const TArr
int32 UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution(UStaticMesh* StaticMesh, float IdealRatio, const FVector& StaticMeshScale)
{
if(StaticMesh == nullptr)
if(StaticMesh == nullptr || !StaticMesh->HasValidRenderData())
{
return 0;
}
DatasmithStaticMeshBlueprintLibraryUtil::EnsureLightmapUVsAreAvailable( StaticMesh );
const FRawStaticIndexBuffer& IndexBuffer = StaticMesh->RenderData->LODResources[0].IndexBuffer;
const FPositionVertexBuffer& PositionBuffer = StaticMesh->RenderData->LODResources[0].VertexBuffers.PositionVertexBuffer;
const FStaticMeshVertexBuffer& VertexBuffer = StaticMesh->RenderData->LODResources[0].VertexBuffers.StaticMeshVertexBuffer;
if ( const FMeshDescription* MeshDescription = StaticMesh->GetMeshDescription( 0 ) )
if (VertexBuffer.GetNumTexCoords() <= (uint32)StaticMesh->LightMapCoordinateIndex)
{
FStaticMeshConstAttributes Attributes(*MeshDescription);
// Compute the mesh UV density, based on FStaticMeshRenderData::ComputeUVDensities, except that we're working on a MeshDescription
const TVertexAttributesConstRef< FVector > VertexPositions = Attributes.GetVertexPositions();
const TVertexInstanceAttributesConstRef< FVector2D > VertexUVs = Attributes.GetVertexInstanceUVs();
if ( VertexUVs.GetNumElements() <= StaticMesh->LightMapCoordinateIndex )
{
return 0;
}
float MeshArea = 0.f;
float MeshUVArea = 0.f;
TArray< FVector2D > PolygonAreas;
for ( const FPolygonID PolygonID : MeshDescription->Polygons().GetElementIDs() )
{
float PolygonArea = 0.f;
float PolygonUVArea = 0.f;
const TArray< FTriangleID >& PolygonTriangleIDs = MeshDescription->GetPolygonTriangleIDs( PolygonID );
for ( const FTriangleID TriangleID : PolygonTriangleIDs )
{
FVector VertexPosition[3];
FVector2D LightmapUVs[3];
for ( int32 CornerIndex = 0; CornerIndex < 3; ++CornerIndex )
{
const FVertexInstanceID VertexInstanceID = MeshDescription->GetTriangleVertexInstance( TriangleID, CornerIndex );
VertexPosition[ CornerIndex ] = VertexPositions[ MeshDescription->GetVertexInstanceVertex( VertexInstanceID ) ] * StaticMeshScale;
LightmapUVs[ CornerIndex ] = VertexUVs.Get( VertexInstanceID, StaticMesh->LightMapCoordinateIndex );
}
PolygonArea += DatasmithStaticMeshBlueprintLibraryUtil::ParallelogramArea( VertexPosition[0], VertexPosition[1], VertexPosition[2] );
PolygonUVArea += DatasmithStaticMeshBlueprintLibraryUtil::ParallelogramArea( FVector( LightmapUVs[0], 0.f ), FVector( LightmapUVs[1], 0.f ), FVector( LightmapUVs[2], 0.f ) );
}
PolygonAreas.Emplace( FMath::Sqrt( PolygonArea ), FMath::Sqrt(PolygonArea / PolygonUVArea ) );
}
Algo::Sort( PolygonAreas, []( const FVector2D& ElementA, const FVector2D& ElementB )
{
return ElementA[1] < ElementB[1];
} );
float WeightedUVDensity = 0.f;
float Weight = 0.f;
// Remove 10% of higher and lower texel factors.
const int32 Threshold = FMath::FloorToInt( 0.1f * (float)PolygonAreas.Num() );
for (int32 Index = Threshold; Index < PolygonAreas.Num() - Threshold; ++Index)
{
WeightedUVDensity += PolygonAreas[ Index ][ 1 ] * PolygonAreas[ Index ][ 0 ];
Weight += PolygonAreas[ Index ][ 0 ];
}
float UVDensity = WeightedUVDensity / Weight;
int32 LightmapResolution = FMath::FloorToInt( UVDensity * IdealRatio );
// Ensure that LightmapResolution is a factor of 4
return FMath::Max( LightmapResolution + 3 & ~3, 4 );
return 0;
}
return 0;
// Compute the mesh UV density, based on FStaticMeshRenderData::ComputeUVDensities, except that we're only working the Lightmap UV.
TArray< FVector2D > PolygonAreas;
const int32 NumberOfTriangles = IndexBuffer.GetNumIndices() / 3;
for (int32 TriangleIndex = 0; TriangleIndex < NumberOfTriangles; ++TriangleIndex)
{
FVector VertexPosition[3];
FVector2D LightmapUVs[3];
for (int32 CornerIndex = 0; CornerIndex < 3; ++CornerIndex)
{
uint32 VertexIndex = IndexBuffer.GetIndex(TriangleIndex * 3 + CornerIndex);
VertexPosition[CornerIndex] = PositionBuffer.VertexPosition(VertexIndex);
LightmapUVs[CornerIndex] = VertexBuffer.GetVertexUV(VertexIndex, StaticMesh->LightMapCoordinateIndex);
}
const float PolygonArea = DatasmithStaticMeshBlueprintLibraryUtil::ParallelogramArea(VertexPosition[0], VertexPosition[1], VertexPosition[2]);
const float PolygonUVArea = DatasmithStaticMeshBlueprintLibraryUtil::ParallelogramArea(FVector(LightmapUVs[0], 0.f), FVector(LightmapUVs[1], 0.f), FVector(LightmapUVs[2], 0.f));
PolygonAreas.Emplace(FMath::Sqrt(PolygonArea), FMath::Sqrt(PolygonArea / PolygonUVArea));
}
Algo::Sort( PolygonAreas, []( const FVector2D& ElementA, const FVector2D& ElementB )
{
return ElementA[1] < ElementB[1];
} );
float WeightedUVDensity = 0.f;
float Weight = 0.f;
// Remove 10% of higher and lower texel factors.
const int32 Threshold = FMath::FloorToInt( 0.1f * (float)PolygonAreas.Num() );
for (int32 Index = Threshold; Index < PolygonAreas.Num() - Threshold; ++Index)
{
WeightedUVDensity += PolygonAreas[ Index ][ 1 ] * PolygonAreas[ Index ][ 0 ];
Weight += PolygonAreas[ Index ][ 0 ];
}
float UVDensity = WeightedUVDensity / Weight;
int32 LightmapResolution = FMath::FloorToInt( UVDensity * IdealRatio );
// Ensure that LightmapResolution is a factor of 4
return FMath::Max( LightmapResolution + 3 & ~3, 4 );
}
FDatasmithImportFactoryCreateFileResult::FDatasmithImportFactoryCreateFileResult()

View File

@@ -7,20 +7,14 @@
#define LOCTEXT_NAMESPACE "DatasmithDataprepOperation"
void UDatasmithComputeLightmapResolutionOperation::OnExecution_Implementation(const FDataprepContext& InContext)
void UDataprepSetupStaticLightingOperation::OnExecution_Implementation(const FDataprepContext& InContext)
{
// Collect start time to log amount of time spent to import incoming file
uint64 StartTime = FPlatformTime::Cycles64();
int32 ObjectsCount = InContext.Objects.Num();
#ifdef LOG_TIME
DataprepOperationTime::FTimeLogger TimeLogger(TEXT("SetupStaticLighting"), [&](FText Text) { this->LogInfo(Text); });
#endif
UDatasmithStaticMeshBlueprintLibrary::ComputeLightmapResolution( InContext.Objects, false, IdealRatio );
// Log time spent to import incoming file in minutes and seconds
double ElapsedSeconds = FPlatformTime::ToSeconds64(FPlatformTime::Cycles64() - StartTime);
int ElapsedMin = int(ElapsedSeconds / 60.0);
ElapsedSeconds -= 60.0 * (double)ElapsedMin;
UE_LOG( LogDatasmithImport, Log, TEXT("Computation of lightmap resolution of %d object(s) took [%d min %.3f s]"), ObjectsCount, ElapsedMin, ElapsedSeconds );
// Execute operation
UDatasmithStaticMeshBlueprintLibrary::SetupStaticLighting(InContext.Objects, false, bEnableLightmapUVGeneration, LightmapResolutionIdealRatio);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -8,20 +8,26 @@
#include "DatasmithDataprepOperation.generated.h"
UCLASS(Experimental, Category = MeshOperation, Meta = (DisplayName="Compute Lightmap Resolution", ToolTip = "For each static mesh to process, recompute the lilghtmap resolution based on the specified ratio") )
class UDatasmithComputeLightmapResolutionOperation : public UDataprepOperation
UCLASS(Experimental, Category = LightmapOptions, Meta = (DisplayName = "Setup Static Lighting", ToolTip = "For each static mesh to process, setup the settings to enable lightmap UVs generation and compute the lightmap resolution."))
class UDataprepSetupStaticLightingOperation : public UDataprepOperation
{
GENERATED_BODY()
UDatasmithComputeLightmapResolutionOperation()
: IdealRatio( 0.2f )
UDataprepSetupStaticLightingOperation()
: bEnableLightmapUVGeneration(true),
LightmapResolutionIdealRatio(0.2f)
{
}
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LightmapOptions )
float IdealRatio;
// The value to set for the generate lightmap uvs flag on each static mesh
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LightmapOptions, meta = (DisplayName = "Enable Lightmap UV Generation", ToolTip = "Enable the lightmap UV generation."))
bool bEnableLightmapUVGeneration;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LightmapOptions, meta = (DisplayName = "Resolution Ideal Ratio", ToolTip = "The ratio used to compute the resolution of the lightmap."))
float LightmapResolutionIdealRatio;
protected:
//~ Begin UDataprepOperation Interface
public:
virtual FText GetCategory_Implementation() const override
@@ -32,4 +38,4 @@ public:
protected:
virtual void OnExecution_Implementation(const FDataprepContext& InContext) override;
//~ End UDataprepOperation Interface
};
};

View File

@@ -104,6 +104,19 @@ public:
UFUNCTION(BlueprintCallable, Category = "Datasmith | Static Mesh")
static void ComputeLightmapResolution( const TArray< UObject* >& Objects, bool bApplyChanges, float IdealRatio = 0.2f );
/**
* Setup the Lightmap UVs settings to enable or disable the lightmap generation on the static meshes found in the Assets list
*
* @param Assets List of objects to set the generate lightmap uvs flag on. Only Static Meshes and Static Mesh Components will be affected.
* @param bApplyChanges Indicates if changes must be apply or not.
* @param bGenerateLightmapUVs The value to set for the generate lightmap uvs flag.
* @param LightmapResolutionIdealRatio The desired lightmap density ratio
*/
UFUNCTION(BlueprintCallable, Category = "Datasmith | Static Mesh")
static void SetupStaticLighting(const TArray< UObject* >& Objects, bool bApplyChanges, bool bGenerateLightmapUVs, float LightmapResolutionIdealRatio = 0.2f );
private:
static void ComputeLightmapResolution(const TMap< UStaticMesh*, TSet< UStaticMeshComponent* > >& StaticMeshMap, bool bApplyChanges, float IdealRatio = 0.2f);
static int32 ComputeLightmapResolution(UStaticMesh* StaticMesh, float IdealRatio, const FVector& StaticMeshScale);
};

View File

@@ -71,6 +71,13 @@ namespace DataprepOperationsLibraryUtil
{
SelectedMeshes.Add( StaticMesh );
}
else if ( UStaticMeshComponent* StaticMeshComponent = Cast<UStaticMeshComponent>(Object) )
{
if (UStaticMesh* StaticMesh = StaticMeshComponent->GetStaticMesh())
{
SelectedMeshes.Add(StaticMesh);
}
}
else if (AActor* Actor = Cast<AActor>(Object) )
{
TInlineComponentArray<UStaticMeshComponent*> StaticMeshComponents( Actor );
@@ -450,41 +457,6 @@ void UDataprepOperationsLibrary::SetConvexDecompositionCollision(const TArray<UO
}
}
void UDataprepOperationsLibrary::SetGenerateLightmapUVs( const TArray< UObject* >& Assets, bool bGenerateLightmapUVs, TArray<UObject*>& ModifiedObjects )
{
TSet<UStaticMesh*> SelectedMeshes = DataprepOperationsLibraryUtil::GetSelectedMeshes(Assets);
for (UStaticMesh* StaticMesh : SelectedMeshes)
{
if (StaticMesh)
{
bool bDidChangeSettings = false;
// 3 is the maximum that lightmass accept
int32 MinBiggestUVChannel = 3;
for ( FStaticMeshSourceModel& SourceModel : StaticMesh->GetSourceModels() )
{
bDidChangeSettings |= SourceModel.BuildSettings.bGenerateLightmapUVs != bGenerateLightmapUVs;
SourceModel.BuildSettings.bGenerateLightmapUVs = bGenerateLightmapUVs;
if( const FMeshDescription* MeshDescription = SourceModel.MeshDescription.Get() )
{
FStaticMeshConstAttributes Attributes(*MeshDescription);
int32 UVChannelCount = Attributes.GetVertexInstanceUVs().GetNumIndices();
MinBiggestUVChannel = FMath::Min( MinBiggestUVChannel, UVChannelCount - 1 );
}
}
if ( StaticMesh->LightMapCoordinateIndex > MinBiggestUVChannel && bDidChangeSettings )
{
// Correct the coordinate index if it was invalid
StaticMesh->LightMapCoordinateIndex = MinBiggestUVChannel;
}
ModifiedObjects.Add( StaticMesh );
}
}
}
void UDataprepOperationsLibrary::SubstituteMaterial(const TArray<UObject*>& SelectedObjects, const FString& MaterialSearch, EEditorScriptingStringMatchType StringMatch, UMaterialInterface* MaterialSubstitute)
{
TArray<UMaterialInterface*> MaterialsUsed = DataprepOperationsLibraryUtil::GetUsedMaterials(SelectedObjects);

View File

@@ -191,15 +191,6 @@ public:
UFUNCTION(BlueprintCallable, Category = "Dataprep | Operation")
static void SetConvexDecompositionCollision(const TArray<UObject*>& SelectedObjects, int32 HullCount, int32 MaxHullVerts, int32 HullPrecision, TArray<UObject*>& ModifiedObjects);
/**
* Sets the Generate Lightmap UVs flag on the static meshes found in the Assets list
*
* @param Assets List of assets to set the generate lightmap uvs flag on. Only Static Meshes will be affected.
* @param bGenerateLightmapUVs The value to set for the generate lightmap uvs flag.
*/
UFUNCTION(BlueprintCallable, Category = "Dataprep | Operation")
static void SetGenerateLightmapUVs( const TArray< UObject* >& Assets, bool bGenerateLightmapUVs, TArray<UObject*>& ModifiedObjects );
/**
* Replaces designated materials in all or specific content folders with specific ones
* @param SelectedObjects: Objects to consider for the substitution

View File

@@ -147,22 +147,6 @@ void UDataprepSetConvexDecompositionCollisionOperation::OnExecution_Implementati
}
}
void UDataprepSetGenerateLightmapUVsOperation::OnExecution_Implementation(const FDataprepContext& InContext)
{
#ifdef LOG_TIME
DataprepOperationTime::FTimeLogger TimeLogger( TEXT("SetGenerateLightmapUVs"), [&]( FText Text) { this->LogInfo( Text ); });
#endif
// Execute operation
TArray<UObject*> ModifiedStaticMeshes;
UDataprepOperationsLibrary::SetGenerateLightmapUVs( InContext.Objects, bGenerateLightmapUVs, ModifiedStaticMeshes );
if(ModifiedStaticMeshes.Num() > 0)
{
AssetsModified( MoveTemp( ModifiedStaticMeshes ) );
}
}
void UDataprepSetMobilityOperation::OnExecution_Implementation(const FDataprepContext& InContext)
{
#ifdef LOG_TIME

View File

@@ -163,34 +163,6 @@ protected:
//~ End UDataprepOperation Interface
};
UCLASS(Experimental, Category = MeshOperation, Meta = (DisplayName="Enable Lightmap UVs", ToolTip = "For each static mesh to process, enable or disable the generation of lightmap UVs") )
class UDataprepSetGenerateLightmapUVsOperation : public UDataprepOperation
{
GENERATED_BODY()
UDataprepSetGenerateLightmapUVsOperation()
: bGenerateLightmapUVs(true)
{
}
public:
// The value to set for the generate lightmap uvs flag on each static mesh
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MeshOperation, meta = (ToolTip = "Maximum number of convex pieces that will be created"))
bool bGenerateLightmapUVs;
protected:
//~ Begin UDataprepOperation Interface
public:
virtual FText GetCategory_Implementation() const override
{
return FDataprepOperationCategories::MeshOperation;
}
protected:
virtual void OnExecution_Implementation(const FDataprepContext& InContext) override;
//~ End UDataprepOperation Interface
};
UCLASS(Experimental, Category = ActorOperation, Meta = (DisplayName="Set Mobility", ToolTip = "For each mesh actor to process, update its mobilty with the selected value") )
class UDataprepSetMobilityOperation : public UDataprepOperation
{