// Copyright Epic Games, Inc. All Rights Reserved. #include "LandscapeEditLayerMergeContext.h" #include "Algo/AllOf.h" #include "Algo/Transform.h" #include "Landscape.h" #include "LandscapeInfo.h" #include "LandscapeLayerInfoObject.h" #include "Materials/MaterialExpressionLandscapeVisibilityMask.h" namespace UE::Landscape::EditLayers { #if WITH_EDITOR FMergeContext::FMergeContext(ALandscape* InLandscape, bool bInIsHeightmapMerge, bool bInSkipProceduralRenderers) : bIsHeightmapMerge(bInIsHeightmapMerge) , bSkipProceduralRenderers(bInSkipProceduralRenderers) , Landscape(InLandscape) , LandscapeInfo(InLandscape->GetLandscapeInfo()) { check(LandscapeInfo != nullptr); // Start by gathering all possible target layer names on this landscape: // This list of all unique target layer names will help accelerate the gathering of output layers on each component (using bit arrays) as well as the target layers intersection tests: if (bInIsHeightmapMerge) { // Only one target layer in the case of heightmap: const FName TargetLayerName = FName("Height"); AllTargetLayerNames = { TargetLayerName }; // And it's valid : ValidTargetLayerBitIndices = TBitArray<>(true, 1); VisibilityTargetLayerMask = TBitArray<>(false, 1); AllWeightmapLayerInfos = { nullptr }; } else { // Gather all target layer names and mark those that are valid layers : for (const FLandscapeInfoLayerSettings& LayerSettings : LandscapeInfo->Layers) { check(!LayerSettings.LayerName.IsNone()); ULandscapeLayerInfoObject*& LayerInfo = AllWeightmapLayerInfos.Add_GetRef(LayerSettings.LayerInfoObj); AllTargetLayerNames.Add(LayerSettings.LayerName); ValidTargetLayerBitIndices.Add(LayerInfo != nullptr); } // Visibility is always a valid layer : VisibilityTargetLayerIndex = AllTargetLayerNames.Find(UMaterialExpressionLandscapeVisibilityMask::ParameterName); if (VisibilityTargetLayerIndex == INDEX_NONE) { VisibilityTargetLayerIndex = AllTargetLayerNames.Num(); AllTargetLayerNames.Add(UMaterialExpressionLandscapeVisibilityMask::ParameterName); check(!AllWeightmapLayerInfos.Contains(ALandscape::VisibilityLayer)); AllWeightmapLayerInfos.Add(ALandscape::VisibilityLayer); check(ALandscape::VisibilityLayer != nullptr); ValidTargetLayerBitIndices.Add(true); } check(VisibilityTargetLayerIndex != INDEX_NONE); VisibilityTargetLayerMask = TBitArray<>(false, AllTargetLayerNames.Num()); VisibilityTargetLayerMask[VisibilityTargetLayerIndex] = true; } NegatedVisibilityTargetLayerMask = VisibilityTargetLayerMask; NegatedVisibilityTargetLayerMask.BitwiseNOT(); } TArray FMergeContext::GetValidTargetLayerNames() const { return bIsHeightmapMerge ? AllTargetLayerNames : ConvertTargetLayerBitIndicesToNames(ValidTargetLayerBitIndices); } int32 FMergeContext::IsValidTargetLayerName(const FName& InName) const { int32 Index = GetTargetLayerIndexForName(InName); return (Index != INDEX_NONE) ? ValidTargetLayerBitIndices[Index] : false; } int32 FMergeContext::IsValidTargetLayerNameChecked(const FName& InName) const { int32 Index = AllTargetLayerNames.Find(InName); check(Index != INDEX_NONE); return ValidTargetLayerBitIndices[Index]; } int32 FMergeContext::IsValidTargetLayerIndex(int32 InIndex) const { check(AllTargetLayerNames.IsValidIndex(InIndex)); return ValidTargetLayerBitIndices[InIndex]; } int32 FMergeContext::GetTargetLayerIndexForName(const FName& InName) const { return AllTargetLayerNames.Find(InName); } int32 FMergeContext::GetTargetLayerIndexForNameChecked(const FName& InName) const { int32 Index = AllTargetLayerNames.Find(InName); check(Index != INDEX_NONE); return Index; } FName FMergeContext::GetTargetLayerNameForIndex(int32 InIndex) const { return AllTargetLayerNames.IsValidIndex(InIndex) ? AllTargetLayerNames[InIndex] : NAME_None; } FName FMergeContext::GetTargetLayerNameForIndexChecked(int32 InIndex) const { check(AllTargetLayerNames.IsValidIndex(InIndex)); return AllTargetLayerNames[InIndex]; } int32 FMergeContext::GetTargetLayerIndexForLayerInfo(ULandscapeLayerInfoObject* InLayerInfo) const { return AllWeightmapLayerInfos.Find(InLayerInfo); } int32 FMergeContext::GetTargetLayerIndexForLayerInfoChecked(ULandscapeLayerInfoObject* InLayerInfo) const { int32 Index = AllWeightmapLayerInfos.Find(InLayerInfo);; check(Index != INDEX_NONE); return Index; } ULandscapeLayerInfoObject* FMergeContext::GetTargetLayerInfoForName(const FName& InName) const { int32 Index = GetTargetLayerIndexForName(InName); return (Index != INDEX_NONE) ? AllWeightmapLayerInfos[Index] : nullptr; } ULandscapeLayerInfoObject* FMergeContext::GetTargetLayerInfoForNameChecked(const FName& InName) const { int32 Index = GetTargetLayerIndexForNameChecked(InName); return AllWeightmapLayerInfos[Index]; } ULandscapeLayerInfoObject* FMergeContext::GetTargetLayerInfoForIndex(int32 InIndex) const { check(AllTargetLayerNames.IsValidIndex(InIndex)); return AllWeightmapLayerInfos[InIndex]; } TBitArray<> FMergeContext::ConvertTargetLayerNamesToBitIndices(TConstArrayView InTargetLayerNames) const { TBitArray<> Result(false, AllTargetLayerNames.Num()); for (FName Name : InTargetLayerNames) { if (int32 Index = GetTargetLayerIndexForName(Name); Index != INDEX_NONE) { Result[Index] = true; } } return Result; } TBitArray<> FMergeContext::ConvertTargetLayerNamesToBitIndicesChecked(TConstArrayView InTargetLayerNames) const { TBitArray<> Result(false, AllTargetLayerNames.Num()); for (FName Name : InTargetLayerNames) { int32 Index = GetTargetLayerIndexForNameChecked(Name); Result[Index] = true; } return Result; } TArray FMergeContext::ConvertTargetLayerBitIndicesToNames(const TBitArray<>& InTargetLayerBitIndices) const { const int32 NumNames = AllTargetLayerNames.Num(); check(InTargetLayerBitIndices.Num() == NumNames); TArray Names; Names.Reserve(NumNames); for (TConstSetBitIterator It(InTargetLayerBitIndices); It; ++It) { Names.Add(AllTargetLayerNames[It.GetIndex()]); } return Names; } TArray FMergeContext::ConvertTargetLayerBitIndicesToLayerInfos(const TBitArray<>& InTargetLayerBitIndices) const { const int32 NumTargetLayerInfos = AllTargetLayerNames.Num(); check(InTargetLayerBitIndices.Num() == NumTargetLayerInfos); TArray LayerInfos; LayerInfos.Reserve(NumTargetLayerInfos); for (TConstSetBitIterator It(InTargetLayerBitIndices); It; ++It) { LayerInfos.Add(AllWeightmapLayerInfos[It.GetIndex()]); } return LayerInfos; } void FMergeContext::ForEachTargetLayer(const TBitArray<>& InTargetLayerBitIndices, TFunctionRef Fn) const { check(InTargetLayerBitIndices.Num() == AllTargetLayerNames.Num()); for (TConstSetBitIterator It(InTargetLayerBitIndices); It; ++It) { const int32 TargetLayerIndex = It.GetIndex(); if (!AllTargetLayerNames.IsValidIndex(TargetLayerIndex)) { return; } if (!Fn(TargetLayerIndex, AllTargetLayerNames[TargetLayerIndex], AllWeightmapLayerInfos[TargetLayerIndex])) { return; } } } void FMergeContext::ForEachValidTargetLayer(TFunctionRef Fn) const { return ForEachTargetLayer(ValidTargetLayerBitIndices, Fn); } TBitArray<> FMergeContext::BuildTargetLayerBitIndices(bool bInBitValue) const { return TBitArray<>(bInBitValue, AllTargetLayerNames.Num()); } #endif // WITH_EDITOR } // namespace UE::Landscape::EditLayers