159 lines
3.6 KiB
C++
159 lines
3.6 KiB
C++
#include "Level/Generator/TerrainGeneratorBase.h"
|
|
|
|
UTerrainGeneratorBase::UTerrainGeneratorBase()
|
|
{
|
|
}
|
|
|
|
int32 UTerrainGeneratorBase::AddTerrain(const FGameplayTag& TerrainTag)
|
|
{
|
|
FTerrainNodeInfo NewNode;
|
|
NewNode.TerrainTag = TerrainTag;
|
|
NewNode.Probability = 1.0f;
|
|
NewNode.Weight = 1.0f;
|
|
NewNode.ParentHandle = -1;
|
|
NewNode.bIsLeafNode = true;
|
|
|
|
int32 Handle = NextHandle++;
|
|
TerrainNodes.Add(Handle, NewNode);
|
|
|
|
return Handle;
|
|
}
|
|
|
|
void UTerrainGeneratorBase::SetWeight(int32 Handle, float Weight)
|
|
{
|
|
if (FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
|
|
{
|
|
Node->Weight = FMath::Max(0.0f, Weight);
|
|
}
|
|
}
|
|
|
|
void UTerrainGeneratorBase::SetProbability(int32 Handle, float Probability)
|
|
{
|
|
if (FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
|
|
{
|
|
Node->Probability = FMath::Clamp(Probability, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
void UTerrainGeneratorBase::SetExclusive(const TArray<int32>& Handles){
|
|
if (Handles.Num() <= 1) return;
|
|
ExclusiveGroups.Add(TSet<int32>(Handles));
|
|
}
|
|
|
|
void UTerrainGeneratorBase::BindChildTerrain(int32 ParentHandle, const TArray<int32>& ChildHandles)
|
|
{
|
|
if (FTerrainNodeInfo* ParentNode = TerrainNodes.Find(ParentHandle))
|
|
{
|
|
// 设置父节点为非叶子节点
|
|
ParentNode->bIsLeafNode = false;
|
|
|
|
// 添加子节点
|
|
ParentNode->ChildHandles = ChildHandles;
|
|
|
|
// 设置子节点的父节点
|
|
for (int32 ChildHandle : ChildHandles)
|
|
{
|
|
if (FTerrainNodeInfo* ChildNode = TerrainNodes.Find(ChildHandle))
|
|
{
|
|
ChildNode->ParentHandle = ParentHandle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FGameplayTag UTerrainGeneratorBase::GetFinalTerrainTag(const int32 Handle) const{
|
|
if (const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle)){
|
|
return Node->TerrainTag;
|
|
}
|
|
return FGameplayTag();
|
|
}
|
|
|
|
TArray<int32> UTerrainGeneratorBase::GetValidLeafNodes() const
|
|
{
|
|
TSet<int32> ValidNodes;
|
|
GetPreCheckVisibleHandles(ValidNodes);
|
|
|
|
// 检查互斥关系, 待实现
|
|
TSet<int32> FinalNodes;
|
|
for (int32 Handle : ValidNodes){
|
|
if (FinalNodes.Find(Handle)) continue;
|
|
FinalNodes.Add(Handle);
|
|
}
|
|
|
|
// 只保留叶子节点
|
|
TArray<int32> LeafNodes;
|
|
for (int32 Handle : FinalNodes)
|
|
{
|
|
const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle);
|
|
if (Node && Node->bIsLeafNode)
|
|
{
|
|
LeafNodes.Add(Handle);
|
|
}
|
|
}
|
|
|
|
return LeafNodes;
|
|
}
|
|
|
|
|
|
void UTerrainGeneratorBase::GetPreCheckVisibleHandles(TSet<int32>& VisibleHandles)const{
|
|
bool bShouldAppear;
|
|
TArray<bool> AppearanceCheckResult;
|
|
const int TerrainNodeCount = TerrainNodes.Num();
|
|
AppearanceCheckResult.Init(true, TerrainNodeCount);
|
|
|
|
for (const auto& Pair : TerrainNodes) {
|
|
const int Handle = Pair.Key;
|
|
const FTerrainNodeInfo* Node = &Pair.Value;
|
|
|
|
if (AppearanceCheckResult[Handle]) {
|
|
bShouldAppear = FMath::FRand() < Node->Probability;
|
|
AppearanceCheckResult[Handle] = bShouldAppear;
|
|
}
|
|
else {
|
|
bShouldAppear = false;
|
|
}
|
|
|
|
if (!bShouldAppear) {
|
|
for (const int32 ChildHandle : Pair.Value.ChildHandles) {
|
|
AppearanceCheckResult[ChildHandle] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < TerrainNodeCount; ++i) {
|
|
if (AppearanceCheckResult[i]) {
|
|
VisibleHandles.Add(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TArray<FGameplayTag> UTerrainGeneratorBase::GenerateMap(int32 Width, int32 Height)
|
|
{
|
|
TArray<FGameplayTag> Map;
|
|
Map.SetNum(Width * Height);
|
|
|
|
// 获取有效的叶子节点
|
|
TArray<int32> ValidLeafNodes = GetValidLeafNodes();
|
|
|
|
if (ValidLeafNodes.Num() == 0)
|
|
{
|
|
UE_LOG(LogTemp, Error, TEXT("No valid terrain nodes to generate map!"));
|
|
return Map;
|
|
}
|
|
|
|
if (GenerateWithNodes(Map, Width, Height, ValidLeafNodes))
|
|
{
|
|
return Map;
|
|
}
|
|
else
|
|
{
|
|
return TArray<FGameplayTag>();
|
|
}
|
|
}
|
|
|
|
bool UTerrainGeneratorBase::GenerateWithNodes(TArray<FGameplayTag>& Map, int32 Width, int32 Height, const TArray<int32>& ValidLeafNodes)
|
|
{
|
|
return false;
|
|
}
|