You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

280 line
6.2 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 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. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdlib>
  14. #include <cstdio>
  15. #include <cstring>
  16. #if defined WIN32 && !defined _XBOX
  17. # define WIN32_LEAN_AND_MEAN
  18. # include <windows.h>
  19. # if defined USE_D3D9
  20. # define FAR
  21. # define NEAR
  22. # include <d3d9.h>
  23. # endif
  24. #endif
  25. #include "core.h"
  26. using namespace std;
  27. namespace lol
  28. {
  29. /*
  30. * TileSet implementation class
  31. */
  32. class TileSetData
  33. {
  34. friend class TileSet;
  35. private:
  36. String m_name;
  37. /* Pixels, then texture coordinates */
  38. Array<ibox2, box2> m_tiles;
  39. ivec2 m_tile_size, m_image_size, m_texture_size;
  40. Image *m_image;
  41. Texture *m_texture;
  42. };
  43. /*
  44. * Public TileSet class
  45. */
  46. TileSet::TileSet(char const *path)
  47. : m_data(new TileSetData())
  48. {
  49. Init(path);
  50. }
  51. TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
  52. : m_data(new TileSetData())
  53. {
  54. Init(path);
  55. /* If count is valid, fix size; otherwise, fix count. */
  56. if (count.x > 0 && count.y > 0)
  57. {
  58. size = m_data->m_image_size / count;
  59. }
  60. else
  61. {
  62. if (size.x <= 0 || size.y <= 0)
  63. size = ivec2(32, 32);
  64. count = max(ivec2(1, 1), m_data->m_image_size / size);
  65. }
  66. for (int j = 0; j < count.y; ++j)
  67. for (int i = 0; i < count.x; ++i)
  68. {
  69. AddTile(ibox2(size * ivec2(i, j),
  70. size * ivec2(i + 1, j + 1)));
  71. }
  72. }
  73. void TileSet::Init(char const *path)
  74. {
  75. m_data->m_name = String("<tileset> ") + path;
  76. m_data->m_texture = 0;
  77. m_data->m_image = Image::Create(path);
  78. m_data->m_image_size = m_data->m_image->GetSize();
  79. m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x),
  80. PotUp(m_data->m_image_size.y));
  81. m_drawgroup = DRAWGROUP_BEFORE;
  82. }
  83. int TileSet::AddTile(ibox2 rect)
  84. {
  85. m_data->m_tiles.Push(rect,
  86. box2((vec2)rect.A / (vec2)m_data->m_texture_size,
  87. (vec2)rect.B / (vec2)m_data->m_texture_size));
  88. return m_data->m_tiles.Count() - 1;
  89. }
  90. TileSet::~TileSet()
  91. {
  92. delete m_data;
  93. }
  94. void TileSet::TickDraw(float seconds)
  95. {
  96. Entity::TickDraw(seconds);
  97. if (IsDestroying())
  98. {
  99. if (m_data->m_image)
  100. {
  101. Image::Destroy(m_data->m_image);
  102. m_data->m_image = nullptr;
  103. }
  104. else
  105. {
  106. delete m_data->m_texture;
  107. m_data->m_texture = nullptr;
  108. }
  109. }
  110. else if (m_data->m_image)
  111. {
  112. PixelFormat format = m_data->m_image->GetFormat();
  113. int planes = format.BytesPerPixel();
  114. int w = m_data->m_texture_size.x;
  115. int h = m_data->m_texture_size.y;
  116. uint8_t *pixels = m_data->m_image->GetData();
  117. if (w != m_data->m_image_size.x || h != m_data->m_image_size.y)
  118. {
  119. uint8_t *tmp = new uint8_t[planes * w * h];
  120. for (int line = 0; line < m_data->m_image_size.y; line++)
  121. memcpy(tmp + planes * w * line,
  122. pixels + planes * m_data->m_image_size.x * line,
  123. planes * m_data->m_image_size.x);
  124. pixels = tmp;
  125. }
  126. m_data->m_texture = new Texture(ivec2(w, h), format);
  127. m_data->m_texture->SetData(pixels);
  128. if (pixels != m_data->m_image->GetData())
  129. delete[] pixels;
  130. Image::Destroy(m_data->m_image);
  131. m_data->m_image = nullptr;
  132. }
  133. }
  134. char const *TileSet::GetName()
  135. {
  136. return m_data->m_name.C();
  137. }
  138. int TileSet::GetTileCount() const
  139. {
  140. return m_data->m_tiles.Count();
  141. }
  142. ivec2 TileSet::GetTileSize(int tileid) const
  143. {
  144. ibox2 const &box = m_data->m_tiles[tileid].m1;
  145. return box.B - box.A;
  146. }
  147. ivec2 TileSet::GetTextureSize() const
  148. {
  149. return m_data->m_texture_size;
  150. }
  151. ShaderTexture TileSet::GetTexture() const
  152. {
  153. return m_data->m_texture->GetTexture();
  154. }
  155. void TileSet::Bind()
  156. {
  157. if (!m_data->m_image && m_data->m_texture)
  158. m_data->m_texture->Bind();
  159. }
  160. void TileSet::Unbind()
  161. {
  162. ;
  163. }
  164. void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
  165. float *vertex, float *texture)
  166. {
  167. ibox2 pixels = m_data->m_tiles[id].m1;
  168. box2 texels = m_data->m_tiles[id].m2;
  169. float dtx = texels.B.x - texels.A.x;
  170. float dty = texels.B.y - texels.A.y;
  171. float tx = texels.A.x;
  172. float ty = texels.A.y;
  173. int dx = (pixels.B.x - pixels.A.x) * scale.x;
  174. int dy = o ? 0 : (pixels.B.y - pixels.A.y) * scale.y;
  175. int dz = o ? (pixels.B.y - pixels.A.y) * scale.y : 0;
  176. /* If scaling is negative, switch triangle winding */
  177. if (scale.x * scale.y < 0.0f)
  178. {
  179. pos.x += dx;
  180. dx = -dx;
  181. tx += dtx;
  182. dtx = -dtx;
  183. }
  184. #if 1
  185. /* HACK: tweak UV values */
  186. tx += (1.f / 128.f) * dtx;
  187. ty += (1.f / 128.f) * dty;
  188. dtx *= 126.f / 128.f;
  189. dty *= 126.f / 128.f;
  190. #endif
  191. if (!m_data->m_image && m_data->m_texture)
  192. {
  193. float tmp[10];
  194. *vertex++ = pos.x + dx;
  195. *vertex++ = pos.y + dy;
  196. *vertex++ = pos.z + dz;
  197. *texture++ = tx + dtx;
  198. *texture++ = ty;
  199. *vertex++ = tmp[0] = pos.x;
  200. *vertex++ = tmp[1] = pos.y + dy;
  201. *vertex++ = tmp[2] = pos.z + dz;
  202. *texture++ = tmp[3] = tx;
  203. *texture++ = tmp[4] = ty;
  204. *vertex++ = tmp[5] = pos.x + dx;
  205. *vertex++ = tmp[6] = pos.y;
  206. *vertex++ = tmp[7] = pos.z;
  207. *texture++ = tmp[8] = tx + dtx;
  208. *texture++ = tmp[9] = ty + dty;
  209. *vertex++ = tmp[5];
  210. *vertex++ = tmp[6];
  211. *vertex++ = tmp[7];
  212. *texture++ = tmp[8];
  213. *texture++ = tmp[9];
  214. *vertex++ = tmp[0];
  215. *vertex++ = tmp[1];
  216. *vertex++ = tmp[2];
  217. *texture++ = tmp[3];
  218. *texture++ = tmp[4];
  219. *vertex++ = pos.x;
  220. *vertex++ = pos.y;
  221. *vertex++ = pos.z;
  222. *texture++ = tx;
  223. *texture++ = ty + dty;
  224. }
  225. else
  226. {
  227. memset(vertex, 0, 3 * sizeof(float));
  228. memset(texture, 0, 2 * sizeof(float));
  229. }
  230. }
  231. } /* namespace lol */