Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

300 рядки
7.1 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <map>
  14. #include <cstdlib>
  15. #include <cstdio>
  16. #include <cstring>
  17. #if defined _WIN32
  18. # define WIN32_LEAN_AND_MEAN
  19. # include <windows.h>
  20. # undef WIN32_LEAN_AND_MEAN
  21. #endif
  22. #include "textureimage-private.h"
  23. namespace lol
  24. {
  25. /* The tileset cache */
  26. static entity_dict<TileSet> tileset_cache;
  27. /*
  28. * TileSet implementation class
  29. */
  30. struct tile_def
  31. {
  32. ibox2 pixel_coords;
  33. box2 tex_coords;
  34. };
  35. class TileSetData
  36. {
  37. friend class TileSet;
  38. protected:
  39. /* Pixels, then texture coordinates */
  40. std::vector<tile_def> m_tiles;
  41. ivec2 m_tile_size;
  42. };
  43. /*
  44. * Public TileSet class
  45. */
  46. TileSet *TileSet::create(std::string const &path)
  47. {
  48. auto ret = tileset_cache.get(path);
  49. return ret ? ret : tileset_cache.set(path, new TileSet(path));
  50. }
  51. TileSet *TileSet::create(std::string const &path, image* img)
  52. {
  53. auto ret = tileset_cache.get(path);
  54. return ret ? ret : tileset_cache.set(path, new TileSet(path, img));
  55. }
  56. TileSet *TileSet::create(std::string const &path, image* img, std::vector<ibox2>& tiles)
  57. {
  58. auto ret = tileset_cache.get(path);
  59. if (!ret)
  60. {
  61. ret = tileset_cache.set(path, new TileSet(path, img));
  62. ret->define_tiles_by_box(tiles);
  63. }
  64. return ret;
  65. }
  66. TileSet *TileSet::create(std::string const &path, ivec2 size, ivec2 count)
  67. {
  68. auto ret = tileset_cache.get(path);
  69. if (!ret)
  70. {
  71. ret = tileset_cache.set(path, new TileSet(path));
  72. /* If count is valid, fix size; otherwise, fix count. */
  73. if (count.x > 0 && count.y > 0)
  74. {
  75. size = ret->m_data->m_image_size / count;
  76. }
  77. else
  78. {
  79. if (size.x <= 0 || size.y <= 0)
  80. size = ivec2(32, 32);
  81. count = max(ivec2(1, 1), ret->m_data->m_image_size / size);
  82. }
  83. for (int j = 0; j < count.y; ++j)
  84. for (int i = 0; i < count.x; ++i)
  85. {
  86. ret->define_tile(ibox2(size * ivec2(i, j),
  87. size * ivec2(i + 1, j + 1)));
  88. }
  89. }
  90. return ret;
  91. }
  92. TileSet *TileSet::create(std::string const &path, image* img, ivec2 size, ivec2 count)
  93. {
  94. auto ret = tileset_cache.get(path);
  95. if (!ret)
  96. {
  97. ret = tileset_cache.set(path, new TileSet(path, img));
  98. /* If count is valid, fix size; otherwise, fix count. */
  99. if (count.x > 0 && count.y > 0)
  100. {
  101. size = ret->m_data->m_image_size / count;
  102. }
  103. else
  104. {
  105. if (size.x <= 0 || size.y <= 0)
  106. size = ivec2(32, 32);
  107. count = max(ivec2(1, 1), ret->m_data->m_image_size / size);
  108. }
  109. for (int j = 0; j < count.y; ++j)
  110. for (int i = 0; i < count.x; ++i)
  111. {
  112. ret->define_tile(ibox2(size * ivec2(i, j),
  113. size * ivec2(i + 1, j + 1)));
  114. }
  115. }
  116. return ret;
  117. }
  118. void TileSet::destroy(TileSet *tileset)
  119. {
  120. // FIXME: decrement!
  121. tileset_cache.erase(tileset);
  122. }
  123. TileSet::TileSet(std::string const &path)
  124. : TextureImage(path),
  125. m_tileset_data(new TileSetData()),
  126. m_palette(nullptr)
  127. {
  128. }
  129. TileSet::TileSet(std::string const &path, image *img)
  130. : TextureImage(path, img),
  131. m_tileset_data(new TileSetData()),
  132. m_palette(nullptr)
  133. {
  134. }
  135. TileSet::~TileSet()
  136. {
  137. delete m_tileset_data;
  138. }
  139. void TileSet::Init(std::string const &path, ResourceCodecData* loaded_data)
  140. {
  141. //Load tileset if available
  142. auto tileset_data = dynamic_cast<ResourceTilesetData*>(loaded_data);
  143. if (tileset_data != nullptr)
  144. {
  145. define_tiles_by_box(tileset_data->m_tiles);
  146. }
  147. m_data->m_name = "<tileset> " + path;
  148. super::Init(path, loaded_data);
  149. }
  150. void TileSet::Init(std::string const &path, image* img)
  151. {
  152. super::Init(path, img);
  153. m_data->m_name = "<tileset> " + path;
  154. }
  155. //Inherited from entity -------------------------------------------------------
  156. std::string TileSet::GetName() const
  157. {
  158. return m_data->m_name;
  159. }
  160. //New methods -----------------------------------------------------------------
  161. void TileSet::clear_all()
  162. {
  163. m_tileset_data->m_tiles.clear();
  164. }
  165. int TileSet::define_tile(ibox2 rect)
  166. {
  167. m_tileset_data->m_tiles.push_back(tile_def {
  168. rect,
  169. box2((vec2)rect.aa / (vec2)m_data->m_texture_size,
  170. (vec2)rect.bb / (vec2)m_data->m_texture_size) });
  171. return int(m_tileset_data->m_tiles.size()) - 1;
  172. }
  173. void TileSet::define_tile(ivec2 count)
  174. {
  175. ivec2 size = m_data->m_image_size / count;
  176. for (int j = 0; j < count.y; ++j)
  177. for (int i = 0; i < count.x; ++i)
  178. {
  179. define_tile(ibox2(size * ivec2(i, j),
  180. size * ivec2(i + 1, j + 1)));
  181. }
  182. }
  183. void TileSet::define_tiles_by_box(std::vector<ibox2>& tiles)
  184. {
  185. for (auto const &t : tiles)
  186. define_tile(t);
  187. }
  188. int TileSet::GetTileCount() const
  189. {
  190. return int(m_tileset_data->m_tiles.size());
  191. }
  192. ivec2 TileSet::GetTileSize(int tileid) const
  193. {
  194. return m_tileset_data->m_tiles[tileid].pixel_coords.extent();
  195. }
  196. ibox2 TileSet::GetTilePixel(int tileid) const
  197. {
  198. return m_tileset_data->m_tiles[tileid].pixel_coords;
  199. }
  200. box2 TileSet::GetTileTexel(int tileid) const
  201. {
  202. return m_tileset_data->m_tiles[tileid].tex_coords;
  203. }
  204. //Palette ---------------------------------------------------------------------
  205. void TileSet::SetPalette(TileSet* palette)
  206. {
  207. m_palette = palette;
  208. }
  209. TileSet* TileSet::GetPalette()
  210. {
  211. return m_palette;
  212. }
  213. TileSet const* TileSet::GetPalette() const
  214. {
  215. return m_palette;
  216. }
  217. void TileSet::BlitTile(uint32_t id, mat4 model, vec3 *vertex, vec2 *texture)
  218. {
  219. ibox2 pixels = m_tileset_data->m_tiles[id].pixel_coords;
  220. box2 texels = m_tileset_data->m_tiles[id].tex_coords;
  221. float dtx = texels.extent().x;
  222. float dty = texels.extent().y;
  223. float tx = texels.aa.x;
  224. float ty = texels.aa.y;
  225. vec3 pos = (model * vec4(0.f, 0.f, 0.f, 1.f)).xyz;
  226. vec3 extent_x = 0.5f * pixels.extent().x * (model * vec4::axis_x).xyz;
  227. vec3 extent_y = 0.5f * pixels.extent().y * (model * vec4::axis_y).xyz;
  228. if (!m_data->m_image && m_data->m_texture)
  229. {
  230. *vertex++ = pos + extent_x + extent_y;
  231. *vertex++ = pos - extent_x + extent_y;
  232. *vertex++ = pos + extent_x - extent_y;
  233. *vertex++ = pos + extent_x - extent_y;
  234. *vertex++ = pos - extent_x + extent_y;
  235. *vertex++ = pos - extent_x - extent_y;
  236. *texture++ = vec2(tx + dtx, ty);
  237. *texture++ = vec2(tx, ty);
  238. *texture++ = vec2(tx + dtx, ty + dty);
  239. *texture++ = vec2(tx + dtx, ty + dty);
  240. *texture++ = vec2(tx, ty);
  241. *texture++ = vec2(tx, ty + dty);
  242. }
  243. else
  244. {
  245. memset((void *)vertex, 0, 6 * sizeof(vec3));
  246. memset((void *)texture, 0, 6 * sizeof(vec2));
  247. }
  248. }
  249. } /* namespace lol */