CmImageSprite.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "CmImageSprite.h"
  2. #include "CmSpriteTexture.h"
  3. #include "CmGUIMaterialManager.h"
  4. namespace CamelotEngine
  5. {
  6. ImageSprite::ImageSprite()
  7. {
  8. }
  9. void ImageSprite::update(const IMAGE_SPRITE_DESC& desc)
  10. {
  11. const FontData* fontData = nullptr;
  12. if(desc.texture == nullptr || desc.texture->getTexture() == nullptr)
  13. {
  14. clearMesh();
  15. return;
  16. }
  17. // Actually generate a mesh
  18. if(mCachedRenderElements.size() < 1)
  19. mCachedRenderElements.resize(1);
  20. bool useScale9Grid = desc.borderLeft > 0 || desc.borderRight > 0 ||
  21. desc.borderTop > 0 || desc.borderBottom > 0;
  22. UINT32 numQuads = 1;
  23. if(useScale9Grid)
  24. numQuads = 9;
  25. UINT32 texPage = 0;
  26. SpriteRenderElement& renderElem = mCachedRenderElements[0];
  27. {
  28. UINT32 newNumQuads = numQuads;
  29. if(newNumQuads != renderElem.numQuads)
  30. {
  31. UINT32 oldVertexCount = renderElem.numQuads * 4;
  32. UINT32 oldIndexCount = renderElem.numQuads * 6;
  33. if(renderElem.vertices != nullptr) CM_DELETE_ARRAY(renderElem.vertices, Vector2, oldVertexCount, ScratchAlloc);
  34. if(renderElem.uvs != nullptr) CM_DELETE_ARRAY(renderElem.uvs, Vector2, oldVertexCount, ScratchAlloc);
  35. if(renderElem.indexes != nullptr) CM_DELETE_ARRAY(renderElem.indexes, UINT32, oldIndexCount, ScratchAlloc);
  36. renderElem.vertices = CM_NEW_ARRAY(Vector2, newNumQuads * 4, ScratchAlloc);
  37. renderElem.uvs = CM_NEW_ARRAY(Vector2, newNumQuads * 4, ScratchAlloc);
  38. renderElem.indexes = CM_NEW_ARRAY(UINT32, newNumQuads * 6, ScratchAlloc);
  39. renderElem.numQuads = newNumQuads;
  40. }
  41. HMaterial newMaterial = GUIMaterialManager::instance().requestImageMaterial(desc.texture->getTexture());
  42. if(renderElem.material != nullptr)
  43. GUIMaterialManager::instance().releaseMaterial(newMaterial);
  44. renderElem.material = newMaterial;
  45. texPage++;
  46. }
  47. for(UINT32 i = 0; i < numQuads; i++)
  48. {
  49. renderElem.indexes[i * 6 + 0] = i * 4 + 0;
  50. renderElem.indexes[i * 6 + 1] = i * 4 + 1;
  51. renderElem.indexes[i * 6 + 2] = i * 4 + 2;
  52. renderElem.indexes[i * 6 + 3] = i * 4 + 1;
  53. renderElem.indexes[i * 6 + 4] = i * 4 + 3;
  54. renderElem.indexes[i * 6 + 5] = i * 4 + 2;
  55. }
  56. Point offset = desc.offset + getAnchorOffset(desc.anchor, desc.width, desc.height);
  57. Vector2 uvOffset(0.0f, 0.0f);
  58. Vector2 uvScale(1.0f, 1.0f);
  59. if(useScale9Grid)
  60. {
  61. UINT32 leftBorder = desc.borderLeft;
  62. UINT32 rightBorder = desc.borderRight;
  63. UINT32 topBorder = desc.borderTop;
  64. UINT32 bottomBorder = desc.borderBottom;
  65. float centerWidth = (float)std::max((UINT32)0, desc.width - leftBorder - rightBorder);
  66. float centerHeight = (float)std::max((UINT32)0, desc.height - topBorder - bottomBorder);
  67. float topCenterStart = (float)(offset.x + leftBorder);
  68. float topRightStart = (float)(topCenterStart + centerWidth);
  69. float middleStart = (float)(offset.y + topBorder);
  70. float bottomStart = (float)(middleStart + centerHeight);
  71. // Top left
  72. renderElem.vertices[0] = Vector2((float)offset.x, (float)offset.y);
  73. renderElem.vertices[1] = Vector2((float)offset.x + leftBorder, (float)offset.y);
  74. renderElem.vertices[2] = Vector2((float)offset.x, (float)offset.y - topBorder);
  75. renderElem.vertices[3] = Vector2((float)offset.x + leftBorder, (float)offset.y - topBorder);
  76. // Top center
  77. renderElem.vertices[4] = Vector2(topCenterStart, (float)offset.y);
  78. renderElem.vertices[5] = Vector2(topCenterStart + centerWidth, (float)offset.y);
  79. renderElem.vertices[6] = Vector2(topCenterStart, (float)offset.y - topBorder);
  80. renderElem.vertices[7] = Vector2(topCenterStart + centerWidth, (float)offset.y - topBorder);
  81. // Top right
  82. renderElem.vertices[8] = Vector2(topRightStart, (float)offset.y);
  83. renderElem.vertices[9] = Vector2(topRightStart + rightBorder, (float)offset.y);
  84. renderElem.vertices[10] = Vector2(topRightStart, (float)offset.y - topBorder);
  85. renderElem.vertices[11] = Vector2(topRightStart + rightBorder, (float)offset.y - topBorder);
  86. // Middle left
  87. renderElem.vertices[12] = Vector2((float)offset.x, middleStart);
  88. renderElem.vertices[13] = Vector2((float)offset.x + leftBorder, middleStart);
  89. renderElem.vertices[14] = Vector2((float)offset.x, middleStart - centerHeight);
  90. renderElem.vertices[15] = Vector2((float)offset.x + leftBorder, middleStart - centerHeight);
  91. // Middle center
  92. renderElem.vertices[16] = Vector2(topCenterStart, middleStart);
  93. renderElem.vertices[17] = Vector2(topCenterStart + centerWidth, middleStart);
  94. renderElem.vertices[18] = Vector2(topCenterStart, middleStart - centerHeight);
  95. renderElem.vertices[19] = Vector2(topCenterStart + centerWidth, middleStart - centerHeight);
  96. // Middle right
  97. renderElem.vertices[20] = Vector2(topRightStart, middleStart);
  98. renderElem.vertices[21] = Vector2(topRightStart + rightBorder, middleStart);
  99. renderElem.vertices[22] = Vector2(topRightStart, middleStart - centerHeight);
  100. renderElem.vertices[23] = Vector2(topRightStart + rightBorder, middleStart - centerHeight);
  101. // Bottom left
  102. renderElem.vertices[24] = Vector2((float)offset.x, bottomStart);
  103. renderElem.vertices[25] = Vector2((float)offset.x + leftBorder, bottomStart);
  104. renderElem.vertices[26] = Vector2((float)offset.x, bottomStart - bottomBorder);
  105. renderElem.vertices[27] = Vector2((float)offset.x + leftBorder, bottomStart - bottomBorder);
  106. // Bottom center
  107. renderElem.vertices[28] = Vector2(topCenterStart, bottomStart);
  108. renderElem.vertices[29] = Vector2(topCenterStart + centerWidth, bottomStart);
  109. renderElem.vertices[30] = Vector2(topCenterStart, bottomStart - bottomBorder);
  110. renderElem.vertices[31] = Vector2(topCenterStart + centerWidth, bottomStart - bottomBorder);
  111. // Bottom right
  112. renderElem.vertices[32] = Vector2(topRightStart, bottomStart);
  113. renderElem.vertices[33] = Vector2(topRightStart + rightBorder, bottomStart);
  114. renderElem.vertices[34] = Vector2(topRightStart, bottomStart - bottomBorder);
  115. renderElem.vertices[35] = Vector2(topRightStart + rightBorder, bottomStart - bottomBorder);
  116. float invWidth = 1.0f / (float)desc.width;
  117. float invHeight = 1.0f / (float)desc.height;
  118. float uvLeftBorder = desc.borderLeft * invWidth;
  119. float uvRightBorder = desc.borderRight * invWidth;
  120. float uvTopBorder = desc.borderTop * invHeight;
  121. float uvBottomBorder = desc.borderBottom * invHeight;
  122. float uvCenterWidth = std::max(0.0f, uvScale.x - uvLeftBorder - uvRightBorder);
  123. float uvCenterHeight = std::max(0.0f, uvScale.y - uvTopBorder - uvBottomBorder);
  124. float uvTopCenterStart = uvOffset.x + uvLeftBorder;
  125. float uvTopRightStart = uvTopCenterStart + uvCenterWidth;
  126. float uvMiddleStart = uvOffset.y + uvTopBorder;
  127. float uvBottomStart = uvMiddleStart + uvCenterHeight;
  128. // UV - Top left
  129. renderElem.uvs[0] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y));
  130. renderElem.uvs[1] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvOffset.y));
  131. renderElem.uvs[2] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y + uvTopBorder));
  132. renderElem.uvs[3] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvOffset.y + uvTopBorder));
  133. // UV - Top center
  134. renderElem.uvs[4] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvOffset.y));
  135. renderElem.uvs[5] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvOffset.y));
  136. renderElem.uvs[6] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvOffset.y + uvTopBorder));
  137. renderElem.uvs[7] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvOffset.y + uvTopBorder));
  138. // UV - Top right
  139. renderElem.uvs[8] = desc.texture->transformUV(Vector2(uvTopRightStart, uvOffset.y));
  140. renderElem.uvs[9] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvOffset.y));
  141. renderElem.uvs[10] = desc.texture->transformUV(Vector2(uvTopRightStart, uvOffset.y + uvTopBorder));
  142. renderElem.uvs[11] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvOffset.y + uvTopBorder));
  143. // UV - Middle left
  144. renderElem.uvs[12] = desc.texture->transformUV(Vector2(uvOffset.x, uvMiddleStart));
  145. renderElem.uvs[13] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvMiddleStart));
  146. renderElem.uvs[14] = desc.texture->transformUV(Vector2(uvOffset.x, uvMiddleStart + uvCenterHeight));
  147. renderElem.uvs[15] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvMiddleStart + uvCenterHeight));
  148. // UV - Middle center
  149. renderElem.uvs[16] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvMiddleStart));
  150. renderElem.uvs[17] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvMiddleStart));
  151. renderElem.uvs[18] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvMiddleStart + uvCenterHeight));
  152. renderElem.uvs[19] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvMiddleStart + uvCenterHeight));
  153. // UV - Middle right
  154. renderElem.uvs[20] = desc.texture->transformUV(Vector2(uvTopRightStart, uvMiddleStart));
  155. renderElem.uvs[21] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvMiddleStart));
  156. renderElem.uvs[22] = desc.texture->transformUV(Vector2(uvTopRightStart, uvMiddleStart + uvCenterHeight));
  157. renderElem.uvs[23] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvMiddleStart + uvCenterHeight));
  158. // UV - Bottom left
  159. renderElem.uvs[24] = desc.texture->transformUV(Vector2(uvOffset.x, uvBottomStart));
  160. renderElem.uvs[25] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvBottomStart));
  161. renderElem.uvs[26] = desc.texture->transformUV(Vector2(uvOffset.x, uvBottomStart + uvBottomBorder));
  162. renderElem.uvs[27] = desc.texture->transformUV(Vector2(uvOffset.x + uvLeftBorder, uvBottomStart + uvBottomBorder));
  163. // UV - Bottom center
  164. renderElem.uvs[28] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvBottomStart));
  165. renderElem.uvs[29] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvBottomStart));
  166. renderElem.uvs[30] = desc.texture->transformUV(Vector2(uvTopCenterStart, uvBottomStart + uvBottomBorder));
  167. renderElem.uvs[31] = desc.texture->transformUV(Vector2(uvTopCenterStart + uvCenterWidth, uvBottomStart + uvBottomBorder));
  168. // UV - Bottom right
  169. renderElem.uvs[32] = desc.texture->transformUV(Vector2(uvTopRightStart, uvBottomStart));
  170. renderElem.uvs[33] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvBottomStart));
  171. renderElem.uvs[34] = desc.texture->transformUV(Vector2(uvTopRightStart, uvBottomStart + uvBottomBorder));
  172. renderElem.uvs[35] = desc.texture->transformUV(Vector2(uvTopRightStart + uvRightBorder, uvBottomStart + uvBottomBorder));
  173. }
  174. else
  175. {
  176. renderElem.vertices[0] = Vector2((float)offset.x, (float)offset.y);
  177. renderElem.vertices[1] = Vector2((float)offset.x + desc.width, (float)offset.y);
  178. renderElem.vertices[2] = Vector2((float)offset.x, (float)offset.y - desc.height);
  179. renderElem.vertices[3] = Vector2((float)offset.x + desc.width, (float)offset.y - desc.height);
  180. renderElem.uvs[0] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y));
  181. renderElem.uvs[1] = desc.texture->transformUV(Vector2(uvOffset.x + uvScale.x, uvOffset.y));
  182. renderElem.uvs[2] = desc.texture->transformUV(Vector2(uvOffset.x, uvOffset.y + uvScale.y));
  183. renderElem.uvs[3] = desc.texture->transformUV(Vector2(uvOffset.x + uvScale.x, uvOffset.y + uvScale.y));
  184. }
  185. if(desc.clipRect.width > 0 && desc.clipRect.height > 0)
  186. {
  187. clipToRect(renderElem.vertices, renderElem.uvs, renderElem.numQuads, desc.clipRect);
  188. }
  189. updateBounds();
  190. }
  191. }