UIBatch.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. //
  2. // Copyright (c) 2008-2013 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Graphics.h"
  24. #include "Matrix3x4.h"
  25. #include "ShaderVariation.h"
  26. #include "Texture.h"
  27. #include "UIElement.h"
  28. #include "DebugNew.h"
  29. namespace Urho3D
  30. {
  31. #ifdef USE_OPENGL
  32. static const float posAdjust = 0.0f;
  33. #else
  34. static const float posAdjust = 0.5f;
  35. #endif
  36. static const Vector3 posAdjustVec(posAdjust, posAdjust, 0.0f);
  37. UIBatch::UIBatch() :
  38. element_(0),
  39. blendMode_(BLEND_REPLACE),
  40. texture_(0),
  41. vertexData_(0),
  42. vertexStart_(0),
  43. vertexEnd_(0)
  44. {
  45. }
  46. UIBatch::UIBatch(UIElement* element, BlendMode blendMode, const IntRect& scissor, Texture* texture, PODVector<float>* vertexData) :
  47. element_(element),
  48. blendMode_(blendMode),
  49. scissor_(scissor),
  50. texture_(texture),
  51. invTextureSize_(texture ? Vector2(1.0f / (float)texture->GetWidth(), 1.0f / (float)texture->GetHeight()) : Vector2::ONE),
  52. fixedColor_(element->GetDerivedColor().ToUInt()),
  53. vertexData_(vertexData),
  54. vertexStart_(vertexData->Size()),
  55. vertexEnd_(vertexData->Size())
  56. {
  57. }
  58. void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight,
  59. Color* color)
  60. {
  61. unsigned topLeftColor, topRightColor, bottomLeftColor, bottomRightColor;
  62. if (color || !element_->HasColorGradient())
  63. {
  64. unsigned uintColor = color ? color->ToUInt() : fixedColor_;
  65. // If alpha is 0, nothing will be rendered, so do not add the quad
  66. if (!(uintColor & 0xff000000))
  67. return;
  68. topLeftColor = uintColor;
  69. topRightColor = uintColor;
  70. bottomLeftColor = uintColor;
  71. bottomRightColor = uintColor;
  72. }
  73. else
  74. {
  75. topLeftColor = GetInterpolatedColor(x, y);
  76. topRightColor = GetInterpolatedColor(x + width, y);
  77. bottomLeftColor = GetInterpolatedColor(x, y + height);
  78. bottomRightColor = GetInterpolatedColor(x + width, y + height);
  79. }
  80. const IntVector2& screenPos = element_->GetScreenPosition();
  81. float left = (float)(x + screenPos.x_) - posAdjust;
  82. float right = left + (float)width;
  83. float top = (float)(y + screenPos.y_) - posAdjust;
  84. float bottom = top + (float)height;
  85. float leftUV = texOffsetX * invTextureSize_.x_;
  86. float topUV = texOffsetY * invTextureSize_.y_;
  87. float rightUV = (texOffsetX + (texWidth ? texWidth : width)) * invTextureSize_.x_;
  88. float bottomUV = (texOffsetY + (texHeight ? texHeight : height)) * invTextureSize_.y_;
  89. unsigned begin = vertexData_->Size();
  90. vertexData_->Resize(begin + 6 * 6);
  91. float* dest = &(vertexData_->At(begin));
  92. vertexEnd_ = vertexData_->Size();
  93. *dest++ = left; *dest++ = top; *dest++ = 0.0f;
  94. *((unsigned*)dest) = topLeftColor; dest++;
  95. *dest++ = leftUV; *dest++ = topUV;
  96. *dest++ = right; *dest++ = top; *dest++ = 0.0f;
  97. *((unsigned*)dest) = topRightColor; dest++;
  98. *dest++ = rightUV; *dest++ = topUV;
  99. *dest++ = left; *dest++ = bottom; *dest++ = 0.0f;
  100. *((unsigned*)dest) = bottomLeftColor; dest++;
  101. *dest++ = leftUV; *dest++ = bottomUV;
  102. *dest++ = right; *dest++ = top; *dest++ = 0.0f;
  103. *((unsigned*)dest) = topRightColor; dest++;
  104. *dest++ = rightUV; *dest++ = topUV;
  105. *dest++ = right; *dest++ = bottom; *dest++ = 0.0f;
  106. *((unsigned*)dest) = bottomRightColor; dest++;
  107. *dest++ = rightUV; *dest++ = bottomUV;
  108. *dest++ = left; *dest++ = bottom; *dest++ = 0.0f;
  109. *((unsigned*)dest) = bottomLeftColor; dest++;
  110. *dest++ = leftUV; *dest++ = bottomUV;
  111. }
  112. void UIBatch::AddQuad(const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
  113. int texWidth, int texHeight, Color* color)
  114. {
  115. unsigned topLeftColor, topRightColor, bottomLeftColor, bottomRightColor;
  116. if (color || !element_->HasColorGradient())
  117. {
  118. unsigned uintColor = color ? color->ToUInt() : fixedColor_;
  119. // If alpha is 0, nothing will be rendered, so do not add the quad
  120. if (!(uintColor & 0xff000000))
  121. return;
  122. topLeftColor = uintColor;
  123. topRightColor = uintColor;
  124. bottomLeftColor = uintColor;
  125. bottomRightColor = uintColor;
  126. }
  127. else
  128. {
  129. topLeftColor = GetInterpolatedColor(x, y);
  130. topRightColor = GetInterpolatedColor(x + width, y);
  131. bottomLeftColor = GetInterpolatedColor(x, y + height);
  132. bottomRightColor = GetInterpolatedColor(x + width, y + height);
  133. }
  134. Vector3 v1 = (transform * Vector3((float)x, (float)y, 0.0f)) - posAdjustVec;
  135. Vector3 v2 = (transform * Vector3((float)x + (float)width, (float)y, 0.0f)) - posAdjustVec;
  136. Vector3 v3 = (transform * Vector3((float)x, (float)y + (float)height, 0.0f)) - posAdjustVec;
  137. Vector3 v4 = (transform * Vector3((float)x + (float)width, (float)y + (float)height, 0.0f)) - posAdjustVec;
  138. float leftUV = ((float)texOffsetX) * invTextureSize_.x_;
  139. float topUV = ((float)texOffsetY) * invTextureSize_.y_;
  140. float rightUV = ((float)(texOffsetX + (texWidth ? texWidth : width))) * invTextureSize_.x_;
  141. float bottomUV = ((float)(texOffsetY + (texHeight ? texHeight : height))) * invTextureSize_.y_;
  142. unsigned begin = vertexData_->Size();
  143. vertexData_->Resize(begin + 6 * 6);
  144. float* dest = &(vertexData_->At(begin));
  145. vertexEnd_ = vertexData_->Size();
  146. *dest++ = v1.x_; *dest++ = v1.y_; *dest++ = 0.0f;
  147. *((unsigned*)dest) = topLeftColor; dest++;
  148. *dest++ = leftUV; *dest++ = topUV;
  149. *dest++ = v2.x_; *dest++ = v2.y_; *dest++ = 0.0f;
  150. *((unsigned*)dest) = topRightColor; dest++;
  151. *dest++ = rightUV; *dest++ = topUV;
  152. *dest++ = v3.x_; *dest++ = v3.y_; *dest++ = 0.0f;
  153. *((unsigned*)dest) = bottomLeftColor; dest++;
  154. *dest++ = leftUV; *dest++ = bottomUV;
  155. *dest++ = v2.x_; *dest++ = v2.y_; *dest++ = 0.0f;
  156. *((unsigned*)dest) = topRightColor; dest++;
  157. *dest++ = rightUV; *dest++ = topUV;
  158. *dest++ = v4.x_; *dest++ = v4.y_; *dest++ = 0.0f;
  159. *((unsigned*)dest) = bottomRightColor; dest++;
  160. *dest++ = rightUV; *dest++ = bottomUV;
  161. *dest++ = v3.x_; *dest++ = v3.y_; *dest++ = 0.0f;
  162. *((unsigned*)dest) = bottomLeftColor; dest++;
  163. *dest++ = leftUV; *dest++ = bottomUV;
  164. }
  165. void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, bool tiled)
  166. {
  167. if (!(element_->HasColorGradient() || element_->GetDerivedColor().ToUInt() & 0xff000000))
  168. return; // No gradient and alpha is 0, so do not add the quad
  169. if (!tiled)
  170. {
  171. AddQuad(x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight);
  172. return;
  173. }
  174. int tileX = 0;
  175. int tileY = 0;
  176. int tileW = 0;
  177. int tileH = 0;
  178. while (tileY < height)
  179. {
  180. tileX = 0;
  181. tileH = Min(height - tileY, texHeight);
  182. while (tileX < width)
  183. {
  184. tileW = Min(width - tileX, texWidth);
  185. AddQuad(x + tileX, y + tileY, tileW, tileH, texOffsetX, texOffsetY, tileW, tileH);
  186. tileX += tileW;
  187. }
  188. tileY += tileH;
  189. }
  190. }
  191. void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight,
  192. const Color& color)
  193. {
  194. Color derivedColor(color.r_, color.g_, color.b_, color.a_ * element_->GetDerivedOpacity());
  195. AddQuad(x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight, &derivedColor);
  196. }
  197. bool UIBatch::Merge(const UIBatch& batch)
  198. {
  199. if (batch.blendMode_ != blendMode_ ||
  200. batch.scissor_ != scissor_ ||
  201. batch.texture_ != texture_ ||
  202. batch.vertexData_ != vertexData_ ||
  203. batch.vertexStart_ != vertexEnd_)
  204. return false;
  205. vertexEnd_ = batch.vertexEnd_;
  206. return true;
  207. }
  208. unsigned UIBatch::GetInterpolatedColor(int x, int y)
  209. {
  210. const IntVector2& size = element_->GetSize();
  211. if (size.x_ && size.y_)
  212. {
  213. float cLerpX = Clamp((float)x / (float)size.x_, 0.0f, 1.0f);
  214. float cLerpY = Clamp((float)y / (float)size.y_, 0.0f, 1.0f);
  215. Color topColor = element_->GetColor(C_TOPLEFT).Lerp(element_->GetColor(C_TOPRIGHT), cLerpX);
  216. Color bottomColor = element_->GetColor(C_BOTTOMLEFT).Lerp(element_->GetColor(C_BOTTOMRIGHT), cLerpX);
  217. Color color = topColor.Lerp(bottomColor, cLerpY);
  218. color.a_ *= element_->GetDerivedOpacity();
  219. return color.ToUInt();
  220. }
  221. else
  222. {
  223. Color color = element_->GetColor(C_TOPLEFT);
  224. color.a_ *= element_->GetDerivedOpacity();
  225. return color.ToUInt();
  226. }
  227. }
  228. void UIBatch::AddOrMerge(const UIBatch& batch, PODVector<UIBatch>& batches)
  229. {
  230. if (batch.vertexEnd_ == batch.vertexStart_)
  231. return;
  232. if (!batches.Empty() && batches.Back().Merge(batch))
  233. return;
  234. batches.Push(batch);
  235. }
  236. }