BsImageSprite.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include "BsImageSprite.h"
  2. #include "BsSpriteTexture.h"
  3. #include "BsGUIMaterialManager.h"
  4. #include "BsSpriteTexture.h"
  5. #include "BsTexture.h"
  6. #include "BsProfilerCPU.h"
  7. namespace BansheeEngine
  8. {
  9. ImageSprite::ImageSprite()
  10. {
  11. }
  12. ImageSprite::~ImageSprite()
  13. {
  14. clearMesh();
  15. }
  16. void ImageSprite::update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId)
  17. {
  18. const FontData* fontData = nullptr;
  19. if(desc.texture == nullptr || desc.texture->getTexture() == nullptr)
  20. {
  21. clearMesh();
  22. return;
  23. }
  24. // Actually generate a mesh
  25. if(mCachedRenderElements.size() < 1)
  26. mCachedRenderElements.resize(1);
  27. bool useScale9Grid = desc.borderLeft > 0 || desc.borderRight > 0 ||
  28. desc.borderTop > 0 || desc.borderBottom > 0;
  29. UINT32 numQuads = 1;
  30. if(useScale9Grid)
  31. numQuads = 9;
  32. UINT32 texPage = 0;
  33. SpriteRenderElement& renderElem = mCachedRenderElements[0];
  34. {
  35. UINT32 newNumQuads = numQuads;
  36. if(newNumQuads != renderElem.numQuads)
  37. {
  38. UINT32 oldVertexCount = renderElem.numQuads * 4;
  39. UINT32 oldIndexCount = renderElem.numQuads * 6;
  40. if(renderElem.vertices != nullptr) bs_deleteN<ScratchAlloc>(renderElem.vertices, oldVertexCount);
  41. if(renderElem.uvs != nullptr) bs_deleteN<ScratchAlloc>(renderElem.uvs, oldVertexCount);
  42. if(renderElem.indexes != nullptr) bs_deleteN<ScratchAlloc>(renderElem.indexes, oldIndexCount);
  43. renderElem.vertices = bs_newN<Vector2, ScratchAlloc>(newNumQuads * 4);
  44. renderElem.uvs = bs_newN<Vector2, ScratchAlloc>(newNumQuads * 4);
  45. renderElem.indexes = bs_newN<UINT32, ScratchAlloc>(newNumQuads * 6);
  46. renderElem.numQuads = newNumQuads;
  47. }
  48. const HTexture& tex = desc.texture->getTexture();
  49. bool getNewMaterial = false;
  50. if(renderElem.matInfo.material == nullptr)
  51. getNewMaterial = true;
  52. else
  53. {
  54. const GUIMaterialInfo* matInfo = nullptr;
  55. if (desc.transparent)
  56. matInfo = GUIMaterialManager::instance().findExistingImageMaterial(groupId, tex, desc.color);
  57. else
  58. matInfo = GUIMaterialManager::instance().findExistingNonAlphaImageMaterial(groupId, tex, desc.color);
  59. if(matInfo == nullptr)
  60. {
  61. getNewMaterial = true;
  62. }
  63. else
  64. {
  65. if(matInfo->material != renderElem.matInfo.material)
  66. {
  67. GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
  68. getNewMaterial = true;
  69. }
  70. }
  71. }
  72. if (getNewMaterial)
  73. {
  74. if (desc.transparent)
  75. renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(groupId, tex, desc.color);
  76. else
  77. renderElem.matInfo = GUIMaterialManager::instance().requestNonAlphaImageMaterial(groupId, tex, desc.color);
  78. }
  79. texPage++;
  80. }
  81. for(UINT32 i = 0; i < numQuads; i++)
  82. {
  83. renderElem.indexes[i * 6 + 0] = i * 4 + 0;
  84. renderElem.indexes[i * 6 + 1] = i * 4 + 1;
  85. renderElem.indexes[i * 6 + 2] = i * 4 + 2;
  86. renderElem.indexes[i * 6 + 3] = i * 4 + 1;
  87. renderElem.indexes[i * 6 + 4] = i * 4 + 3;
  88. renderElem.indexes[i * 6 + 5] = i * 4 + 2;
  89. }
  90. Vector2I offset = getAnchorOffset(desc.anchor, desc.width, desc.height);
  91. Vector2 uvOffset = desc.uvOffset;
  92. Vector2 uvScale = desc.uvScale;
  93. if(useScale9Grid)
  94. {
  95. UINT32 leftBorder = desc.borderLeft;
  96. UINT32 rightBorder = desc.borderRight;
  97. UINT32 topBorder = desc.borderTop;
  98. UINT32 bottomBorder = desc.borderBottom;
  99. float centerWidth = (float)std::max((INT32)0, (INT32)desc.width - (INT32)leftBorder - (INT32)rightBorder);
  100. float centerHeight = (float)std::max((INT32)0, (INT32)desc.height - (INT32)topBorder - (INT32)bottomBorder);
  101. float topCenterStart = (float)(offset.x + leftBorder);
  102. float topRightStart = (float)(topCenterStart + centerWidth);
  103. float middleStart = (float)(offset.y + topBorder);
  104. float bottomStart = (float)(middleStart + centerHeight);
  105. // Top left
  106. renderElem.vertices[0] = Vector2((float)offset.x, (float)offset.y);
  107. renderElem.vertices[1] = Vector2((float)offset.x + leftBorder, (float)offset.y);
  108. renderElem.vertices[2] = Vector2((float)offset.x, middleStart);
  109. renderElem.vertices[3] = Vector2((float)offset.x + leftBorder, middleStart);
  110. // Top center
  111. renderElem.vertices[4] = Vector2(topCenterStart, (float)offset.y);
  112. renderElem.vertices[5] = Vector2(topCenterStart + centerWidth, (float)offset.y);
  113. renderElem.vertices[6] = Vector2(topCenterStart, middleStart);
  114. renderElem.vertices[7] = Vector2(topCenterStart + centerWidth, middleStart);
  115. // Top right
  116. renderElem.vertices[8] = Vector2(topRightStart, (float)offset.y);
  117. renderElem.vertices[9] = Vector2(topRightStart + rightBorder, (float)offset.y);
  118. renderElem.vertices[10] = Vector2(topRightStart, middleStart);
  119. renderElem.vertices[11] = Vector2(topRightStart + rightBorder, middleStart);
  120. // Middle left
  121. renderElem.vertices[12] = Vector2((float)offset.x, middleStart);
  122. renderElem.vertices[13] = Vector2((float)offset.x + leftBorder, middleStart);
  123. renderElem.vertices[14] = Vector2((float)offset.x, bottomStart);
  124. renderElem.vertices[15] = Vector2((float)offset.x + leftBorder, bottomStart);
  125. // Middle center
  126. renderElem.vertices[16] = Vector2(topCenterStart, middleStart);
  127. renderElem.vertices[17] = Vector2(topCenterStart + centerWidth, middleStart);
  128. renderElem.vertices[18] = Vector2(topCenterStart, bottomStart);
  129. renderElem.vertices[19] = Vector2(topCenterStart + centerWidth, bottomStart);
  130. // Middle right
  131. renderElem.vertices[20] = Vector2(topRightStart, middleStart);
  132. renderElem.vertices[21] = Vector2(topRightStart + rightBorder, middleStart);
  133. renderElem.vertices[22] = Vector2(topRightStart, bottomStart);
  134. renderElem.vertices[23] = Vector2(topRightStart + rightBorder, bottomStart);
  135. // Bottom left
  136. renderElem.vertices[24] = Vector2((float)offset.x, bottomStart);
  137. renderElem.vertices[25] = Vector2((float)offset.x + leftBorder, bottomStart);
  138. renderElem.vertices[26] = Vector2((float)offset.x, bottomStart + bottomBorder);
  139. renderElem.vertices[27] = Vector2((float)offset.x + leftBorder, bottomStart + bottomBorder);
  140. // Bottom center
  141. renderElem.vertices[28] = Vector2(topCenterStart, bottomStart);
  142. renderElem.vertices[29] = Vector2(topCenterStart + centerWidth, bottomStart);
  143. renderElem.vertices[30] = Vector2(topCenterStart, bottomStart + bottomBorder);
  144. renderElem.vertices[31] = Vector2(topCenterStart + centerWidth, bottomStart + bottomBorder);
  145. // Bottom right
  146. renderElem.vertices[32] = Vector2(topRightStart, bottomStart);
  147. renderElem.vertices[33] = Vector2(topRightStart + rightBorder, bottomStart);
  148. renderElem.vertices[34] = Vector2(topRightStart, bottomStart + bottomBorder);
  149. renderElem.vertices[35] = Vector2(topRightStart + rightBorder, bottomStart + bottomBorder);
  150. float invWidth = 1.0f / (float)desc.texture->getTexture()->getProperties().getWidth();
  151. float invHeight = 1.0f / (float)desc.texture->getTexture()->getProperties().getHeight();
  152. float uvLeftBorder = desc.borderLeft * invWidth;
  153. float uvRightBorder = desc.borderRight * invWidth;
  154. float uvTopBorder = desc.borderTop * invHeight;
  155. float uvBottomBorder = desc.borderBottom * invHeight;
  156. float uvCenterWidth = std::max(0.0f, uvScale.x - uvLeftBorder - uvRightBorder);
  157. float uvCenterHeight = std::max(0.0f, uvScale.y - uvTopBorder - uvBottomBorder);
  158. float uvTopCenterStart = uvOffset.x + uvLeftBorder;
  159. float uvTopRightStart = uvTopCenterStart + uvCenterWidth;
  160. float uvMiddleStart = uvOffset.y + uvTopBorder;
  161. float uvBottomStart = uvMiddleStart + uvCenterHeight;
  162. // UV - Top left
  163. renderElem.uvs[0] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y));
  164. renderElem.uvs[1] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvOffset.y));
  165. renderElem.uvs[2] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y + uvTopBorder));
  166. renderElem.uvs[3] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvOffset.y + uvTopBorder));
  167. // UV - Top center
  168. renderElem.uvs[4] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvOffset.y));
  169. renderElem.uvs[5] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvOffset.y));
  170. renderElem.uvs[6] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvOffset.y + uvTopBorder));
  171. renderElem.uvs[7] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvOffset.y + uvTopBorder));
  172. // UV - Top right
  173. renderElem.uvs[8] = desc.texture->transformUV(Vector2(uvTopRightStart, uvOffset.y));
  174. renderElem.uvs[9] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvOffset.y));
  175. renderElem.uvs[10] = desc.texture->transformUV(Vector2(uvTopRightStart, uvOffset.y + uvTopBorder));
  176. renderElem.uvs[11] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvOffset.y + uvTopBorder));
  177. // UV - Middle left
  178. renderElem.uvs[12] = desc.texture->transformUV(Vector2(uvOffset.x, uvMiddleStart));
  179. renderElem.uvs[13] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvMiddleStart));
  180. renderElem.uvs[14] = desc.texture->transformUV(Vector2(uvOffset.x, uvMiddleStart + uvCenterHeight));
  181. renderElem.uvs[15] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvMiddleStart + uvCenterHeight));
  182. // UV - Middle center
  183. renderElem.uvs[16] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvMiddleStart));
  184. renderElem.uvs[17] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvMiddleStart));
  185. renderElem.uvs[18] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvMiddleStart + uvCenterHeight));
  186. renderElem.uvs[19] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvMiddleStart + uvCenterHeight));
  187. // UV - Middle right
  188. renderElem.uvs[20] = desc.texture->transformUV(Vector2(uvTopRightStart, uvMiddleStart));
  189. renderElem.uvs[21] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvMiddleStart));
  190. renderElem.uvs[22] = desc.texture->transformUV(Vector2(uvTopRightStart, uvMiddleStart + uvCenterHeight));
  191. renderElem.uvs[23] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvMiddleStart + uvCenterHeight));
  192. // UV - Bottom left
  193. renderElem.uvs[24] = desc.texture->transformUV(Vector2(uvOffset.x, uvBottomStart));
  194. renderElem.uvs[25] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvBottomStart));
  195. renderElem.uvs[26] = desc.texture->transformUV(Vector2(uvOffset.x, uvBottomStart + uvBottomBorder));
  196. renderElem.uvs[27] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvBottomStart + uvBottomBorder));
  197. // UV - Bottom center
  198. renderElem.uvs[28] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvBottomStart));
  199. renderElem.uvs[29] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvBottomStart));
  200. renderElem.uvs[30] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvBottomStart + uvBottomBorder));
  201. renderElem.uvs[31] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvBottomStart + uvBottomBorder));
  202. // UV - Bottom right
  203. renderElem.uvs[32] = desc.texture->transformUV(Vector2(uvTopRightStart, uvBottomStart));
  204. renderElem.uvs[33] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvBottomStart));
  205. renderElem.uvs[34] = desc.texture->transformUV(Vector2(uvTopRightStart, uvBottomStart + uvBottomBorder));
  206. renderElem.uvs[35] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvBottomStart + uvBottomBorder));
  207. }
  208. else
  209. {
  210. renderElem.vertices[0] = Vector2((float)offset.x, (float)offset.y);
  211. renderElem.vertices[1] = Vector2((float)offset.x + desc.width, (float)offset.y);
  212. renderElem.vertices[2] = Vector2((float)offset.x, (float)offset.y + desc.height);
  213. renderElem.vertices[3] = Vector2((float)offset.x + desc.width, (float)offset.y + desc.height);
  214. renderElem.uvs[0] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y));
  215. renderElem.uvs[1] = desc.texture->transformUV(Vector2(uvOffset.x + uvScale.x, uvOffset.y));
  216. renderElem.uvs[2] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y + uvScale.y));
  217. renderElem.uvs[3] = desc.texture->transformUV(Vector2(uvOffset.x + uvScale.x, uvOffset.y + uvScale.y));
  218. }
  219. updateBounds();
  220. }
  221. void ImageSprite::clearMesh()
  222. {
  223. for (auto& renderElem : mCachedRenderElements)
  224. {
  225. UINT32 vertexCount = renderElem.numQuads * 4;
  226. UINT32 indexCount = renderElem.numQuads * 6;
  227. if (renderElem.vertices != nullptr)
  228. {
  229. bs_deleteN<ScratchAlloc>(renderElem.vertices, vertexCount);
  230. renderElem.vertices = nullptr;
  231. }
  232. if (renderElem.uvs != nullptr)
  233. {
  234. bs_deleteN<ScratchAlloc>(renderElem.uvs, vertexCount);
  235. renderElem.uvs = nullptr;
  236. }
  237. if (renderElem.indexes != nullptr)
  238. {
  239. bs_deleteN<ScratchAlloc>(renderElem.indexes, indexCount);
  240. renderElem.indexes = nullptr;
  241. }
  242. if (renderElem.matInfo.material != nullptr)
  243. {
  244. GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
  245. }
  246. }
  247. mCachedRenderElements.clear();
  248. updateBounds();
  249. }
  250. }