1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
#include "StarTerrainDatabase.hpp"
#include "StarRidgeBlocksSelector.hpp"
#include "StarKarstCave.hpp"
#include "StarWormCave.hpp"
#include "StarConstantSelector.hpp"
#include "StarMaxSelector.hpp"
#include "StarMinMaxSelector.hpp"
#include "StarFlatSurfaceSelector.hpp"
#include "StarDisplacementSelector.hpp"
#include "StarRotateSelector.hpp"
#include "StarMixSelector.hpp"
#include "StarPerlinSelector.hpp"
#include "StarCacheSelector.hpp"
#include "StarIslandSurfaceSelector.hpp"
#include "StarAssets.hpp"
#include "StarRoot.hpp"
#include "StarRandom.hpp"
#include "StarJsonExtra.hpp"
namespace Star {
TerrainSelectorParameters::TerrainSelectorParameters() {
seed = Random::randu64();
worldWidth = 0;
commonality = 1.0f;
}
TerrainSelectorParameters::TerrainSelectorParameters(Json const& v) {
worldWidth = v.getUInt("worldWidth");
baseHeight = v.getFloat("baseHeight");
seed = v.getUInt("seed");
commonality = v.getFloat("commonality");
}
Json TerrainSelectorParameters::toJson() const {
return JsonObject{
{"worldWidth", worldWidth}, {"baseHeight", baseHeight}, {"seed", seed}, {"commonality", commonality}};
}
TerrainSelectorParameters TerrainSelectorParameters::withSeed(uint64_t seed) const {
TerrainSelectorParameters copy = *this;
copy.seed = seed;
return copy;
}
TerrainSelectorParameters TerrainSelectorParameters::withCommonality(float commonality) const {
TerrainSelectorParameters copy = *this;
copy.commonality = commonality;
return copy;
}
TerrainSelector::TerrainSelector(String type, Json config, TerrainSelectorParameters parameters)
: type(std::move(type)), config(std::move(config)), parameters(std::move(parameters)) {}
TerrainSelector::~TerrainSelector() {}
TerrainDatabase::TerrainDatabase() {
auto assets = Root::singleton().assets();
// 'type' here is the extension of the file, and determines the selector type
auto scanFiles = [this, assets](String const& type) {
auto& files = assets->scanExtension(type);
assets->queueJsons(files);
for (auto& path : files) {
auto parameters = assets->json(path);
auto name = parameters.getString("name");
if (m_terrainSelectors.contains(name))
throw TerrainException(strf("Duplicate terrain generator name '{}'", name));
m_terrainSelectors[name] = {type, parameters};
}
};
scanFiles(KarstCaveSelector::Name);
scanFiles(WormCaveSelector::Name);
scanFiles(RidgeBlocksSelector::Name);
auto& files = assets->scanExtension("terrain");
assets->queueJsons(files);
for (auto& path : files) {
auto parameters = assets->json(path);
auto name = parameters.getString("name");
auto type = parameters.getString("type");
if (m_terrainSelectors.contains(name))
throw TerrainException(strf("Duplicate composed terrain generator name '{}'", name));
m_terrainSelectors[name] = {type, parameters};
}
}
TerrainDatabase::Config TerrainDatabase::selectorConfig(String const& name) const {
if (auto config = m_terrainSelectors.maybe(name))
return config.take();
else
throw TerrainException(strf("No such terrain selector '{}'", name));
}
TerrainSelectorConstPtr TerrainDatabase::createNamedSelector(String const& name, TerrainSelectorParameters const& parameters) const {
auto config = selectorConfig(name);
return createSelectorType(config.type, config.parameters, parameters);
}
TerrainSelectorConstPtr TerrainDatabase::constantSelector(float value) {
return createSelectorType(ConstantSelector::Name, JsonObject{{"value", value}}, TerrainSelectorParameters());
}
Json TerrainDatabase::storeSelector(TerrainSelectorConstPtr const& selector) const {
if (!selector)
return {};
return JsonObject{
{"type", selector->type},
{"config", selector->config},
{"parameters", selector->parameters.toJson()}
};
}
TerrainSelectorConstPtr TerrainDatabase::loadSelector(Json const& store) const {
if (store.isNull())
return {};
return createSelectorType(store.getString("type"), store.get("config"),
TerrainSelectorParameters(store.get("parameters")));
}
TerrainSelectorConstPtr TerrainDatabase::createSelectorType(String const& type, Json const& config, TerrainSelectorParameters const& parameters) const {
if (type == WormCaveSelector::Name)
return make_shared<WormCaveSelector>(config, parameters);
else if (type == KarstCaveSelector::Name)
return make_shared<KarstCaveSelector>(config, parameters);
else if (type == ConstantSelector::Name)
return make_shared<ConstantSelector>(config, parameters);
else if (type == MaxSelector::Name)
return make_shared<MaxSelector>(config, parameters, this);
else if (type == MinMaxSelector::Name)
return make_shared<MinMaxSelector>(config, parameters, this);
else if (type == IslandSurfaceSelector::Name)
return make_shared<IslandSurfaceSelector>(config, parameters);
else if (type == FlatSurfaceSelector::Name)
return make_shared<FlatSurfaceSelector>(config, parameters);
else if (type == DisplacementSelector::Name)
return make_shared<DisplacementSelector>(config, parameters, this);
else if (type == RotateSelector::Name)
return make_shared<RotateSelector>(config, parameters, this);
else if (type == MixSelector::Name)
return make_shared<MixSelector>(config, parameters, this);
else if (type == PerlinSelector::Name)
return make_shared<PerlinSelector>(config, parameters);
else if (type == RidgeBlocksSelector::Name)
return make_shared<RidgeBlocksSelector>(config, parameters);
else if (type == CacheSelector::Name)
return make_shared<CacheSelector>(config, parameters, this);
else
throw TerrainException(strf("Unknown terrain selector type '{}'", type));
}
}
|