Files
2026-09-25 17:02:24 +03:00

55 lines
2.7 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "LandscapeAuthoringLibrary.generated.h"
class ALandscape;
class ULandscapeLayerInfoObject;
class UMaterialInterface;
// One paint layer to import with the heightmap: the layer info asset the material expects and an 8-bit
// greyscale file (PNG or raw) with the same resolution as the heightmap.
USTRUCT(BlueprintType)
struct FLandscapeAuthoringWeightmap
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
TObjectPtr<ULandscapeLayerInfoObject> LayerInfo = nullptr;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
FString File;
};
// What the editor's "New Landscape > Import" button does, callable from an authoring script. The engine exposes
// no landscape creation to Python, so this is the project's first editor tool. Mirrors
// FLandscapeEditorDetailCustomization_NewLandscape::OnCreateButtonClicked without the regions path.
UCLASS()
class SALTYEDITOR_API ULandscapeAuthoringLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
// Creates a landscape in World from a 16-bit heightmap file, centred on Location, with the given per-quad
// scale (cm; Z is the engine's height scale where 100 spans -256 m to +256 m). The component layout is chosen
// from the file's resolution; a file that does not fit a layout exactly is expanded, not resampled. In a
// world-partitioned level the landscape is split into streaming proxies of GridSize x GridSize components.
// Returns null and logs why on failure.
UFUNCTION(BlueprintCallable, Category = "Salty|Authoring")
static ALandscape* CreateLandscapeFromHeightmap(UWorld* World, const FString& HeightmapFile,
const TArray<FLandscapeAuthoringWeightmap>& Weightmaps, UMaterialInterface* Material,
FVector Location, FVector Scale, int32 WorldPartitionGridSize = 4);
// Creates a ULandscapeLayerInfoObject asset carrying LayerName, which is the name the landscape material
// blends by and the name a weightmap is imported against.
//
// The second thing the engine exposes no Python path to, and for the same reason as the first. There is no
// LayerInfo factory in the bindings, and ULandscapeLayerInfoObject::LayerName is VisibleAnywhere - so the
// obvious workaround, duplicating an existing layer info, produces an asset that silently keeps the name it
// was copied from and paints that substance wherever the new layer should be. Returns null and logs why on
// failure; an existing asset at the path is returned rather than replaced, so this is safe to rerun.
UFUNCTION(BlueprintCallable, Category = "Salty|Authoring")
static ULandscapeLayerInfoObject* CreateLayerInfo(const FString& PackagePath, const FString& AssetName, FName LayerName);
};