2021-09-13 17:51:19 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "BakeMeshAttributeMapsToolBase.h"
|
|
|
|
|
#include "InteractiveToolManager.h"
|
|
|
|
|
#include "ToolBuilderUtil.h"
|
2021-10-07 22:25:54 -04:00
|
|
|
#include "ToolSetupUtil.h"
|
2021-09-13 17:51:19 -04:00
|
|
|
|
|
|
|
|
#include "DynamicMesh/DynamicMesh3.h"
|
|
|
|
|
#include "DynamicMesh/DynamicMeshAttributeSet.h"
|
|
|
|
|
#include "Materials/Material.h"
|
|
|
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
|
|
|
#include "ImageUtils.h"
|
|
|
|
|
|
|
|
|
|
#include "Sampling/MeshOcclusionMapEvaluator.h"
|
|
|
|
|
#include "Sampling/MeshPropertyMapEvaluator.h"
|
|
|
|
|
|
|
|
|
|
#include "AssetUtils/Texture2DBuilder.h"
|
|
|
|
|
#include "AssetUtils/Texture2DUtil.h"
|
|
|
|
|
|
|
|
|
|
#include "TargetInterfaces/MaterialProvider.h"
|
|
|
|
|
#include "ModelingToolTargetUtil.h"
|
2021-11-02 13:58:07 -04:00
|
|
|
#include "ModelingObjectsCreationAPI.h"
|
|
|
|
|
|
|
|
|
|
#include "EngineAnalytics.h"
|
2021-09-13 17:51:19 -04:00
|
|
|
|
|
|
|
|
#include "ExplicitUseGeometryMathTypes.h" // using UE::Geometry::(math types)
|
2021-11-02 13:58:07 -04:00
|
|
|
#include "Sampling/MeshCurvatureMapEvaluator.h"
|
|
|
|
|
#include "Sampling/MeshResampleImageEvaluator.h"
|
2021-09-13 17:51:19 -04:00
|
|
|
using namespace UE::Geometry;
|
|
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "UBakeMeshAttributeMapsToolBase"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::Setup()
|
|
|
|
|
{
|
|
|
|
|
Super::Setup();
|
|
|
|
|
|
|
|
|
|
InitializeEmptyMaps();
|
|
|
|
|
|
|
|
|
|
// Setup preview materials
|
|
|
|
|
UMaterial* Material = LoadObject<UMaterial>(nullptr, TEXT("/MeshModelingToolsetExp/Materials/BakePreviewMaterial"));
|
|
|
|
|
check(Material);
|
|
|
|
|
if (Material != nullptr)
|
|
|
|
|
{
|
|
|
|
|
PreviewMaterial = UMaterialInstanceDynamic::Create(Material, GetToolManager());
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), EmptyNormalMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), EmptyColorMapWhite);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), EmptyColorMapWhite);
|
|
|
|
|
}
|
|
|
|
|
UMaterial* BentNormalMaterial = LoadObject<UMaterial>(nullptr, TEXT("/MeshModelingToolsetExp/Materials/BakeBentNormalPreviewMaterial"));
|
|
|
|
|
check(BentNormalMaterial);
|
|
|
|
|
if (BentNormalMaterial != nullptr)
|
|
|
|
|
{
|
|
|
|
|
BentNormalPreviewMaterial = UMaterialInstanceDynamic::Create(BentNormalMaterial, GetToolManager());
|
|
|
|
|
}
|
|
|
|
|
UMaterial* WorkingMaterial = LoadObject<UMaterial>(nullptr, TEXT("/MeshModelingToolsetExp/Materials/InProgressMaterial"));
|
|
|
|
|
check(WorkingMaterial);
|
|
|
|
|
if (WorkingMaterial != nullptr)
|
|
|
|
|
{
|
|
|
|
|
WorkingPreviewMaterial = UMaterialInstanceDynamic::Create(WorkingMaterial, GetToolManager());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize preview mesh
|
|
|
|
|
UE::ToolTarget::HideSourceObject(Targets[0]);
|
|
|
|
|
|
|
|
|
|
const FDynamicMesh3 InputMesh = UE::ToolTarget::GetDynamicMeshCopy(Targets[0], true);
|
|
|
|
|
const UE::Geometry::FTransform3d BaseToWorld = UE::ToolTarget::GetLocalToWorldTransform(Targets[0]);
|
|
|
|
|
PreviewMesh = NewObject<UPreviewMesh>(this);
|
|
|
|
|
PreviewMesh->CreateInWorld(TargetWorld, FTransform::Identity);
|
2021-10-07 22:25:54 -04:00
|
|
|
ToolSetupUtil::ApplyRenderingConfigurationToPreview(PreviewMesh, nullptr);
|
2021-09-13 17:51:19 -04:00
|
|
|
PreviewMesh->SetTransform(static_cast<FTransform>(BaseToWorld));
|
|
|
|
|
PreviewMesh->SetTangentsMode(EDynamicMeshComponentTangentsMode::ExternallyProvided);
|
|
|
|
|
PreviewMesh->ReplaceMesh(InputMesh);
|
|
|
|
|
PreviewMesh->SetMaterials(UE::ToolTarget::GetMaterialSet(Targets[0]).Materials);
|
|
|
|
|
PreviewMesh->SetOverrideRenderMaterial(PreviewMaterial);
|
|
|
|
|
PreviewMesh->SetVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::PostSetup()
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
|
|
|
|
VisualizationProps = NewObject<UBakedOcclusionMapVisualizationProperties>(this);
|
|
|
|
|
VisualizationProps->RestoreProperties(this);
|
|
|
|
|
AddToolPropertySource(VisualizationProps);
|
2021-11-02 13:58:07 -04:00
|
|
|
|
|
|
|
|
GatherAnalytics(BakeAnalytics.MeshSettings);
|
2021-09-13 17:51:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::Shutdown(EToolShutdownType ShutdownType)
|
|
|
|
|
{
|
|
|
|
|
VisualizationProps->SaveProperties(this);
|
|
|
|
|
|
|
|
|
|
if (PreviewMesh != nullptr)
|
|
|
|
|
{
|
|
|
|
|
PreviewMesh->SetVisible(false);
|
|
|
|
|
PreviewMesh->Disconnect();
|
|
|
|
|
PreviewMesh = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE::ToolTarget::ShowSourceObject(Targets[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::OnTick(float DeltaTime)
|
|
|
|
|
{
|
|
|
|
|
if (Compute)
|
|
|
|
|
{
|
|
|
|
|
Compute->Tick(DeltaTime);
|
|
|
|
|
|
|
|
|
|
float ElapsedComputeTime = Compute->GetElapsedComputeTime();
|
|
|
|
|
if (!CanAccept() && ElapsedComputeTime > SecondsBeforeWorkingMaterial)
|
|
|
|
|
{
|
|
|
|
|
PreviewMesh->SetOverrideRenderMaterial(WorkingPreviewMaterial);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::Render(IToolsContextRenderAPI* RenderAPI)
|
|
|
|
|
{
|
|
|
|
|
UpdateResult();
|
|
|
|
|
|
|
|
|
|
float GrayLevel = VisualizationProps->BaseGrayLevel;
|
|
|
|
|
PreviewMaterial->SetVectorParameterValue(TEXT("BaseColor"), FVector(GrayLevel, GrayLevel, GrayLevel) );
|
|
|
|
|
float AOWeight = VisualizationProps->OcclusionMultiplier;
|
|
|
|
|
PreviewMaterial->SetScalarParameterValue(TEXT("AOWeight"), AOWeight );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TUniquePtr<UE::Geometry::TGenericDataOperator<FMeshMapBaker>> UBakeMeshAttributeMapsToolBase::MakeNewOperator()
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::SetWorld(UWorld* World)
|
|
|
|
|
{
|
|
|
|
|
TargetWorld = World;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
|
2021-09-13 17:51:19 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::UpdateResult()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
|
2021-09-13 17:51:19 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::UpdateVisualization()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::InvalidateCompute()
|
|
|
|
|
{
|
2021-11-03 21:48:49 -04:00
|
|
|
const bool bInvalidate = static_cast<bool>(OpState & EBakeOpState::Evaluate);
|
2021-11-02 13:58:07 -04:00
|
|
|
if (!Compute)
|
|
|
|
|
{
|
|
|
|
|
Compute = MakeUnique<TGenericDataBackgroundCompute<FMeshMapBaker>>();
|
|
|
|
|
Compute->Setup(this);
|
|
|
|
|
Compute->OnResultUpdated.AddLambda([this](const TUniquePtr<FMeshMapBaker>& NewResult) { OnMapsUpdated(NewResult); });
|
|
|
|
|
Compute->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
else if (bInvalidate)
|
|
|
|
|
{
|
|
|
|
|
Compute->InvalidateResult();
|
|
|
|
|
}
|
2021-11-03 21:48:49 -04:00
|
|
|
OpState = EBakeOpState::Clean;
|
2021-11-02 13:58:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::CreateTextureAssets(const TMap<EBakeMapType, TObjectPtr<UTexture2D>>& Textures, UWorld* SourceWorld, UObject* SourceAsset)
|
|
|
|
|
{
|
|
|
|
|
bool bCreatedAssetOK = true;
|
|
|
|
|
const FString BaseName = UE::ToolTarget::GetTargetActor(Targets[0])->GetActorNameOrLabel();
|
|
|
|
|
for (const TTuple<EBakeMapType, TObjectPtr<UTexture2D>>& Result : Textures)
|
|
|
|
|
{
|
|
|
|
|
FString TexName;
|
|
|
|
|
GetTextureName(Result.Get<0>(), BaseName, TexName);
|
|
|
|
|
bCreatedAssetOK = bCreatedAssetOK &&
|
|
|
|
|
UE::Modeling::CreateTextureObject(
|
|
|
|
|
GetToolManager(),
|
|
|
|
|
FCreateTextureObjectParams{ 0, SourceWorld, SourceAsset, TexName, Result.Get<1>() }).IsOK();
|
|
|
|
|
}
|
|
|
|
|
ensure(bCreatedAssetOK);
|
|
|
|
|
|
|
|
|
|
RecordAnalytics(BakeAnalytics, GetAnalyticsEventName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-10-21 10:53:58 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::UpdatePreview(const EBakeMapType PreviewMapType)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
|
|
|
|
if (PreviewMapType == EBakeMapType::None)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-10-21 10:53:58 -04:00
|
|
|
|
|
|
|
|
if (!CachedMaps.Contains(PreviewMapType))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-09-13 17:51:19 -04:00
|
|
|
|
2021-10-21 10:53:58 -04:00
|
|
|
UTexture2D* PreviewMap = CachedMaps[PreviewMapType];
|
2021-09-13 17:51:19 -04:00
|
|
|
switch (PreviewMapType)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), EmptyNormalMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), EmptyColorMapWhite);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), EmptyColorMapWhite);
|
|
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::TangentSpaceNormal:
|
2021-09-13 17:51:19 -04:00
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), PreviewMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), EmptyColorMapWhite);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), EmptyColorMapWhite);
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::AmbientOcclusion:
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), EmptyNormalMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), PreviewMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), EmptyColorMapWhite);
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::BentNormal:
|
|
|
|
|
{
|
2021-10-21 10:53:58 -04:00
|
|
|
UTexture2D* AOMap = CachedMaps.Contains(EBakeMapType::AmbientOcclusion) ? CachedMaps[EBakeMapType::AmbientOcclusion] : EmptyColorMapWhite;
|
2021-09-13 17:51:19 -04:00
|
|
|
BentNormalPreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), EmptyNormalMap);
|
|
|
|
|
BentNormalPreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), AOMap);
|
|
|
|
|
BentNormalPreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), EmptyColorMapWhite);
|
|
|
|
|
BentNormalPreviewMaterial->SetTextureParameterValue(TEXT("BentNormalMap"), PreviewMap);
|
|
|
|
|
PreviewMesh->SetOverrideRenderMaterial(BentNormalPreviewMaterial);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EBakeMapType::Curvature:
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::ObjectSpaceNormal:
|
|
|
|
|
case EBakeMapType::FaceNormal:
|
|
|
|
|
case EBakeMapType::Position:
|
2021-09-13 17:51:19 -04:00
|
|
|
case EBakeMapType::MaterialID:
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::Texture:
|
2021-09-13 17:51:19 -04:00
|
|
|
case EBakeMapType::MultiTexture:
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::VertexColor:
|
2021-09-13 17:51:19 -04:00
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("NormalMap"), EmptyNormalMap);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("OcclusionMap"), EmptyColorMapWhite);
|
|
|
|
|
PreviewMaterial->SetTextureParameterValue(TEXT("ColorMap"), PreviewMap);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::OnMapsUpdated(const TUniquePtr<UE::Geometry::FMeshMapBaker>& NewResult)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-11-02 13:58:07 -04:00
|
|
|
const FImageDimensions BakeDimensions = NewResult->GetDimensions();
|
|
|
|
|
const EBakeTextureFormat Format = CachedBakeCacheSettings.SourceFormat;
|
2021-09-15 20:13:36 -04:00
|
|
|
const int32 NumEval = NewResult->NumEvaluators();
|
|
|
|
|
for (int32 EvalIdx = 0; EvalIdx < NumEval; ++EvalIdx)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-09-15 20:13:36 -04:00
|
|
|
FMeshMapEvaluator* Eval = NewResult->GetEvaluator(EvalIdx);
|
2021-09-13 17:51:19 -04:00
|
|
|
|
2021-10-15 11:49:51 -04:00
|
|
|
auto UpdateCachedMap = [this, &NewResult, &EvalIdx, &BakeDimensions](const EBakeMapType MapType, const EBakeTextureFormat MapFormat, const int32 ResultIdx) -> void
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
// For 8-bit color textures, ensure that the source data is in sRGB.
|
2021-10-15 11:49:51 -04:00
|
|
|
const FTexture2DBuilder::ETextureType TexType = GetTextureType(MapType, MapFormat);
|
2021-10-05 13:56:51 -04:00
|
|
|
const bool bConvertToSRGB = TexType == FTexture2DBuilder::ETextureType::Color;
|
2021-10-15 11:49:51 -04:00
|
|
|
const ETextureSourceFormat SourceDataFormat = MapFormat == EBakeTextureFormat::ChannelBits16 ? TSF_RGBA16F : TSF_BGRA8;
|
|
|
|
|
|
2021-09-13 17:51:19 -04:00
|
|
|
FTexture2DBuilder TextureBuilder;
|
|
|
|
|
TextureBuilder.Initialize(TexType, BakeDimensions);
|
2021-10-05 13:56:51 -04:00
|
|
|
TextureBuilder.Copy(*NewResult->GetBakeResults(EvalIdx)[ResultIdx], bConvertToSRGB);
|
2021-09-13 17:51:19 -04:00
|
|
|
TextureBuilder.Commit(false);
|
|
|
|
|
|
2021-10-15 11:49:51 -04:00
|
|
|
// Copy image to source data after commit. This will avoid incurring
|
|
|
|
|
// the cost of hitting the DDC for texture compile while iterating on
|
|
|
|
|
// bake settings. Since this dirties the texture, the next time the texture
|
|
|
|
|
// is used after accepting the final texture, the DDC will trigger and
|
|
|
|
|
// properly recompile the platform data.
|
|
|
|
|
const bool bConvertSourceToSRGB = bConvertToSRGB && SourceDataFormat == TSF_BGRA8;
|
|
|
|
|
TextureBuilder.CopyImageToSourceData(*NewResult->GetBakeResults(EvalIdx)[ResultIdx], SourceDataFormat, bConvertSourceToSRGB);
|
|
|
|
|
|
2021-10-21 10:53:58 -04:00
|
|
|
// The CachedMap can be thrown out of sync if updated during a background
|
|
|
|
|
// compute. Validate the computed type against our cached maps.
|
|
|
|
|
if (CachedMaps.Contains(MapType))
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-10-21 10:53:58 -04:00
|
|
|
CachedMaps[MapType] = TextureBuilder.GetTexture2D();
|
2021-09-13 17:51:19 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-15 20:13:36 -04:00
|
|
|
switch (Eval->Type())
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
|
|
|
|
case EMeshMapEvaluatorType::Normal:
|
|
|
|
|
{
|
2021-10-21 10:53:58 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::TangentSpaceNormal;
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, 0);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::Occlusion:
|
|
|
|
|
{
|
|
|
|
|
// Occlusion Evaluator always outputs AmbientOcclusion then BentNormal.
|
2021-09-15 20:13:36 -04:00
|
|
|
const FMeshOcclusionMapEvaluator* OcclusionEval = static_cast<FMeshOcclusionMapEvaluator*>(Eval);
|
2021-09-13 17:51:19 -04:00
|
|
|
int32 OcclusionIdx = 0;
|
2021-09-15 20:13:36 -04:00
|
|
|
if ((bool)(OcclusionEval->OcclusionType & EMeshOcclusionMapType::AmbientOcclusion))
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::AmbientOcclusion;
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, OcclusionIdx++);
|
2021-09-13 17:51:19 -04:00
|
|
|
}
|
2021-09-15 20:13:36 -04:00
|
|
|
if ((bool)(OcclusionEval->OcclusionType & EMeshOcclusionMapType::BentNormal))
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::BentNormal;
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, OcclusionIdx++);
|
2021-09-13 17:51:19 -04:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::Curvature:
|
|
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::Curvature;
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, 0);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::Property:
|
|
|
|
|
{
|
2021-09-15 20:13:36 -04:00
|
|
|
const FMeshPropertyMapEvaluator* PropertyEval = static_cast<FMeshPropertyMapEvaluator*>(Eval);
|
2021-09-13 17:51:19 -04:00
|
|
|
EBakeMapType MapType = EBakeMapType::None;
|
2021-09-15 20:13:36 -04:00
|
|
|
switch (PropertyEval->Property)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
|
|
|
|
case EMeshPropertyMapType::Normal:
|
2021-10-21 10:53:58 -04:00
|
|
|
MapType = EBakeMapType::ObjectSpaceNormal;
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EMeshPropertyMapType::FacetNormal:
|
2021-10-21 10:53:58 -04:00
|
|
|
MapType = EBakeMapType::FaceNormal;
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EMeshPropertyMapType::Position:
|
2021-10-21 10:53:58 -04:00
|
|
|
MapType = EBakeMapType::Position;
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EMeshPropertyMapType::MaterialID:
|
|
|
|
|
MapType = EBakeMapType::MaterialID;
|
|
|
|
|
break;
|
|
|
|
|
case EMeshPropertyMapType::VertexColor:
|
2021-10-21 10:53:58 -04:00
|
|
|
MapType = EBakeMapType::VertexColor;
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EMeshPropertyMapType::UVPosition:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, 0);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::ResampleImage:
|
|
|
|
|
{
|
2021-10-21 10:53:58 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::Texture;
|
|
|
|
|
UpdateCachedMap(MapType, Format, 0);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::MultiResampleImage:
|
|
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
constexpr EBakeMapType MapType = EBakeMapType::MultiTexture;
|
2021-10-15 11:49:51 -04:00
|
|
|
UpdateCachedMap(MapType, Format, 0);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
GatherAnalytics(*NewResult, CachedBakeCacheSettings, BakeAnalytics);
|
2021-09-13 17:51:19 -04:00
|
|
|
UpdateVisualization();
|
|
|
|
|
GetToolManager()->PostInvalidation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EBakeMapType UBakeMeshAttributeMapsToolBase::GetMapTypes(const int32& MapTypes)
|
|
|
|
|
{
|
2021-10-21 10:53:58 -04:00
|
|
|
EBakeMapType OutMapTypes = static_cast<EBakeMapType>(MapTypes);
|
2021-09-13 17:51:19 -04:00
|
|
|
// Force AO bake for BentNormal preview
|
|
|
|
|
if ((bool)(OutMapTypes & EBakeMapType::BentNormal))
|
|
|
|
|
{
|
|
|
|
|
OutMapTypes |= EBakeMapType::AmbientOcclusion;
|
|
|
|
|
}
|
|
|
|
|
return OutMapTypes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-10-15 11:49:51 -04:00
|
|
|
FTexture2DBuilder::ETextureType UBakeMeshAttributeMapsToolBase::GetTextureType(const EBakeMapType MapType, const EBakeTextureFormat MapFormat)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
2021-10-05 13:56:51 -04:00
|
|
|
FTexture2DBuilder::ETextureType TexType = FTexture2DBuilder::ETextureType::Color;
|
2021-09-13 17:51:19 -04:00
|
|
|
switch (MapType)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
checkNoEntry();
|
|
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::TangentSpaceNormal:
|
2021-09-13 17:51:19 -04:00
|
|
|
TexType = FTexture2DBuilder::ETextureType::NormalMap;
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::AmbientOcclusion:
|
|
|
|
|
TexType = FTexture2DBuilder::ETextureType::AmbientOcclusion;
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::BentNormal:
|
|
|
|
|
TexType = FTexture2DBuilder::ETextureType::NormalMap;
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::Curvature:
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::ObjectSpaceNormal:
|
|
|
|
|
case EBakeMapType::FaceNormal:
|
|
|
|
|
case EBakeMapType::Position:
|
2021-10-05 13:56:51 -04:00
|
|
|
TexType = FTexture2DBuilder::ETextureType::ColorLinear;
|
|
|
|
|
break;
|
2021-09-13 17:51:19 -04:00
|
|
|
case EBakeMapType::MaterialID:
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::VertexColor:
|
2021-10-15 11:49:51 -04:00
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::Texture:
|
2021-09-13 17:51:19 -04:00
|
|
|
case EBakeMapType::MultiTexture:
|
2021-10-15 11:49:51 -04:00
|
|
|
// For texture output with 16-bit source data, output HDR texture
|
|
|
|
|
if (MapFormat == EBakeTextureFormat::ChannelBits16)
|
|
|
|
|
{
|
|
|
|
|
TexType = FTexture2DBuilder::ETextureType::EmissiveHDR;
|
|
|
|
|
}
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return TexType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-10-05 13:56:51 -04:00
|
|
|
void UBakeMeshAttributeMapsToolBase::GetTextureName(const EBakeMapType MapType, const FString& BaseName, FString& TexName)
|
2021-09-13 17:51:19 -04:00
|
|
|
{
|
|
|
|
|
switch (MapType)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
checkNoEntry();
|
|
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::TangentSpaceNormal:
|
2021-09-13 17:51:19 -04:00
|
|
|
TexName = FString::Printf(TEXT("%s_Normals"), *BaseName);
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::AmbientOcclusion:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_Occlusion"), *BaseName);
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::BentNormal:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_BentNormal"), *BaseName);
|
|
|
|
|
break;
|
|
|
|
|
case EBakeMapType::Curvature:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_Curvature"), *BaseName);
|
|
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::ObjectSpaceNormal:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_NormalsObject"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::FaceNormal:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_FaceNormal"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EBakeMapType::MaterialID:
|
2021-10-21 10:53:58 -04:00
|
|
|
TexName = FString::Printf(TEXT("%s_MaterialID"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::VertexColor:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_VertexColorID"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::Position:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_Position"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
2021-10-21 10:53:58 -04:00
|
|
|
case EBakeMapType::Texture:
|
|
|
|
|
TexName = FString::Printf(TEXT("%s_Texture"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
case EBakeMapType::MultiTexture:
|
2021-10-21 10:53:58 -04:00
|
|
|
TexName = FString::Printf(TEXT("%s_MultiTexture"), *BaseName);
|
2021-09-13 17:51:19 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int UBakeMeshAttributeMapsToolBase::SelectColorTextureToBake(const TArray<UTexture*>& Textures)
|
|
|
|
|
{
|
|
|
|
|
TArray<int> TextureVotes;
|
|
|
|
|
TextureVotes.Init(0, Textures.Num());
|
|
|
|
|
|
|
|
|
|
for (int TextureIndex = 0; TextureIndex < Textures.Num(); ++TextureIndex)
|
|
|
|
|
{
|
|
|
|
|
UTexture* Tex = Textures[TextureIndex];
|
|
|
|
|
UTexture2D* Tex2D = Cast<UTexture2D>(Tex);
|
|
|
|
|
|
|
|
|
|
if (Tex2D)
|
|
|
|
|
{
|
|
|
|
|
// Texture uses SRGB
|
|
|
|
|
if (Tex->SRGB != 0)
|
|
|
|
|
{
|
|
|
|
|
++TextureVotes[TextureIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
|
// Texture has multiple channels
|
|
|
|
|
ETextureSourceFormat Format = Tex->Source.GetFormat();
|
|
|
|
|
if (Format == TSF_BGRA8 || Format == TSF_BGRE8 || Format == TSF_RGBA16 || Format == TSF_RGBA16F)
|
|
|
|
|
{
|
|
|
|
|
++TextureVotes[TextureIndex];
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// What else? Largest texture? Most layers? Most mipmaps?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MaxIndex = -1;
|
|
|
|
|
int MaxVotes = -1;
|
|
|
|
|
for (int TextureIndex = 0; TextureIndex < Textures.Num(); ++TextureIndex)
|
|
|
|
|
{
|
|
|
|
|
if (TextureVotes[TextureIndex] > MaxVotes)
|
|
|
|
|
{
|
|
|
|
|
MaxIndex = TextureIndex;
|
|
|
|
|
MaxVotes = TextureVotes[TextureIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MaxIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::InitializeEmptyMaps()
|
|
|
|
|
{
|
|
|
|
|
FTexture2DBuilder NormalsBuilder;
|
|
|
|
|
NormalsBuilder.Initialize(FTexture2DBuilder::ETextureType::NormalMap, FImageDimensions(16, 16));
|
|
|
|
|
NormalsBuilder.Commit(false);
|
|
|
|
|
EmptyNormalMap = NormalsBuilder.GetTexture2D();
|
|
|
|
|
|
|
|
|
|
FTexture2DBuilder ColorBuilderBlack;
|
|
|
|
|
ColorBuilderBlack.Initialize(FTexture2DBuilder::ETextureType::Color, FImageDimensions(16, 16));
|
|
|
|
|
ColorBuilderBlack.Clear(FColor(0,0,0));
|
|
|
|
|
ColorBuilderBlack.Commit(false);
|
|
|
|
|
EmptyColorMapBlack = ColorBuilderBlack.GetTexture2D();
|
|
|
|
|
|
|
|
|
|
FTexture2DBuilder ColorBuilderWhite;
|
|
|
|
|
ColorBuilderWhite.Initialize(FTexture2DBuilder::ETextureType::Color, FImageDimensions(16, 16));
|
|
|
|
|
ColorBuilderWhite.Clear(FColor::White);
|
|
|
|
|
ColorBuilderWhite.Commit(false);
|
|
|
|
|
EmptyColorMapWhite = ColorBuilderWhite.GetTexture2D();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-02 13:58:07 -04:00
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::GatherAnalytics(FBakeAnalytics::FMeshSettings& Data)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::GatherAnalytics(const FMeshMapBaker& Result, const FBakeCacheSettings& Settings, FBakeAnalytics& Data)
|
|
|
|
|
{
|
|
|
|
|
if (!FEngineAnalytics::IsAvailable())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Data.TotalBakeDuration = Result.BakeAnalytics.TotalBakeDuration;
|
|
|
|
|
Data.WriteToImageDuration = Result.BakeAnalytics.WriteToImageDuration;
|
|
|
|
|
Data.WriteToGutterDuration = Result.BakeAnalytics.WriteToGutterDuration;
|
|
|
|
|
Data.NumBakedPixels = Result.BakeAnalytics.NumBakedPixels;
|
|
|
|
|
Data.NumGutterPixels = Result.BakeAnalytics.NumGutterPixels;
|
|
|
|
|
Data.BakeSettings = Settings;
|
|
|
|
|
|
|
|
|
|
const int NumEvaluators = Result.NumEvaluators();
|
|
|
|
|
for (int EvalId = 0; EvalId < NumEvaluators; ++EvalId)
|
|
|
|
|
{
|
|
|
|
|
FMeshMapEvaluator* Eval = Result.GetEvaluator(EvalId);
|
|
|
|
|
switch(Eval->Type())
|
|
|
|
|
{
|
|
|
|
|
case EMeshMapEvaluatorType::Occlusion:
|
|
|
|
|
{
|
|
|
|
|
const FMeshOcclusionMapEvaluator* OcclusionEval = static_cast<FMeshOcclusionMapEvaluator*>(Eval);
|
|
|
|
|
Data.OcclusionSettings.OcclusionRays = OcclusionEval->NumOcclusionRays;
|
|
|
|
|
Data.OcclusionSettings.MaxDistance = OcclusionEval->MaxDistance;
|
|
|
|
|
Data.OcclusionSettings.SpreadAngle = OcclusionEval->SpreadAngle;
|
|
|
|
|
Data.OcclusionSettings.BiasAngle = OcclusionEval->BiasAngleDeg;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case EMeshMapEvaluatorType::Curvature:
|
|
|
|
|
{
|
|
|
|
|
const FMeshCurvatureMapEvaluator* CurvatureEval = static_cast<FMeshCurvatureMapEvaluator*>(Eval);
|
|
|
|
|
Data.CurvatureSettings.CurvatureType = static_cast<int>(CurvatureEval->UseCurvatureType);
|
|
|
|
|
Data.CurvatureSettings.RangeMultiplier = CurvatureEval->RangeScale;
|
|
|
|
|
Data.CurvatureSettings.MinRangeMultiplier = CurvatureEval->MinRangeScale;
|
|
|
|
|
Data.CurvatureSettings.ColorMode = static_cast<int>(CurvatureEval->UseColorMode);
|
|
|
|
|
Data.CurvatureSettings.ClampMode = static_cast<int>(CurvatureEval->UseClampMode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBakeMeshAttributeMapsToolBase::RecordAnalytics(const FBakeAnalytics& Data, const FString& EventName)
|
|
|
|
|
{
|
|
|
|
|
if (!FEngineAnalytics::IsAvailable())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TArray<FAnalyticsEventAttribute> Attributes;
|
|
|
|
|
|
|
|
|
|
// General
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Bake.Duration.Total.Seconds"), Data.TotalBakeDuration));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Bake.Duration.WriteToImage.Seconds"), Data.WriteToImageDuration));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Bake.Duration.WriteToGutter.Seconds"), Data.WriteToGutterDuration));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Bake.Stats.NumBakedPixels"), Data.NumBakedPixels));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Bake.Stats.NumGutterPixels"), Data.NumGutterPixels));
|
|
|
|
|
|
|
|
|
|
// Mesh data
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Input.TargetMesh.NumTriangles"), Data.MeshSettings.NumTargetMeshTris));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Input.DetailMesh.NumMeshes"), Data.MeshSettings.NumDetailMesh));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Input.DetailMesh.NumTriangles"), Data.MeshSettings.NumDetailMeshTris));
|
|
|
|
|
|
|
|
|
|
// Bake settings
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Image.Width"), Data.BakeSettings.Dimensions.GetWidth()));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Image.Height"), Data.BakeSettings.Dimensions.GetHeight()));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Multisampling"), Data.BakeSettings.Multisampling));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Thickness"), Data.BakeSettings.Thickness));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.UVLayer"), Data.BakeSettings.UVLayer));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.UseWorldSpace"), Data.BakeSettings.bUseWorldSpace));
|
|
|
|
|
|
|
|
|
|
// Map types
|
|
|
|
|
const bool bTangentSpaceNormal = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::TangentSpaceNormal);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.TangentSpaceNormal.Enabled"), bTangentSpaceNormal));
|
|
|
|
|
|
|
|
|
|
const bool bAmbientOcclusion = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::AmbientOcclusion);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.AmbientOcclusion.Enabled"), bAmbientOcclusion));
|
|
|
|
|
if (bAmbientOcclusion)
|
|
|
|
|
{
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.AmbientOcclusion.OcclusionRays"), Data.OcclusionSettings.OcclusionRays));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.AmbientOcclusion.MaxDistance"), Data.OcclusionSettings.MaxDistance));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.AmbientOcclusion.SpreadAngle"), Data.OcclusionSettings.SpreadAngle));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.AmbientOcclusion.BiasAngle"), Data.OcclusionSettings.BiasAngle));
|
|
|
|
|
}
|
|
|
|
|
const bool bBentNormal = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::BentNormal);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.BentNormal.Enabled"), bBentNormal));
|
|
|
|
|
if (bBentNormal)
|
|
|
|
|
{
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.BentNormal.OcclusionRays"), Data.OcclusionSettings.OcclusionRays));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.BentNormal.MaxDistance"), Data.OcclusionSettings.MaxDistance));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.BentNormal.SpreadAngle"), Data.OcclusionSettings.SpreadAngle));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bCurvature = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::Curvature);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.Enabled"), bCurvature));
|
|
|
|
|
if (bCurvature)
|
|
|
|
|
{
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.CurvatureType"), Data.CurvatureSettings.CurvatureType));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.RangeMultiplier"), Data.CurvatureSettings.RangeMultiplier));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.MinRangeMultiplier"), Data.CurvatureSettings.MinRangeMultiplier));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.ClampMode"), Data.CurvatureSettings.ClampMode));
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Curvature.ColorMode"), Data.CurvatureSettings.ColorMode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bObjectSpaceNormal = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::ObjectSpaceNormal);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.ObjectSpaceNormal.Enabled"), bObjectSpaceNormal));
|
|
|
|
|
|
|
|
|
|
const bool bFaceNormal = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::FaceNormal);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.FaceNormal.Enabled"), bFaceNormal));
|
|
|
|
|
|
|
|
|
|
const bool bPosition = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::Position);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Position.Enabled"), bPosition));
|
|
|
|
|
|
|
|
|
|
const bool bMaterialID = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::MaterialID);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.MaterialID.Enabled"), bMaterialID));
|
|
|
|
|
|
|
|
|
|
const bool bTexture = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::Texture);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.Texture.Enabled"), bTexture));
|
|
|
|
|
|
|
|
|
|
const bool bMultiTexture = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::MultiTexture);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.MultiTexture.Enabled"), bMultiTexture));
|
|
|
|
|
|
|
|
|
|
const bool bVertexColor = static_cast<bool>(Data.BakeSettings.SourceBakeMapTypes & EBakeMapType::VertexColor);
|
|
|
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Settings.VertexColor.Enabled"), bVertexColor));
|
|
|
|
|
|
|
|
|
|
FEngineAnalytics::GetProvider().RecordEvent(FString(TEXT("Editor.Usage.ModelingTools.")) + EventName, Attributes);
|
|
|
|
|
|
|
|
|
|
constexpr bool bLogAnalytics = false;
|
|
|
|
|
if constexpr (bLogAnalytics)
|
|
|
|
|
{
|
|
|
|
|
for (const FAnalyticsEventAttribute& Attr : Attributes)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogGeometry, Log, TEXT("[%s] %s = %s"), *EventName, *Attr.GetName(), *Attr.GetValue());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-09-13 17:51:19 -04:00
|
|
|
#undef LOCTEXT_NAMESPACE
|