载入中...
搜索中...
未找到
LevelDocument.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4
5#include <algorithm>
6
7namespace eve::level_editing {
8
9LevelDocument::LevelDocument(int width, int height, float tileWidth, float tileHeight)
10 : width_(width), height_(height), tileWidth_(tileWidth), tileHeight_(tileHeight) {
11 if (width < 1 || height < 1 || tileWidth <= 0 || tileHeight <= 0)
12 throw Exception("LevelDocument: dimensions and tile size must be positive");
13}
14
15std::string LevelDocument::nextId(const char* prefix) {
16 for (;;) {
17 std::string candidate = std::string(prefix) + std::to_string(nextId_++);
18 bool occupied = false;
19 for (const auto& layer : layers_) {
20 occupied = occupied || layer.id == candidate;
21 for (const auto& object : layer.objects) occupied = occupied || object.id == candidate;
22 }
23 if (!occupied) return candidate;
24 }
25}
26
28 if (width < 1 || height < 1) throw Exception("LevelDocument::resize: dimensions must be positive");
29 width_ = width;
30 height_ = height;
31 for (auto& l : layers_)
32 if (l.tiles) l.tiles->resize(width, height);
33}
34
36 if (width <= 0 || height <= 0) throw Exception("LevelDocument::setTileSize: size must be positive");
37 tileWidth_ = width;
38 tileHeight_ = height;
39}
40
41void LevelDocument::setOrientation(const std::string& value) {
42 if (value != "orthogonal" && value != "isometric" && value != "staggered" && value != "hexagonal")
43 throw Exception("LevelDocument::setOrientation: unsupported orientation");
44 orientation_ = value;
45}
46
47int LevelDocument::addTileLayer(const std::string& name) {
48 LevelLayer l;
49 l.id = nextId("layer-");
50 l.name = name;
52 l.tiles = std::make_unique<TileBuffer>(width_, height_);
53 layers_.push_back(std::move(l));
54 return int(layers_.size()) - 1;
55}
56
57int LevelDocument::addObjectLayer(const std::string& name) {
58 LevelLayer l;
59 l.id = nextId("layer-");
60 l.name = name;
62 layers_.push_back(std::move(l));
63 return int(layers_.size()) - 1;
64}
65
67 if (!layer(i)) return LevelChange::Unchanged;
68 layers_.erase(layers_.begin() + i);
70}
71
73 if (!layer(from) || to < 0 || to >= int(layers_.size()) || from == to) return LevelChange::Unchanged;
74 auto moving = std::move(layers_[from]);
75 layers_.erase(layers_.begin() + from);
76 layers_.insert(layers_.begin() + to, std::move(moving));
78}
79
81 return i < 0 || i >= int(layers_.size()) ? eve::OptionalRef<LevelLayer>{}
82 : eve::OptionalRef<LevelLayer>{std::ref(layers_[i])};
83}
85 return i < 0 || i >= int(layers_.size()) ? eve::OptionalRef<const LevelLayer>{}
86 : eve::OptionalRef<const LevelLayer>{std::cref(layers_[i])};
87}
88
89const std::string& LevelDocument::getLayerName(int i) const {
90 auto l = layer(i);
91 if (!l) throw Exception("LevelDocument: layer index out of bounds");
92 return l->get().name;
93}
94void LevelDocument::setLayerName(int i, const std::string& name) {
95 auto l = layer(i);
96 if (!l) throw Exception("LevelDocument: layer index out of bounds");
97 l->get().name = name;
98}
99const std::string LevelDocument::getLayerKind(int i) const {
100 auto l = layer(i);
101 if (!l) return {};
102 return l->get().kind == LevelLayer::Kind::Tiles ? "tiles" : "objects";
103}
105 auto l = layer(i);
106 return l && l->get().tiles ? eve::OptionalRef<TileBuffer>{std::ref(*l->get().tiles)}
108}
110 auto l = layer(i);
111 return l && l->get().tiles ? eve::OptionalRef<const TileBuffer>{std::cref(*l->get().tiles)}
113}
114
115int LevelDocument::addObject(int li, const std::string& type, float x, float y) {
116 auto l = layer(li);
117 if (!l || l->get().kind != LevelLayer::Kind::Objects) return -1;
118 LevelObject o;
119 o.id = nextId("object-");
120 o.type = type;
121 o.x = x;
122 o.y = y;
123 l->get().objects.push_back(std::move(o));
124 return int(l->get().objects.size()) - 1;
125}
127 auto l = layer(li);
128 return l ? int(l->get().objects.size()) : 0;
129}
131 auto l = layer(li);
132 return !l || oi < 0 || oi >= int(l->get().objects.size())
134 : eve::OptionalRef<LevelObject>{std::ref(l->get().objects[oi])};
135}
137 auto l = layer(li);
138 return !l || oi < 0 || oi >= int(l->get().objects.size())
140 : eve::OptionalRef<const LevelObject>{std::cref(l->get().objects[oi])};
141}
143 auto l = layer(li);
144 if (!l || oi < 0 || oi >= int(l->get().objects.size())) return LevelChange::Unchanged;
145 l->get().objects.erase(l->get().objects.begin() + oi);
147}
148
149void LevelDocument::setProperty(const std::string& key, const std::string& value) { properties_[key] = value; }
150std::string LevelDocument::getProperty(const std::string& key, const std::string& fallback) const {
151 auto it = properties_.find(key);
152 return it == properties_.end() ? fallback : it->second;
153}
154
155} // namespace eve::level_editing
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
std::string from
std::uint32_t key
HexCoordinates to
Cell the unit walks towards on this segment.
Definition HexUnits.cpp:64
std::uint32_t height
std::uint32_t width
std::string name
TileLayer * layer
std::string id
Definition PlayHost.cpp:108
bool occupied
Json object
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
const std::string & getLayerName(int index) const
Returns the layer name.
int addObject(int layerIndex, const std::string &type, float x, float y)
Adds object.
int addObjectLayer(const std::string &name)
Adds object layer.
LevelChange moveLayer(int from, int to)
Moves layer.
int getObjectCount(int layerIndex) const
Returns the object count.
std::string getProperty(const std::string &key, const std::string &fallback={}) const
Returns the property.
LevelChange removeObject(int layerIndex, int objectIndex)
Removes object.
eve::OptionalRef< LevelLayer > layer(int index)
Layer.
void setOrientation(const std::string &orientation)
Sets the orientation.
void setLayerName(int index, const std::string &name)
Sets the layer name.
void resize(int width, int height)
Changes map dimensions and resizes all tile layers.
eve::OptionalRef< LevelObject > object(int layerIndex, int objectIndex)
Object.
void setTileSize(float width, float height)
Sets the tile size.
LevelChange removeLayer(int index)
Removes layer.
int addTileLayer(const std::string &name)
Adds tile layer.
LevelDocument(int width=1, int height=1, float tileWidth=32.f, float tileHeight=32.f)
Level document.
const std::string getLayerKind(int index) const
Returns the layer kind.
void setProperty(const std::string &key, const std::string &value)
Sets the property.
eve::OptionalRef< TileBuffer > getTileLayer(int index)
Returns the tile layer.
LevelChange
Whether a requested level mutation changed authoritative document state.
std::optional< std::reference_wrapper< T > > OptionalRef
Optional borrowed reference; it does not extend T's lifetime.
Definition BorrowedRef.h:24
A tile or object layer in a LevelDocument.
std::unique_ptr< TileBuffer > tiles
One freely extensible object placed in a top-down level.