目標
UEでLandscape(レイヤー編集を有効にする)のハイトマップとウェイトマップを表示するための小さなツールを作成します。
ハイトマップとウェイトマップを表示すること自体は難しくありません。ただし、ここではエンジンのソース コードは変更しないでください。したがって、物事は外部 (プロジェクト エンジニアリング モジュールやプラグイン モジュールなど) で行われます。
地形のハイトマップとウェイトマップのデータ構造
データ構造は、LandscapeComponent.h で確認できます。
編集レイヤーが有効な場合、データは にありLayersData
、各編集レイヤーは GUID に対応します。
UPROPERTY()
TMap<FGuid, FLandscapeLayerComponentData> LayersData;
それぞれFLandscapeLayerComponentData
にFHeightmapData
と が含まれますFWeightmapData
USTRUCT(NotBlueprintable)
struct FLandscapeLayerComponentData
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
FHeightmapData HeightmapData;
UPROPERTY()
FWeightmapData WeightmapData;
bool IsInitialized() const {
return HeightmapData.Texture != nullptr || WeightmapData.Textures.Num() > 0; }
};
FHeightmapData
テクスチャが含まれています:
USTRUCT(NotBlueprintable)
struct FHeightmapData
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
UTexture2D* Texture;
};
FWeightmapData
複数のマップが含まれます (ウェイト レイヤーが多数存在する可能性があるため)。
USTRUCT(NotBlueprintable)
struct FWeightmapData
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
TArray<UTexture2D*> Textures;
UPROPERTY()
TArray<FWeightmapLayerAllocationInfo> LayerAllocations;
UPROPERTY(Transient)
TArray<ULandscapeWeightmapUsage*> TextureUsages;
};
小さな道具
プロセスは前と同じで、最初に UObject を定義します。
詳細パネルで関連するテクスチャを表示するために、元の構造が接尾辞_visを持つ新しい構造に置き換えられ、UProperty が追加されますVisibleAnywhere
。FindLandscapeTextures()
次に、トリガー後のワールド内の地形を検索し、そのデータをコピーする機能であるボタンを提供します。(現時点では、最初に見つかった地形の最初のコンポーネントのみを観察します)
コードは以下のように表示されます:
LandscapeTextureWatcher.h
#pragma once
#include "UObject/Object.h"
#include "Landscape/Classes/LandscapeComponent.h"
#include "LandscapeTextureWatcher.generated.h"
USTRUCT(NotBlueprintable)
struct FWeightmapData_vis
{
GENERATED_USTRUCT_BODY()
UPROPERTY(VisibleAnywhere)
TArray<UTexture2D*> Textures;
UPROPERTY(VisibleAnywhere)
TArray<FWeightmapLayerAllocationInfo> LayerAllocations;
UPROPERTY(Transient)
TArray<ULandscapeWeightmapUsage*> TextureUsages;
};
USTRUCT(NotBlueprintable)
struct FHeightmapData_vis
{
GENERATED_USTRUCT_BODY()
UPROPERTY(VisibleAnywhere)
UTexture2D* Texture;
};
USTRUCT(NotBlueprintable)
struct FLandscapeLayerComponentData_vis
{
GENERATED_USTRUCT_BODY()
UPROPERTY(VisibleAnywhere)
FHeightmapData_vis HeightmapData;
UPROPERTY(VisibleAnywhere)
FWeightmapData_vis WeightmapData;
bool IsInitialized() const {
return HeightmapData.Texture != nullptr || WeightmapData.Textures.Num() > 0; }
};
UCLASS(Blueprintable)
class ULandscapeTextureWatcher : public UObject
{
GENERATED_UCLASS_BODY()
public:
//按钮,点击后就把地形的纹理数据拿来
UFUNCTION(CallInEditor)
void FindLandscapeTextures();
//要观察的地形纹理数据:
UPROPERTY(VisibleAnywhere)
TMap<FGuid, FLandscapeLayerComponentData_vis> LayersData;
};
LandscapeTextureWatcher.cpp
#include "LandscapeTextureWatcher.h"
#include "Kismet/GameplayStatics.h"
#include "Editor.h"
#include "LandscapeInfo.h"
#include "Landscape/Classes/Landscape.h"
ULandscapeTextureWatcher::ULandscapeTextureWatcher(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void ULandscapeTextureWatcher::FindLandscapeTextures()
{
//得到World
const UWorld* World = GEditor->GetEditorWorldContext().World();
//找地形:
TArray<AActor*> OutActors;
UGameplayStatics::GetAllActorsOfClass(World, ALandscape::StaticClass(), OutActors);
//没找到则直接返回
if (OutActors.Num() == 0)
return;
//找到则用第一个Landscape:
ALandscape* Landscape = (ALandscape*)OutActors[0];
if (Landscape->LandscapeComponents.Num() == 0)
return;
//使用第一个Component:
ULandscapeComponent* LandscapeComponent = Landscape->LandscapeComponents[0];
//遍历所有layer,填入数据
LandscapeComponent->ForEachLayer([&](const FGuid& LayerGuid, FLandscapeLayerComponentData& LayerData)
{
FLandscapeLayerComponentData_vis data;
data.HeightmapData.Texture = LayerData.HeightmapData.Texture;
data.WeightmapData.Textures = LayerData.WeightmapData.Textures;
LayersData.Add(LayerGuid, data);
});
}
次に、前の手順 (3)に従って、詳細パネルを表示します。
効果
編集レイヤー機能をオンにして地形を作成します。コンポーネントは 1 つだけ作成され (当面は最初のコンポーネントのみが観察されるため)、
編集レイヤーは 2 つ作成され、使用される地形マテリアルには 5 つのウェイト レイヤが含まれます。
結果は次のようになります。
上のテクスチャは黒ですが、アルファ チャネルが 0 であるため、テクスチャを直接開き、アルファ チャネルをオフにして効果を確認できます。
ハイトマップ:
ウェイト マップでは、各レイヤーがチャネルを占有していることがわかります。