Tooling
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "World/WorldMapProjection.h"
|
||||
#include "WorldMapDefinition.generated.h"
|
||||
|
||||
class UTexture2D;
|
||||
|
||||
// Every property here is EditAnywhere rather than the EditDefaultsOnly a data asset usually carries, because
|
||||
// this asset is *written by a script*: Python's set_editor_property refuses a property marked edit-on-default
|
||||
// when the object is an instance, and a UDataAsset is an instance. EditDefaultsOnly guards against editing a
|
||||
// placed actor's copy of something; there is no such copy here.
|
||||
|
||||
/**
|
||||
* One picture of the whole world, and what to call it. Every layer is a different render of the same cylinder,
|
||||
* so they share the definition's projection and need not share a resolution.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct SALTY_API FWorldMapLayer
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** How code and the console name this layer. Matches the id in RawContent/World/MapArt/layers.json. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
FName Id;
|
||||
|
||||
/** What a person sees on the button. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
FText DisplayName;
|
||||
|
||||
/** Soft, because a map that is never opened should not cost 11 MB of texture to be in the level. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
TSoftObjectPtr<UTexture2D> Texture;
|
||||
|
||||
/** Why this layer exists, for whoever opens the asset next. Never shown to a player. */
|
||||
UPROPERTY(EditAnywhere, Category = "World Map", meta = (MultiLine = true))
|
||||
FString Note;
|
||||
};
|
||||
|
||||
/**
|
||||
* The map of one level: where the ground is on the picture, and which pictures there are.
|
||||
*
|
||||
* Written by Scripts/Authoring/create_world_map.py out of RawContent/World/Region.json and MapArt/layers.json,
|
||||
* so the projection here and the geometry of the landscape come from the same numbers and cannot drift. It is
|
||||
* an asset rather than a config entry because it is content, and because the editor tab and the game both read
|
||||
* it without either of them knowing that RawContent exists.
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class SALTY_API UWorldMapDefinition : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** The primary asset type, registered for scanning in Config/DefaultGame.ini. */
|
||||
static const FPrimaryAssetType AssetType;
|
||||
|
||||
virtual FPrimaryAssetId GetPrimaryAssetId() const override { return FPrimaryAssetId(AssetType, GetFName()); }
|
||||
|
||||
/** Where the ground is on the art. See FWorldMapProjection: for L_World this is the whole planet. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
FWorldMapProjection Projection;
|
||||
|
||||
/**
|
||||
* The level this is a map of. How UWorldMapSubsystem decides a definition belongs to the world it is in.
|
||||
*
|
||||
* A path rather than a TSoftObjectPtr<UWorld> because it is only ever compared, never loaded: resolving it
|
||||
* would pull a 98-landscape level in to answer "is this the world I am already standing in".
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map", meta = (AllowedClasses = "/Script/Engine.World"))
|
||||
FSoftObjectPath Level;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
TArray<FWorldMapLayer> Layers;
|
||||
|
||||
/** Which layer the map opens on. Falls back to the first layer when it names one that is not here. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map")
|
||||
FName DefaultLayer;
|
||||
|
||||
/** What built this, so a map that looks wrong can be traced to the run that made it. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "World Map", meta = (MultiLine = true))
|
||||
FString BuiltFrom;
|
||||
|
||||
const FWorldMapLayer* FindLayer(FName Id) const;
|
||||
|
||||
/** DefaultLayer if it exists, otherwise the first layer, otherwise nullptr. */
|
||||
const FWorldMapLayer* ResolveDefaultLayer() const;
|
||||
|
||||
/** The id after Id, wrapping; NAME_None when there are no layers. For a "next layer" key or button. */
|
||||
FName NextLayerId(FName Id) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "World Map")
|
||||
TArray<FName> GetLayerIds() const;
|
||||
|
||||
/** True when this can actually be drawn: a projection with an extent and at least one layer. */
|
||||
UFUNCTION(BlueprintPure, Category = "World Map")
|
||||
bool IsUsable() const { return Projection.IsValid() && Layers.Num() > 0; }
|
||||
};
|
||||
Reference in New Issue
Block a user