AnimatedSprite2D.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  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 "AnimatedSprite2D.h"
  24. #include "Animation2D.h"
  25. #include "AnimationSet2D.h"
  26. #include "Context.h"
  27. #include "Drawable2D.h"
  28. #include "ResourceCache.h"
  29. #include "Scene.h"
  30. #include "SceneEvents.h"
  31. #include "Sprite2D.h"
  32. #include "StaticSprite2D.h"
  33. #include "DebugNew.h"
  34. namespace Urho3D
  35. {
  36. extern const char* URHO2D_CATEGORY;
  37. extern const char* blendModeNames[];
  38. const char* loopModeNames[] =
  39. {
  40. "Default",
  41. "ForceLooped",
  42. "ForceClamped",
  43. 0
  44. };
  45. AnimatedSprite2D::AnimatedSprite2D(Context* context) :
  46. Drawable(context, DRAWABLE_GEOMETRY),
  47. layer_(0),
  48. orderInLayer_(0),
  49. blendMode_(BLEND_ALPHA),
  50. flipX_(false),
  51. flipY_(false),
  52. color_(Color::WHITE),
  53. speed_(1.0f),
  54. loopMode_(LM_DEFAULT),
  55. looped_(false),
  56. currentTime_(0.0f)
  57. {
  58. }
  59. AnimatedSprite2D::~AnimatedSprite2D()
  60. {
  61. }
  62. void AnimatedSprite2D::RegisterObject(Context* context)
  63. {
  64. context->RegisterFactory<AnimatedSprite2D>(URHO2D_CATEGORY);
  65. ACCESSOR_ATTRIBUTE("Layer", GetLayer, SetLayer, int, 0, AM_DEFAULT);
  66. ACCESSOR_ATTRIBUTE("Order in Layer", GetOrderInLayer, SetOrderInLayer, int, 0, AM_DEFAULT);
  67. ENUM_ACCESSOR_ATTRIBUTE("Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, BLEND_ALPHA, AM_DEFAULT);
  68. ACCESSOR_ATTRIBUTE("Flip X", GetFlipX, SetFlipX, bool, false, AM_DEFAULT);
  69. ACCESSOR_ATTRIBUTE("Flip Y", GetFlipY, SetFlipY, bool, false, AM_DEFAULT);
  70. ACCESSOR_ATTRIBUTE("Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
  71. ACCESSOR_ATTRIBUTE("Speed", GetSpeed, SetSpeed, float, 1.0f, AM_DEFAULT);
  72. MIXED_ACCESSOR_ATTRIBUTE("Animation Set", GetAnimationSetAttr, SetAnimationSetAttr, ResourceRef, ResourceRef(AnimatedSprite2D::GetTypeStatic()), AM_DEFAULT);
  73. ACCESSOR_ATTRIBUTE("Animation", GetAnimation, SetAnimationAttr, String, String::EMPTY, AM_DEFAULT);
  74. ENUM_ACCESSOR_ATTRIBUTE("Loop Mode", GetLoopMode, SetLoopMode, LoopMode2D, loopModeNames, LM_DEFAULT, AM_DEFAULT);
  75. COPY_BASE_ATTRIBUTES(Drawable);
  76. }
  77. void AnimatedSprite2D::OnSetEnabled()
  78. {
  79. Drawable::OnSetEnabled();
  80. Scene* scene = GetScene();
  81. if (scene)
  82. {
  83. if (IsEnabledEffective())
  84. SubscribeToEvent(scene, E_SCENEPOSTUPDATE, HANDLER(AnimatedSprite2D, HandleScenePostUpdate));
  85. else
  86. UnsubscribeFromEvent(scene, E_SCENEPOSTUPDATE);
  87. }
  88. }
  89. void AnimatedSprite2D::SetLayer(int layer)
  90. {
  91. if (layer == layer_)
  92. return;
  93. layer_ = layer;
  94. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  95. {
  96. if (!timelineNodes_[i])
  97. continue;
  98. StaticSprite2D* staticSprite = timelineNodes_[i]->GetComponent<StaticSprite2D>();
  99. staticSprite->SetLayer(layer_);
  100. }
  101. }
  102. void AnimatedSprite2D::SetOrderInLayer(int orderInLayer)
  103. {
  104. orderInLayer_ = orderInLayer;
  105. }
  106. void AnimatedSprite2D::SetBlendMode(BlendMode blendMode)
  107. {
  108. if (blendMode == blendMode_)
  109. return;
  110. blendMode_ = blendMode;
  111. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  112. {
  113. if (!timelineNodes_[i])
  114. continue;
  115. StaticSprite2D* staticSprite = timelineNodes_[i]->GetComponent<StaticSprite2D>();
  116. staticSprite->SetBlendMode(blendMode_);
  117. }
  118. }
  119. void AnimatedSprite2D::SetFlip(bool flipX, bool flipY)
  120. {
  121. if (flipX == flipX_ && flipY == flipY_)
  122. return;
  123. flipX_ = flipX;
  124. flipY_ = flipY;
  125. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  126. {
  127. if (!timelineNodes_[i])
  128. continue;
  129. StaticSprite2D* staticSprite = timelineNodes_[i]->GetComponent<StaticSprite2D>();
  130. staticSprite->SetFlip(flipX_, flipY_);
  131. }
  132. // For editor paused mode
  133. UpdateAnimation(0.0f);
  134. MarkNetworkUpdate();
  135. }
  136. void AnimatedSprite2D::SetFlipX(bool flipX)
  137. {
  138. SetFlip(flipX, flipY_);
  139. }
  140. void AnimatedSprite2D::SetFlipY(bool flipY)
  141. {
  142. SetFlip(flipX_, flipY);
  143. }
  144. void AnimatedSprite2D::SetColor(const Color& color)
  145. {
  146. color_ = color;
  147. MarkNetworkUpdate();
  148. }
  149. void AnimatedSprite2D::SetSpeed(float speed)
  150. {
  151. speed_ = speed;
  152. MarkNetworkUpdate();
  153. }
  154. void AnimatedSprite2D::SetAnimation(AnimationSet2D* animationSet, const String& name, LoopMode2D loopMode)
  155. {
  156. animationSet_ = animationSet;
  157. SetAnimation(name, loopMode);
  158. }
  159. void AnimatedSprite2D::SetAnimation(const String& name, LoopMode2D loopMode)
  160. {
  161. animationName_ = name;
  162. if (animationSet_)
  163. SetAnimation(animationSet_->GetAnimation(animationName_), loopMode);
  164. }
  165. void AnimatedSprite2D::SetAnimationSet(AnimationSet2D* animationSet)
  166. {
  167. if (animationSet == animationSet_)
  168. return;
  169. animationSet_ = animationSet;
  170. SetAnimation(animationName_, loopMode_);
  171. }
  172. void AnimatedSprite2D::SetLoopMode(LoopMode2D loopMode)
  173. {
  174. if (!animation_)
  175. return;
  176. loopMode_ = loopMode;
  177. switch (loopMode_)
  178. {
  179. case LM_FORCE_LOOPED:
  180. looped_ = true;
  181. break;
  182. case LM_FORCE_CLAMPED:
  183. looped_ = false;
  184. break;
  185. default:
  186. looped_ = animation_->IsLooped();
  187. break;
  188. }
  189. }
  190. AnimationSet2D* AnimatedSprite2D::GetAnimationSet() const
  191. {
  192. return animationSet_;
  193. }
  194. Node* AnimatedSprite2D::GetRootNode() const
  195. {
  196. return rootNode_;
  197. }
  198. void AnimatedSprite2D::SetAnimationSetAttr(const ResourceRef& value)
  199. {
  200. ResourceCache* cache = GetSubsystem<ResourceCache>();
  201. SetAnimationSet(cache->GetResource<AnimationSet2D>(value.name_));
  202. }
  203. ResourceRef AnimatedSprite2D::GetAnimationSetAttr() const
  204. {
  205. return GetResourceRef(animationSet_, AnimationSet2D::GetTypeStatic());
  206. }
  207. void AnimatedSprite2D::OnNodeSet(Node* node)
  208. {
  209. Drawable::OnNodeSet(node);
  210. if (node)
  211. {
  212. Scene* scene = GetScene();
  213. if (scene && IsEnabledEffective())
  214. SubscribeToEvent(scene, E_SCENEPOSTUPDATE, HANDLER(AnimatedSprite2D, HandleScenePostUpdate));
  215. }
  216. else
  217. {
  218. if (rootNode_)
  219. rootNode_->Remove();
  220. rootNode_ = 0;
  221. timelineNodes_.Clear();
  222. }
  223. }
  224. void AnimatedSprite2D::SetAnimationAttr(const String& name)
  225. {
  226. animationName_ = name;
  227. if (animationSet_)
  228. SetAnimation(animationSet_->GetAnimation(animationName_), loopMode_);
  229. }
  230. void AnimatedSprite2D::OnWorldBoundingBoxUpdate()
  231. {
  232. boundingBox_.Clear();
  233. worldBoundingBox_.Clear();
  234. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  235. {
  236. if (!timelineNodes_[i])
  237. continue;
  238. StaticSprite2D* staticSprite = timelineNodes_[i]->GetComponent<StaticSprite2D>();
  239. if (staticSprite)
  240. worldBoundingBox_.Merge(staticSprite->GetWorldBoundingBox());
  241. }
  242. boundingBox_ = worldBoundingBox_.Transformed(node_->GetWorldTransform().Inverse());
  243. }
  244. void AnimatedSprite2D::SetAnimation(Animation2D* animation, LoopMode2D loopMode)
  245. {
  246. if (animation == animation_)
  247. {
  248. SetLoopMode(loopMode_);
  249. currentTime_ = 0.0f;
  250. UpdateAnimation(0.0f);
  251. return;
  252. }
  253. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  254. {
  255. if (timelineNodes_[i])
  256. timelineNodes_[i]->SetEnabled(false);
  257. }
  258. timelineNodes_.Clear();
  259. animation_ = animation;
  260. if (!animation_)
  261. return;
  262. currentTime_ = 0.0f;
  263. if (!rootNode_)
  264. {
  265. rootNode_ = GetNode()->CreateChild("RootNode", LOCAL);
  266. rootNode_->SetTemporary(true);
  267. }
  268. timelineNodes_.Resize(animation_->GetNumTimelines());
  269. timelineTransformInfos_.Resize(animation_->GetNumTimelines());
  270. for (unsigned i = 0; i < animation_->GetNumTimelines(); ++i)
  271. {
  272. const Timeline2D& timeline = animation->GetTimeline(i);
  273. SharedPtr<Node> timelineNode(rootNode_->GetChild(timeline.name_));
  274. StaticSprite2D* staticSprite = 0;
  275. if (timelineNode)
  276. {
  277. // Enable timeline node
  278. timelineNode->SetEnabled(true);
  279. // Get StaticSprite2D component
  280. if (timeline.type_ == OT_SPRITE)
  281. staticSprite = timelineNode->GetComponent<StaticSprite2D>();
  282. }
  283. else
  284. {
  285. // Create new timeline node
  286. timelineNode = rootNode_->CreateChild(timeline.name_, LOCAL);
  287. // Create StaticSprite2D component
  288. if (timeline.type_ == OT_SPRITE)
  289. staticSprite = timelineNode->CreateComponent<StaticSprite2D>();
  290. }
  291. if (staticSprite)
  292. {
  293. staticSprite->SetLayer(layer_);
  294. staticSprite->SetBlendMode(blendMode_);
  295. staticSprite->SetFlip(flipX_, flipY_);
  296. staticSprite->SetUseHotSpot(true);
  297. }
  298. timelineNodes_[i] = timelineNode;
  299. timelineTransformInfos_[i].parent_ = timeline.parent_;
  300. }
  301. SetLoopMode(loopMode);
  302. UpdateAnimation(0.0f);
  303. MarkNetworkUpdate();
  304. }
  305. void AnimatedSprite2D::UpdateAnimation(float timeStep)
  306. {
  307. if (!animation_)
  308. return;
  309. currentTime_ += timeStep * speed_;
  310. float time;
  311. float animtationLength = animation_->GetLength();
  312. if (looped_)
  313. {
  314. time = fmodf(currentTime_, animtationLength);
  315. if (time < 0.0f)
  316. time += animation_->GetLength();
  317. }
  318. else
  319. time = Clamp(currentTime_, 0.0f, animtationLength);
  320. // Update timeline's local transform
  321. for (unsigned i = 0; i < timelineTransformInfos_.Size(); ++i)
  322. {
  323. const Timeline2D& timeline = animation_->GetTimeline(i);
  324. const Vector<TimelineKey2D>& objectKeys = timeline.timelineKeys_;
  325. unsigned index = objectKeys.Size() - 1;
  326. for (unsigned j = 0; j < objectKeys.Size() - 1; ++j)
  327. {
  328. if (time <= objectKeys[j + 1].time_)
  329. {
  330. index = j;
  331. break;
  332. }
  333. }
  334. const TimelineKey2D& currKey = objectKeys[index];
  335. if (index < objectKeys.Size() - 1)
  336. {
  337. const TimelineKey2D& nextKey = objectKeys[index + 1];
  338. float t = (time - currKey.time_) / (nextKey.time_ - currKey.time_);
  339. timelineTransformInfos_[i].worldSpace_ = false;
  340. timelineTransformInfos_[i].transform_ = currKey.transform_.Lerp(nextKey.transform_, t, currKey.spin_);
  341. // Update sprite's sprite and hot spot and color
  342. Node* timelineNode = timelineNodes_[i];
  343. if (timelineNode)
  344. {
  345. StaticSprite2D* staticSprite = timelineNode->GetComponent<StaticSprite2D>();
  346. if (staticSprite)
  347. {
  348. staticSprite->SetSprite(currKey.sprite_);
  349. staticSprite->SetHotSpot(currKey.hotSpot_.Lerp(nextKey.hotSpot_, t));
  350. float alpha = Lerp(currKey.alpha_, nextKey.alpha_, t);
  351. staticSprite->SetColor(Color(color_.r_, color_.g_, color_.b_, color_.a_ * alpha));
  352. }
  353. }
  354. }
  355. else
  356. {
  357. timelineTransformInfos_[i].worldSpace_ = false;
  358. timelineTransformInfos_[i].transform_ = currKey.transform_;
  359. // Update sprite's sprite and hot spot and color
  360. Node* timelineNode = timelineNodes_[i];
  361. if (timelineNode)
  362. {
  363. StaticSprite2D* staticSprite = timelineNode->GetComponent<StaticSprite2D>();
  364. if (staticSprite)
  365. {
  366. staticSprite->SetSprite(currKey.sprite_);
  367. staticSprite->SetHotSpot(currKey.hotSpot_);
  368. staticSprite->SetColor(Color(color_.r_, color_.g_, color_.b_, color_.a_ * currKey.alpha_));
  369. }
  370. }
  371. }
  372. }
  373. // Calculate timeline world transform.
  374. for (unsigned i = 0; i < timelineTransformInfos_.Size(); ++i)
  375. CalculateTimelineWorldTransform(i);
  376. // Get mainline key
  377. const Vector<MainlineKey2D>& mainlineKeys = animation_->GetMainlineKeys();
  378. const MainlineKey2D* mainlineKey = 0;
  379. for (unsigned i = 1; i < mainlineKeys.Size(); ++i)
  380. {
  381. if (time < mainlineKeys[i].time_)
  382. {
  383. mainlineKey = &mainlineKeys[i - 1];
  384. break;
  385. }
  386. }
  387. if (!mainlineKey)
  388. mainlineKey = &mainlineKeys.Back();
  389. // Update node's transform and sprite's z order
  390. for (unsigned i = 0; i < timelineNodes_.Size(); ++i)
  391. {
  392. Node* timelineNode = timelineNodes_[i];
  393. if (!timelineNode)
  394. continue;
  395. const Reference2D* ref = mainlineKey->GetReference(i);
  396. if (!ref)
  397. {
  398. // Disable node
  399. if (timelineNode->IsEnabled())
  400. timelineNode->SetEnabled(false);
  401. }
  402. else
  403. {
  404. // Enable node
  405. if (!timelineNode->IsEnabled())
  406. timelineNode->SetEnabled(true);
  407. // Update node's transform
  408. const Transform2D& transform = timelineTransformInfos_[i].transform_;
  409. Vector2 position = transform.position_ * PIXEL_SIZE;
  410. if (flipX_)
  411. position.x_ = -position.x_;
  412. if (flipY_)
  413. position.y_ = -position.y_;
  414. timelineNode->SetPosition(position);
  415. float angle = transform.angle_;
  416. if (flipX_ != flipY_)
  417. angle = -angle;
  418. timelineNode->SetRotation(angle);
  419. timelineNode->SetScale(transform.scale_);
  420. // Update sprite's z order
  421. StaticSprite2D* staticSprite = timelineNode->GetComponent<StaticSprite2D>();
  422. if (staticSprite)
  423. staticSprite->SetOrderInLayer(orderInLayer_ + ref->zIndex_);
  424. }
  425. }
  426. MarkForUpdate();
  427. }
  428. void AnimatedSprite2D::CalculateTimelineWorldTransform(unsigned index)
  429. {
  430. TransformInfo& info = timelineTransformInfos_[index];
  431. if (info.worldSpace_)
  432. return;
  433. info.worldSpace_ = true;
  434. if (info.parent_ != -1)
  435. {
  436. CalculateTimelineWorldTransform(info.parent_);
  437. info.transform_ = timelineTransformInfos_[info.parent_].transform_ * info.transform_;
  438. }
  439. }
  440. void AnimatedSprite2D::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
  441. {
  442. using namespace ScenePostUpdate;
  443. float timeStep = eventData[P_TIMESTEP].GetFloat();
  444. UpdateAnimation(timeStep);
  445. }
  446. }