Sprite.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. //
  2. // Copyright (c) 2008-2014 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 "Context.h"
  24. #include "ResourceCache.h"
  25. #include "Sprite.h"
  26. #include "Texture2D.h"
  27. #include "DebugNew.h"
  28. namespace Urho3D
  29. {
  30. extern const char* blendModeNames[];
  31. extern const char* horizontalAlignments[];
  32. extern const char* verticalAlignments[];
  33. extern const char* UI_CATEGORY;
  34. Sprite::Sprite(Context* context) :
  35. UIElement(context),
  36. floatPosition_(Vector2::ZERO),
  37. hotSpot_(IntVector2::ZERO),
  38. scale_(Vector2::ONE),
  39. rotation_(0.0f),
  40. imageRect_(IntRect::ZERO),
  41. blendMode_(BLEND_REPLACE)
  42. {
  43. }
  44. Sprite::~Sprite()
  45. {
  46. }
  47. void Sprite::RegisterObject(Context* context)
  48. {
  49. context->RegisterFactory<Sprite>(UI_CATEGORY);
  50. REF_ACCESSOR_ATTRIBUTE("Name", GetName, SetName, String, String::EMPTY, AM_FILE);
  51. REF_ACCESSOR_ATTRIBUTE("Position", GetPosition, SetPosition, Vector2, Vector2::ZERO, AM_FILE);
  52. REF_ACCESSOR_ATTRIBUTE("Size", GetSize, SetSize, IntVector2, IntVector2::ZERO, AM_FILE);
  53. REF_ACCESSOR_ATTRIBUTE("Hotspot", GetHotSpot, SetHotSpot, IntVector2, IntVector2::ZERO, AM_FILE);
  54. REF_ACCESSOR_ATTRIBUTE("Scale", GetScale, SetScale, Vector2, Vector2::ONE, AM_FILE);
  55. ACCESSOR_ATTRIBUTE("Rotation", GetRotation, SetRotation, float, 0.0f, AM_FILE);
  56. MIXED_ACCESSOR_ATTRIBUTE("Texture", GetTextureAttr, SetTextureAttr, ResourceRef, ResourceRef(Texture2D::GetTypeStatic()), AM_FILE);
  57. REF_ACCESSOR_ATTRIBUTE("Image Rect", GetImageRect, SetImageRect, IntRect, IntRect::ZERO, AM_FILE);
  58. ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
  59. ENUM_ACCESSOR_ATTRIBUTE("Horiz Alignment", GetHorizontalAlignment, SetHorizontalAlignment, HorizontalAlignment, horizontalAlignments, HA_LEFT, AM_FILE);
  60. ENUM_ACCESSOR_ATTRIBUTE("Vert Alignment", GetVerticalAlignment, SetVerticalAlignment, VerticalAlignment, verticalAlignments, VA_TOP, AM_FILE);
  61. ACCESSOR_ATTRIBUTE("Priority", GetPriority, SetPriority, int, 0, AM_FILE);
  62. ACCESSOR_ATTRIBUTE("Opacity", GetOpacity, SetOpacity, float, 1.0f, AM_FILE);
  63. REF_ACCESSOR_ATTRIBUTE("Color", GetColorAttr, SetColor, Color, Color::WHITE, AM_FILE);
  64. ATTRIBUTE(VAR_COLOR, "Top Left Color", color_[0], Color::WHITE, AM_FILE);
  65. ATTRIBUTE(VAR_COLOR, "Top Right Color", color_[1], Color::WHITE, AM_FILE);
  66. ATTRIBUTE(VAR_COLOR, "Bottom Left Color", color_[2], Color::WHITE, AM_FILE);
  67. ATTRIBUTE(VAR_COLOR, "Bottom Right Color", color_[3], Color::WHITE, AM_FILE);
  68. ACCESSOR_ATTRIBUTE("Is Visible", IsVisible, SetVisible, bool, true, AM_FILE);
  69. ACCESSOR_ATTRIBUTE("Use Derived Opacity", GetUseDerivedOpacity, SetUseDerivedOpacity, bool, true, AM_FILE);
  70. ATTRIBUTE(VAR_VARIANTMAP, "Variables", vars_, Variant::emptyVariantMap, AM_FILE);
  71. }
  72. bool Sprite::IsWithinScissor(const IntRect& currentScissor)
  73. {
  74. /// \todo Implement properly, for now just checks visibility flag
  75. return visible_;
  76. }
  77. const IntVector2& Sprite::GetScreenPosition() const
  78. {
  79. // This updates screen position for a sprite
  80. GetTransform();
  81. return screenPosition_;
  82. }
  83. void Sprite::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
  84. {
  85. bool allOpaque = true;
  86. if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
  87. color_[C_BOTTOMLEFT].a_ < 1.0f || color_[C_BOTTOMRIGHT].a_ < 1.0f)
  88. allOpaque = false;
  89. const IntVector2& size = GetSize();
  90. UIBatch batch(this, blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &vertexData);
  91. batch.AddQuad(GetTransform(), 0, 0, size.x_, size.y_, imageRect_.left_, imageRect_.top_, imageRect_.right_ -
  92. imageRect_.left_, imageRect_.bottom_ - imageRect_.top_);
  93. UIBatch::AddOrMerge(batch, batches);
  94. // Reset hovering for next frame
  95. hovering_ = false;
  96. }
  97. void Sprite::OnPositionSet()
  98. {
  99. // If the integer position was set (layout update?), copy to the float position
  100. floatPosition_ = Vector2((float)position_.x_, (float)position_.y_);
  101. }
  102. void Sprite::SetPosition(const Vector2& position)
  103. {
  104. if (position != floatPosition_)
  105. {
  106. floatPosition_ = position;
  107. // Copy to the integer position
  108. position_ = IntVector2((int)position.x_, (int)position.y_);
  109. MarkDirty();
  110. }
  111. }
  112. void Sprite::SetPosition(float x, float y)
  113. {
  114. SetPosition(Vector2(x, y));
  115. }
  116. void Sprite::SetHotSpot(const IntVector2& hotSpot)
  117. {
  118. if (hotSpot != hotSpot_)
  119. {
  120. hotSpot_ = hotSpot;
  121. MarkDirty();
  122. }
  123. }
  124. void Sprite::SetHotSpot(int x, int y)
  125. {
  126. SetHotSpot(IntVector2(x, y));
  127. }
  128. void Sprite::SetScale(const Vector2& scale)
  129. {
  130. if (scale != scale_)
  131. {
  132. scale_ = scale;
  133. MarkDirty();
  134. }
  135. }
  136. void Sprite::SetScale(float x, float y)
  137. {
  138. SetScale(Vector2(x, y));
  139. }
  140. void Sprite::SetScale(float scale)
  141. {
  142. SetScale(Vector2(scale, scale));
  143. }
  144. void Sprite::SetRotation(float angle)
  145. {
  146. if (angle != rotation_)
  147. {
  148. rotation_ = angle;
  149. MarkDirty();
  150. }
  151. }
  152. void Sprite::SetTexture(Texture* texture)
  153. {
  154. texture_ = texture;
  155. if (imageRect_ == IntRect::ZERO)
  156. SetFullImageRect();
  157. }
  158. void Sprite::SetImageRect(const IntRect& rect)
  159. {
  160. if (rect != IntRect::ZERO)
  161. imageRect_ = rect;
  162. }
  163. void Sprite::SetFullImageRect()
  164. {
  165. if (texture_)
  166. SetImageRect(IntRect(0, 0, texture_->GetWidth(), texture_->GetHeight()));
  167. }
  168. void Sprite::SetBlendMode(BlendMode mode)
  169. {
  170. blendMode_ = mode;
  171. }
  172. const Matrix3x4& Sprite::GetTransform() const
  173. {
  174. if (positionDirty_)
  175. {
  176. Vector2 pos = floatPosition_;
  177. Matrix3x4 parentTransform;
  178. if (parent_)
  179. {
  180. Sprite* parentSprite = dynamic_cast<Sprite*>(parent_);
  181. if (parentSprite)
  182. parentTransform = parentSprite->GetTransform();
  183. else
  184. {
  185. const IntVector2& parentScreenPos = parent_->GetScreenPosition() + parent_->GetChildOffset();
  186. parentTransform = Matrix3x4::IDENTITY;
  187. parentTransform.SetTranslation(Vector3((float)parentScreenPos.x_, (float)parentScreenPos.y_, 0.0f));
  188. }
  189. switch (GetHorizontalAlignment())
  190. {
  191. case HA_LEFT:
  192. break;
  193. case HA_CENTER:
  194. pos.x_ += (float)(parent_->GetSize().x_ / 2);
  195. break;
  196. case HA_RIGHT:
  197. pos.x_ += (float)parent_->GetSize().x_;
  198. break;
  199. }
  200. switch (GetVerticalAlignment())
  201. {
  202. case VA_TOP:
  203. break;
  204. case VA_CENTER:
  205. pos.y_ += (float)(parent_->GetSize().y_ / 2);
  206. break;
  207. case VA_BOTTOM:
  208. pos.y_ += (float)(parent_->GetSize().y_);
  209. break;
  210. }
  211. }
  212. else
  213. parentTransform = Matrix3x4::IDENTITY;
  214. Matrix3x4 hotspotAdjust(Matrix3x4::IDENTITY);
  215. hotspotAdjust.SetTranslation(Vector3((float)-hotSpot_.x_, (float)-hotSpot_.y_, 0.0f));
  216. Matrix3x4 mainTransform(Vector3(pos, 0.0f), Quaternion(rotation_, Vector3::FORWARD), Vector3(scale_, 1.0f));
  217. transform_ = parentTransform * mainTransform * hotspotAdjust;
  218. positionDirty_ = false;
  219. // Calculate an approximate screen position for GetElementAt(), or pixel-perfect child elements
  220. Vector3 topLeftCorner = transform_ * Vector3::ZERO;
  221. screenPosition_ = IntVector2((int)topLeftCorner.x_, (int)topLeftCorner.y_);
  222. }
  223. return transform_;
  224. }
  225. void Sprite::SetTextureAttr(const ResourceRef& value)
  226. {
  227. ResourceCache* cache = GetSubsystem<ResourceCache>();
  228. SetTexture(cache->GetResource<Texture2D>(value.name_));
  229. }
  230. ResourceRef Sprite::GetTextureAttr() const
  231. {
  232. return GetResourceRef(texture_, Texture2D::GetTypeStatic());
  233. }
  234. }