246 lines
5.9 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #include <lol/engine-internal.h>
  11. #include <cstdlib>
  12. #include <cstdio>
  13. #include <cstring>
  14. #if defined(_WIN32) && !defined(_XBOX)
  15. # define WIN32_LEAN_AND_MEAN
  16. # include <windows.h>
  17. # if defined USE_D3D9
  18. # define FAR
  19. # define NEAR
  20. # include <d3d9.h>
  21. # endif
  22. #endif
  23. #include "textureimage-private.h"
  24. namespace lol
  25. {
  26. /*
  27. * TileSet implementation class
  28. */
  29. class TileSetData
  30. {
  31. friend class TileSet;
  32. protected:
  33. /* Pixels, then texture coordinates */
  34. array<ibox2, box2> m_tiles;
  35. ivec2 m_tile_size;
  36. };
  37. /*
  38. * Public TileSet class
  39. */
  40. TileSet::TileSet(char const *path)
  41. : TextureImage(path),
  42. m_tileset_data(new TileSetData()),
  43. m_palette(nullptr)
  44. {
  45. array<ivec2, ivec2> tiles;
  46. if (m_data->m_image->RetrieveTiles(tiles))
  47. for (int i = 0; i < tiles.count(); i++)
  48. AddTile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
  49. }
  50. TileSet::TileSet(char const *path, Image* image)
  51. : TextureImage(path, image),
  52. m_tileset_data(new TileSetData()),
  53. m_palette(nullptr)
  54. {
  55. array<ivec2, ivec2> tiles;
  56. if (m_data->m_image->RetrieveTiles(tiles))
  57. for (int i = 0; i < tiles.count(); i++)
  58. AddTile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
  59. }
  60. TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
  61. : TileSet(path)
  62. {
  63. /* If count is valid, fix size; otherwise, fix count. */
  64. if (count.x > 0 && count.y > 0)
  65. {
  66. size = m_data->m_image_size / count;
  67. }
  68. else
  69. {
  70. if (size.x <= 0 || size.y <= 0)
  71. size = ivec2(32, 32);
  72. count = max(ivec2(1, 1), m_data->m_image_size / size);
  73. }
  74. for (int j = 0; j < count.y; ++j)
  75. for (int i = 0; i < count.x; ++i)
  76. {
  77. AddTile(ibox2(size * ivec2(i, j),
  78. size * ivec2(i + 1, j + 1)));
  79. }
  80. }
  81. TileSet::TileSet(char const *path, Image* image, ivec2 size, ivec2 count)
  82. : TileSet(path, image)
  83. {
  84. /* If count is valid, fix size; otherwise, fix count. */
  85. if (count.x > 0 && count.y > 0)
  86. {
  87. size = m_data->m_image_size / count;
  88. }
  89. else
  90. {
  91. if (size.x <= 0 || size.y <= 0)
  92. size = ivec2(32, 32);
  93. count = max(ivec2(1, 1), m_data->m_image_size / size);
  94. }
  95. for (int j = 0; j < count.y; ++j)
  96. for (int i = 0; i < count.x; ++i)
  97. {
  98. AddTile(ibox2(size * ivec2(i, j),
  99. size * ivec2(i + 1, j + 1)));
  100. }
  101. }
  102. TileSet::~TileSet()
  103. {
  104. delete m_tileset_data;
  105. }
  106. void TileSet::Init(char const *path, Image* image)
  107. {
  108. super::Init(path, image);
  109. m_data->m_name = String("<tileset> ") + path;
  110. }
  111. //Inherited from Entity -------------------------------------------------------
  112. char const *TileSet::GetName()
  113. {
  114. return m_data->m_name.C();
  115. }
  116. //New methods -----------------------------------------------------------------
  117. int TileSet::AddTile(ibox2 rect)
  118. {
  119. m_tileset_data->m_tiles.push(rect,
  120. box2((vec2)rect.aa / (vec2)m_data->m_texture_size,
  121. (vec2)rect.bb / (vec2)m_data->m_texture_size));
  122. return m_tileset_data->m_tiles.count() - 1;
  123. }
  124. void TileSet::AddTile(ivec2 count)
  125. {
  126. ivec2 size = m_data->m_image_size / count;
  127. for (int j = 0; j < count.y; ++j)
  128. for (int i = 0; i < count.x; ++i)
  129. {
  130. AddTile(ibox2(size * ivec2(i, j),
  131. size * ivec2(i + 1, j + 1)));
  132. }
  133. }
  134. int TileSet::GetTileCount() const
  135. {
  136. return m_tileset_data->m_tiles.count();
  137. }
  138. ivec2 TileSet::GetTileSize(int tileid) const
  139. {
  140. return m_tileset_data->m_tiles[tileid].m1.extent();
  141. }
  142. //Palette ---------------------------------------------------------------------
  143. void TileSet::SetPalette(TileSet* palette)
  144. {
  145. m_palette = palette;
  146. }
  147. TileSet* TileSet::GetPalette()
  148. {
  149. return m_palette;
  150. }
  151. TileSet const* TileSet::GetPalette() const
  152. {
  153. return m_palette;
  154. }
  155. void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, float angle,
  156. vec3 *vertex, vec2 *texture)
  157. {
  158. ibox2 pixels = m_tileset_data->m_tiles[id].m1;
  159. box2 texels = m_tileset_data->m_tiles[id].m2;
  160. float dtx = texels.extent().x;
  161. float dty = texels.extent().y;
  162. float tx = texels.aa.x;
  163. float ty = texels.aa.y;
  164. int dx = (int)(pixels.extent().x * scale.x);
  165. int dy = o ? 0 : (int)(pixels.extent().y * scale.y);
  166. int dz = o ? (int)(pixels.extent().y * scale.y) : 0;
  167. /* If scaling is negative, switch triangle winding */
  168. if (scale.x * scale.y < 0.0f)
  169. {
  170. pos.x += dx;
  171. dx = -dx;
  172. tx += dtx;
  173. dtx = -dtx;
  174. }
  175. #if 1
  176. /* HACK: tweak UV values */
  177. tx += (1.f / 128.f) * dtx;
  178. ty += (1.f / 128.f) * dty;
  179. dtx *= 126.f / 128.f;
  180. dty *= 126.f / 128.f;
  181. #endif
  182. vec3 extent_x = 0.5f * vec3((float)dx, 0.f, 0.f);
  183. vec3 extent_y = 0.5f * vec3(0.f, (float)dy, (float)dz);
  184. vec3 center = pos + extent_x + extent_y;
  185. extent_x = mat3::rotate(angle, vec3::axis_z) * extent_x;
  186. extent_y = mat3::rotate(angle, vec3::axis_z) * extent_y;
  187. if (!m_data->m_image && m_data->m_texture)
  188. {
  189. *vertex++ = center + extent_x + extent_y;
  190. *vertex++ = center - extent_x + extent_y;
  191. *vertex++ = center + extent_x - extent_y;
  192. *vertex++ = center + extent_x - extent_y;
  193. *vertex++ = center - extent_x + extent_y;
  194. *vertex++ = center - extent_x - extent_y;
  195. *texture++ = vec2(tx + dtx, ty);
  196. *texture++ = vec2(tx, ty);
  197. *texture++ = vec2(tx + dtx, ty + dty);
  198. *texture++ = vec2(tx + dtx, ty + dty);
  199. *texture++ = vec2(tx, ty);
  200. *texture++ = vec2(tx, ty + dty);
  201. }
  202. else
  203. {
  204. memset(vertex, 0, 6 * sizeof(vec3));
  205. memset(texture, 0, 6 * sizeof(vec2));
  206. }
  207. }
  208. } /* namespace lol */