Peoplemon  0.1.0
Peoplemon 3 game source documentation
Tileset.cpp
Go to the documentation of this file.
1 #include <Core/Maps/Tileset.hpp>
2 #include <Core/Properties.hpp>
3 #include <Core/Resources.hpp>
4 
5 namespace core
6 {
7 namespace map
8 {
10 : nextTextureId(1)
11 , nextAnimationId(1)
12 , enginePtr(nullptr) {}
13 
14 Tile::IdType Tileset::addTexture(const std::string& uri) {
15  textureFiles.emplace(nextTextureId, uri);
16  const auto it = textures
17  .emplace(nextTextureId,
18  ImageManager::load(
19  bl::util::FileUtil::joinPath(Properties::MapTilePath(), uri)))
20  .first;
21  if (enginePtr) {
22  textureAtlas.try_emplace(nextTextureId, textureStitcher.value().addImage(*it->second));
23  combinedTextures->ensureSize({textureStitcher.value().getStitchedImage().getSize().x,
24  textureStitcher.value().getStitchedImage().getSize().y});
25  combinedTextures.asBindlessTexture()->update(textureStitcher.value().getStitchedImage());
26  }
27  return nextTextureId++;
28 }
29 
31  textureFiles.erase(id);
32  textures.erase(id);
33 }
34 
35 Tile::IdType Tileset::addAnimation(const std::string& uri) {
36  animFiles.emplace(nextAnimationId, uri);
37  auto it = anims
38  .emplace(nextAnimationId,
39  AnimationManager::load(
40  bl::util::FileUtil::joinPath(Properties::MapAnimationPath(), uri)))
41  .first;
42  if (it->second->isLooping() && enginePtr) {
43  sharedAnimations.try_emplace(nextAnimationId)
44  .first->second.create(
45  *enginePtr, it->second, bl::gfx::DiscreteAnimation2DPlayer::Auto, true, true);
46  }
47  return nextAnimationId++;
48 }
49 
51  animFiles.erase(id);
52  anims.erase(id);
53  sharedAnimations.erase(id);
54 }
55 
56 void Tileset::activate(bl::engine::Engine& engine) {
57  if (enginePtr != nullptr) { return; }
58 
59  BL_LOG_INFO << "Activating tileset...";
60  enginePtr = &engine;
61 
62  BL_LOG_INFO << "Creating shared animation players...";
63  for (const auto& apair : anims) {
64  if (apair.second->isLooping()) {
65  sharedAnimations.try_emplace(apair.first)
66  .first->second.create(
67  engine, apair.second, bl::gfx::DiscreteAnimation2DPlayer::Auto, true, true);
68  }
69  }
70 
71  BL_LOG_INFO << "Stitching tiles into atlas...";
72  textureStitcher.emplace(engine.renderer());
73  for (const auto& tpair : textures) {
74  textureAtlas.try_emplace(tpair.first, textureStitcher.value().addImage(*tpair.second));
75  }
76  combinedTextures = engine.renderer().texturePool().createTexture(
77  textureStitcher.value().getStitchedImage(),
78  engine.renderer().vulkanState().samplerCache.noFilterEdgeClamped());
79 
80  BL_LOG_INFO << "Tileset activated";
81 }
82 
83 unsigned int Tileset::tileHeight(Tile::IdType id, bool isAnim) const {
84  if (isAnim) {
85  auto anim = anims.find(id);
86  if (anim != anims.end()) {
87  if (anim->second->frameCount() > 0) return anim->second->getFrameSize(0).y;
88  }
89  }
90  else {
91  auto txtr = textures.find(id);
92  if (txtr != textures.end()) { return txtr->second->getSize().y; }
93  }
94  return 0;
95 }
96 
97 bool Tileset::loadDev(std::istream& input) {
98  clear();
99  if (!bl::serial::json::Serializer<Tileset>::deserializeStream(input, *this)) return false;
100  finishLoad();
101  return true;
102 }
103 
104 void Tileset::clear() {
105  textureFiles.clear();
106  animFiles.clear();
107  nextTextureId = nextAnimationId = 1;
108  textures.clear();
109  anims.clear();
110  sharedAnimations.clear();
111 }
112 
113 bool Tileset::loadProd(bl::serial::binary::InputStream& input) {
114  clear();
115  if (!bl::serial::binary::Serializer<Tileset>::deserialize(input, *this)) return false;
116  finishLoad();
117  return true;
118 }
119 
120 void Tileset::finishLoad() {
121  for (const auto& tpair : textureFiles) {
122  textures.emplace(tpair.first,
123  ImageManager::load(bl::util::FileUtil::joinPath(Properties::MapTilePath(),
124  tpair.second)));
125  if (tpair.first >= nextTextureId) nextTextureId = tpair.first + 1;
126  }
127 
128  for (const auto& apair : animFiles) {
129  auto it = anims
130  .emplace(apair.first,
131  AnimationManager::load(bl::util::FileUtil::joinPath(
132  Properties::MapAnimationPath(), apair.second)))
133  .first;
134  if (apair.first >= nextAnimationId) nextAnimationId = apair.first + 1;
135  }
136 }
137 
138 bool Tileset::save(const std::string& file) const {
139  std::ofstream output(bl::util::FileUtil::startsWithPath(file, Properties::TilesetPath()) ?
140  file.c_str() :
141  bl::util::FileUtil::joinPath(Properties::TilesetPath(), file).c_str());
142  return bl::serial::json::Serializer<Tileset>::serializeStream(output, *this, 4, 0);
143 }
144 
145 bool Tileset::saveBundle(bl::serial::binary::OutputStream& output,
146  bl::resource::bundle::FileHandlerContext& ctx) const {
147  if (!bl::serial::binary::Serializer<Tileset>::serialize(output, *this)) return false;
148  for (const auto& tp : textureFiles) {
149  const std::string p = bl::util::FileUtil::joinPath(Properties::MapTilePath(), tp.second);
150  if (bl::util::FileUtil::exists(p)) { ctx.addDependencyFile(p); }
151  }
152  for (const auto& ap : animFiles) {
153  const std::string p =
154  bl::util::FileUtil::joinPath(Properties::MapAnimationPath(), ap.second);
155  if (bl::util::FileUtil::exists(p)) { ctx.addDependencyFile(p); }
156  }
157  return true;
158 }
159 
160 bl::resource::Ref<sf::Image> Tileset::getTile(Tile::IdType id) const {
161  auto it = textures.find(id);
162  return it != textures.end() ? it->second : bl::resource::Ref<sf::Image>{};
163 }
164 
165 std::vector<Tileset::TileStore::const_iterator> Tileset::getTiles() const {
166  std::vector<TileStore::const_iterator> result;
167  result.reserve(textures.size());
168  for (Tile::IdType id = 0; id < nextTextureId; ++id) {
169  auto it = textures.find(id);
170  if (it != textures.end()) { result.emplace_back(it); }
171  }
172  return result;
173 }
174 
175 bl::resource::Ref<bl::gfx::a2d::AnimationData> Tileset::getAnim(Tile::IdType id) const {
176  auto it = anims.find(id);
177  return it != anims.end() ? it->second : bl::resource::Ref<bl::gfx::a2d::AnimationData>{};
178 }
179 
180 std::vector<Tileset::AnimStore::const_iterator> Tileset::getAnims() const {
181  std::vector<AnimStore::const_iterator> result;
182  result.reserve(anims.size());
183  for (Tile::IdType id = 0; id < nextAnimationId; ++id) {
184  auto it = anims.find(id);
185  if (it != anims.end()) { result.emplace_back(it); }
186  }
187  return result;
188 }
189 
190 std::string Tileset::getFullPath(const std::string& path) {
191  return bl::util::FileUtil::joinPath(Properties::TilesetPath(), path);
192 }
193 
194 sf::FloatRect Tileset::getTileTextureBounds(Tile::IdType tid) const {
195  const auto tit = textures.find(tid);
196  if (tit == textures.end()) {
197  BL_LOG_ERROR << "Unable to find texture with id: " << tid;
198  return {-1.f, -1.f, -1.f, -1.f};
199  }
200 
201  const auto ait = textureAtlas.find(tid);
202  if (ait == textureAtlas.end()) {
203  BL_LOG_ERROR << "Texture with id " << tid << " is missing from atlas";
204  return {-1.f, -1.f, -1.f, -1.f};
205  }
206 
207  return {static_cast<float>(ait->second.x),
208  static_cast<float>(ait->second.y),
209  static_cast<float>(tit->second->getSize().x),
210  static_cast<float>(tit->second->getSize().y)};
211 }
212 
213 } // namespace map
214 } // namespace core
Core classes and functionality for both the editor and game.
std::uint16_t IdType
Definition: Tile.hpp:33
unsigned int tileHeight(Tile::IdType id, bool isAnim) const
Returns the height of the requested tile, in pixels.
Definition: Tileset.cpp:83
Tile::IdType addAnimation(const std::string &uri)
Adds the given animation to the tileset and returns its id.
Definition: Tileset.cpp:35
bool save(const std::string &file) const
Saves the tileset to the given file. No media is saved.
Definition: Tileset.cpp:138
static std::string getFullPath(const std::string &path)
Generates the full path to the given tileset file.
Definition: Tileset.cpp:190
Tile::IdType addTexture(const std::string &uri)
Adds a texture to the tileset and returns its id.
Definition: Tileset.cpp:14
std::vector< TileStore::const_iterator > getTiles() const
Returns all contained tiles.
Definition: Tileset.cpp:165
void activate(bl::engine::Engine &engine)
Prepares renderer resources and starts playing all shared animations.
Definition: Tileset.cpp:56
Tileset()
Creates an empty Tileset.
Definition: Tileset.cpp:9
bool loadDev(std::istream &input)
Loads the tileset from the development format data.
Definition: Tileset.cpp:97
sf::FloatRect getTileTextureBounds(Tile::IdType tid) const
Returns the normalized texture coordinates for the given tile id.
Definition: Tileset.cpp:194
bl::resource::Ref< bl::gfx::a2d::AnimationData > getAnim(Tile::IdType id) const
Returns an animation from the set. Returns nullptr if not found.
Definition: Tileset.cpp:175
void removeTexture(Tile::IdType id)
Removes the given texture from the tileset. Undefined behavior if any tiles reference it....
Definition: Tileset.cpp:30
bl::resource::Ref< sf::Image > getTile(Tile::IdType id) const
Returns a tile from the set. Returns nullptr if not found.
Definition: Tileset.cpp:160
void removeAnimation(Tile::IdType id)
Removes the given animation from the tileset. Undefined behavior if any tiles reference it....
Definition: Tileset.cpp:50
bool saveBundle(bl::serial::binary::OutputStream &output, bl::resource::bundle::FileHandlerContext &ctx) const
Saves the data from this object to the given bundle and registers dependency files.
Definition: Tileset.cpp:145
std::vector< AnimStore::const_iterator > getAnims() const
Returns all contained animations.
Definition: Tileset.cpp:180
bool loadProd(bl::serial::binary::InputStream &input)
Loads the tileset from the production format data.
Definition: Tileset.cpp:113
static const std::string & MapAnimationPath()
Definition: Properties.cpp:357
static const std::string & MapTilePath()
Definition: Properties.cpp:351
static const std::string & TilesetPath()
Definition: Properties.cpp:345