StaticSprite2D.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. //
  2. // Copyright (c) 2008-2020 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 "../Core/Context.h"
  24. #include "../Graphics/Material.h"
  25. #include "../Graphics/Texture2D.h"
  26. #include "../Resource/ResourceCache.h"
  27. #include "../Scene/Scene.h"
  28. #include "../Urho2D/Renderer2D.h"
  29. #include "../Urho2D/Sprite2D.h"
  30. #include "../Urho2D/StaticSprite2D.h"
  31. #include "../DebugNew.h"
  32. namespace Urho3D
  33. {
  34. extern const char* URHO2D_CATEGORY;
  35. extern const char* blendModeNames[];
  36. StaticSprite2D::StaticSprite2D(Context* context) :
  37. Drawable2D(context),
  38. blendMode_(BLEND_ALPHA),
  39. flipX_(false),
  40. flipY_(false),
  41. swapXY_(false),
  42. color_(Color::WHITE),
  43. useHotSpot_(false),
  44. useDrawRect_(false),
  45. useTextureRect_(false),
  46. hotSpot_(0.5f, 0.5f),
  47. drawRect_(Rect::ZERO),
  48. textureRect_(Rect::ZERO)
  49. {
  50. sourceBatches_.Resize(1);
  51. sourceBatches_[0].owner_ = this;
  52. }
  53. StaticSprite2D::~StaticSprite2D() = default;
  54. void StaticSprite2D::RegisterObject(Context* context)
  55. {
  56. context->RegisterFactory<StaticSprite2D>(URHO2D_CATEGORY);
  57. URHO3D_ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
  58. URHO3D_COPY_BASE_ATTRIBUTES(Drawable2D);
  59. URHO3D_MIXED_ACCESSOR_ATTRIBUTE("Sprite", GetSpriteAttr, SetSpriteAttr, ResourceRef, ResourceRef(Sprite2D::GetTypeStatic()),
  60. AM_DEFAULT);
  61. URHO3D_ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT);
  62. URHO3D_ACCESSOR_ATTRIBUTE("Flip X", GetFlipX, SetFlipX, bool, false, AM_DEFAULT);
  63. URHO3D_ACCESSOR_ATTRIBUTE("Flip Y", GetFlipY, SetFlipY, bool, false, AM_DEFAULT);
  64. URHO3D_ACCESSOR_ATTRIBUTE("Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
  65. URHO3D_MIXED_ACCESSOR_ATTRIBUTE("Custom material", GetCustomMaterialAttr, SetCustomMaterialAttr, ResourceRef,
  66. ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
  67. URHO3D_ACCESSOR_ATTRIBUTE("Hot Spot", GetHotSpot, SetHotSpot, Vector2, Vector2(0.5f, 0.5f), AM_DEFAULT);
  68. URHO3D_ACCESSOR_ATTRIBUTE("Use Hot Spot", GetUseHotSpot, SetUseHotSpot, bool, false, AM_DEFAULT);
  69. URHO3D_ACCESSOR_ATTRIBUTE("Draw Rectangle", GetDrawRect, SetDrawRect, Rect, Rect::ZERO, AM_DEFAULT);
  70. URHO3D_ACCESSOR_ATTRIBUTE("Use Draw Rectangle", GetUseDrawRect, SetUseDrawRect, bool, false, AM_DEFAULT);
  71. URHO3D_ACCESSOR_ATTRIBUTE("Texture Rectangle", GetTextureRect, SetTextureRect, Rect, Rect::ZERO, AM_DEFAULT);
  72. URHO3D_ACCESSOR_ATTRIBUTE("Use Texture Rectangle", GetUseTextureRect, SetUseTextureRect, bool, false, AM_DEFAULT);
  73. }
  74. void StaticSprite2D::SetSprite(Sprite2D* sprite)
  75. {
  76. if (sprite == sprite_)
  77. return;
  78. sprite_ = sprite;
  79. UpdateMaterial();
  80. sourceBatchesDirty_ = true;
  81. MarkNetworkUpdate();
  82. UpdateDrawRect();
  83. }
  84. void StaticSprite2D::SetDrawRect(const Rect& rect)
  85. {
  86. drawRect_ = rect;
  87. if(useDrawRect_)
  88. {
  89. sourceBatchesDirty_ = true;
  90. }
  91. }
  92. void StaticSprite2D::SetTextureRect(const Rect& rect)
  93. {
  94. textureRect_ = rect;
  95. if(useTextureRect_)
  96. {
  97. sourceBatchesDirty_ = true;
  98. }
  99. }
  100. void StaticSprite2D::SetBlendMode(BlendMode blendMode)
  101. {
  102. if (blendMode == blendMode_)
  103. return;
  104. blendMode_ = blendMode;
  105. UpdateMaterial();
  106. MarkNetworkUpdate();
  107. }
  108. void StaticSprite2D::SetFlip(bool flipX, bool flipY, bool swapXY)
  109. {
  110. if (flipX == flipX_ && flipY == flipY_ && swapXY == swapXY_)
  111. return;
  112. flipX_ = flipX;
  113. flipY_ = flipY;
  114. swapXY_ = swapXY;
  115. sourceBatchesDirty_ = true;
  116. MarkNetworkUpdate();
  117. }
  118. void StaticSprite2D::SetFlipX(bool flipX)
  119. {
  120. SetFlip(flipX, flipY_, swapXY_);
  121. }
  122. void StaticSprite2D::SetFlipY(bool flipY)
  123. {
  124. SetFlip(flipX_, flipY, swapXY_);
  125. }
  126. void StaticSprite2D::SetSwapXY(bool swapXY)
  127. {
  128. SetFlip(flipX_, flipY_, swapXY);
  129. }
  130. void StaticSprite2D::SetColor(const Color& color)
  131. {
  132. if (color == color_)
  133. return;
  134. color_ = color;
  135. sourceBatchesDirty_ = true;
  136. MarkNetworkUpdate();
  137. }
  138. void StaticSprite2D::SetAlpha(float alpha)
  139. {
  140. if (alpha == color_.a_)
  141. return;
  142. color_.a_ = alpha;
  143. sourceBatchesDirty_ = true;
  144. MarkNetworkUpdate();
  145. }
  146. void StaticSprite2D::SetUseHotSpot(bool useHotSpot)
  147. {
  148. if (useHotSpot == useHotSpot_)
  149. return;
  150. useHotSpot_ = useHotSpot;
  151. sourceBatchesDirty_ = true;
  152. MarkNetworkUpdate();
  153. UpdateDrawRect();
  154. }
  155. void StaticSprite2D::SetUseDrawRect(bool useDrawRect)
  156. {
  157. if (useDrawRect == useDrawRect_)
  158. return;
  159. useDrawRect_ = useDrawRect;
  160. sourceBatchesDirty_ = true;
  161. MarkNetworkUpdate();
  162. UpdateDrawRect();
  163. }
  164. void StaticSprite2D::SetUseTextureRect(bool useTextureRect)
  165. {
  166. if (useTextureRect == useTextureRect_)
  167. return;
  168. useTextureRect_ = useTextureRect;
  169. sourceBatchesDirty_ = true;
  170. MarkNetworkUpdate();
  171. }
  172. void StaticSprite2D::SetHotSpot(const Vector2& hotspot)
  173. {
  174. if (hotspot == hotSpot_)
  175. return;
  176. hotSpot_ = hotspot;
  177. if (useHotSpot_)
  178. {
  179. sourceBatchesDirty_ = true;
  180. MarkNetworkUpdate();
  181. }
  182. UpdateDrawRect();
  183. }
  184. void StaticSprite2D::SetCustomMaterial(Material* customMaterial)
  185. {
  186. if (customMaterial == customMaterial_)
  187. return;
  188. customMaterial_ = customMaterial;
  189. sourceBatchesDirty_ = true;
  190. UpdateMaterial();
  191. MarkNetworkUpdate();
  192. }
  193. Sprite2D* StaticSprite2D::GetSprite() const
  194. {
  195. return sprite_;
  196. }
  197. Material* StaticSprite2D::GetCustomMaterial() const
  198. {
  199. return customMaterial_;
  200. }
  201. void StaticSprite2D::SetSpriteAttr(const ResourceRef& value)
  202. {
  203. Sprite2D* sprite = Sprite2D::LoadFromResourceRef(this, value);
  204. if (sprite)
  205. SetSprite(sprite);
  206. }
  207. ResourceRef StaticSprite2D::GetSpriteAttr() const
  208. {
  209. return Sprite2D::SaveToResourceRef(sprite_);
  210. }
  211. void StaticSprite2D::SetCustomMaterialAttr(const ResourceRef& value)
  212. {
  213. auto* cache = GetSubsystem<ResourceCache>();
  214. SetCustomMaterial(cache->GetResource<Material>(value.name_));
  215. }
  216. ResourceRef StaticSprite2D::GetCustomMaterialAttr() const
  217. {
  218. return GetResourceRef(customMaterial_, Material::GetTypeStatic());
  219. }
  220. void StaticSprite2D::OnSceneSet(Scene* scene)
  221. {
  222. Drawable2D::OnSceneSet(scene);
  223. UpdateMaterial();
  224. }
  225. void StaticSprite2D::OnWorldBoundingBoxUpdate()
  226. {
  227. boundingBox_.Clear();
  228. worldBoundingBox_.Clear();
  229. const Vector<SourceBatch2D>& sourceBatches = GetSourceBatches();
  230. for (unsigned i = 0; i < sourceBatches[0].vertices_.Size(); ++i)
  231. worldBoundingBox_.Merge(sourceBatches[0].vertices_[i].position_);
  232. boundingBox_ = worldBoundingBox_.Transformed(node_->GetWorldTransform().Inverse());
  233. }
  234. void StaticSprite2D::OnDrawOrderChanged()
  235. {
  236. sourceBatches_[0].drawOrder_ = GetDrawOrder();
  237. }
  238. void StaticSprite2D::UpdateSourceBatches()
  239. {
  240. if (!sourceBatchesDirty_)
  241. return;
  242. Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_;
  243. vertices.Clear();
  244. if (!sprite_)
  245. return;
  246. if (!useTextureRect_)
  247. {
  248. if (!sprite_->GetTextureRectangle(textureRect_, flipX_, flipY_))
  249. return;
  250. }
  251. /*
  252. V1---------V2
  253. | / |
  254. | / |
  255. | / |
  256. | / |
  257. | / |
  258. V0---------V3
  259. */
  260. Vertex2D vertex0;
  261. Vertex2D vertex1;
  262. Vertex2D vertex2;
  263. Vertex2D vertex3;
  264. // Convert to world space
  265. const Matrix3x4& worldTransform = node_->GetWorldTransform();
  266. vertex0.position_ = worldTransform * Vector3(drawRect_.min_.x_, drawRect_.min_.y_, 0.0f);
  267. vertex1.position_ = worldTransform * Vector3(drawRect_.min_.x_, drawRect_.max_.y_, 0.0f);
  268. vertex2.position_ = worldTransform * Vector3(drawRect_.max_.x_, drawRect_.max_.y_, 0.0f);
  269. vertex3.position_ = worldTransform * Vector3(drawRect_.max_.x_, drawRect_.min_.y_, 0.0f);
  270. vertex0.uv_ = textureRect_.min_;
  271. (swapXY_ ? vertex3.uv_ : vertex1.uv_) = Vector2(textureRect_.min_.x_, textureRect_.max_.y_);
  272. vertex2.uv_ = textureRect_.max_;
  273. (swapXY_ ? vertex1.uv_ : vertex3.uv_) = Vector2(textureRect_.max_.x_, textureRect_.min_.y_);
  274. vertex0.color_ = vertex1.color_ = vertex2.color_ = vertex3.color_ = color_.ToUInt();
  275. vertices.Push(vertex0);
  276. vertices.Push(vertex1);
  277. vertices.Push(vertex2);
  278. vertices.Push(vertex3);
  279. sourceBatchesDirty_ = false;
  280. }
  281. void StaticSprite2D::UpdateMaterial()
  282. {
  283. if (customMaterial_)
  284. sourceBatches_[0].material_ = customMaterial_;
  285. else
  286. {
  287. if (sprite_ && renderer_)
  288. sourceBatches_[0].material_ = renderer_->GetMaterial(sprite_->GetTexture(), blendMode_);
  289. else
  290. sourceBatches_[0].material_ = nullptr;
  291. }
  292. }
  293. void StaticSprite2D::UpdateDrawRect()
  294. {
  295. if (!useDrawRect_)
  296. {
  297. if (useHotSpot_)
  298. {
  299. if (sprite_ && !sprite_->GetDrawRectangle(drawRect_, hotSpot_, flipX_, flipY_))
  300. return;
  301. }
  302. else
  303. {
  304. if (sprite_ && !sprite_->GetDrawRectangle(drawRect_, flipX_, flipY_))
  305. return;
  306. }
  307. }
  308. }
  309. }