ObjectAnimation.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../Resource/XMLFile.h"
  6. #include "../Resource/JSONFile.h"
  7. #include "../Scene/ObjectAnimation.h"
  8. #include "../Scene/SceneEvents.h"
  9. #include "../Scene/ValueAnimation.h"
  10. #include "../Scene/ValueAnimationInfo.h"
  11. #include "../DebugNew.h"
  12. namespace Urho3D
  13. {
  14. const char* wrapModeNames[] =
  15. {
  16. "Loop",
  17. "Once",
  18. "Clamp",
  19. nullptr
  20. };
  21. ObjectAnimation::ObjectAnimation(Context* context) :
  22. Resource(context)
  23. {
  24. }
  25. ObjectAnimation::~ObjectAnimation() = default;
  26. void ObjectAnimation::RegisterObject(Context* context)
  27. {
  28. context->RegisterFactory<ObjectAnimation>();
  29. }
  30. bool ObjectAnimation::BeginLoad(Deserializer& source)
  31. {
  32. XMLFile xmlFile(context_);
  33. if (!xmlFile.Load(source))
  34. return false;
  35. return LoadXML(xmlFile.GetRoot());
  36. }
  37. bool ObjectAnimation::Save(Serializer& dest) const
  38. {
  39. XMLFile xmlFile(context_);
  40. XMLElement rootElem = xmlFile.CreateRoot("objectanimation");
  41. if (!SaveXML(rootElem))
  42. return false;
  43. return xmlFile.Save(dest);
  44. }
  45. bool ObjectAnimation::LoadXML(const XMLElement& source)
  46. {
  47. attributeAnimationInfos_.Clear();
  48. XMLElement animElem;
  49. animElem = source.GetChild("attributeanimation");
  50. while (animElem)
  51. {
  52. String name = animElem.GetAttribute("name");
  53. SharedPtr<ValueAnimation> animation(new ValueAnimation(context_));
  54. if (!animation->LoadXML(animElem))
  55. return false;
  56. String wrapModeString = animElem.GetAttribute("wrapmode");
  57. WrapMode wrapMode = WM_LOOP;
  58. for (int i = 0; i <= WM_CLAMP; ++i)
  59. {
  60. if (wrapModeString == wrapModeNames[i])
  61. {
  62. wrapMode = (WrapMode)i;
  63. break;
  64. }
  65. }
  66. float speed = animElem.GetFloat("speed");
  67. AddAttributeAnimation(name, animation, wrapMode, speed);
  68. animElem = animElem.GetNext("attributeanimation");
  69. }
  70. return true;
  71. }
  72. bool ObjectAnimation::SaveXML(XMLElement& dest) const
  73. {
  74. for (HashMap<String, SharedPtr<ValueAnimationInfo>>::ConstIterator i = attributeAnimationInfos_.Begin();
  75. i != attributeAnimationInfos_.End(); ++i)
  76. {
  77. XMLElement animElem = dest.CreateChild("attributeanimation");
  78. animElem.SetAttribute("name", i->first_);
  79. const ValueAnimationInfo* info = i->second_;
  80. if (!info->GetAnimation()->SaveXML(animElem))
  81. return false;
  82. animElem.SetAttribute("wrapmode", wrapModeNames[info->GetWrapMode()]);
  83. animElem.SetFloat("speed", info->GetSpeed());
  84. }
  85. return true;
  86. }
  87. bool ObjectAnimation::LoadJSON(const JSONValue& source)
  88. {
  89. attributeAnimationInfos_.Clear();
  90. JSONValue attributeAnimationsValue = source.Get("attributeanimations");
  91. if (attributeAnimationsValue.IsNull())
  92. return true;
  93. if (!attributeAnimationsValue.IsObject())
  94. return true;
  95. const JSONObject& attributeAnimationsObject = attributeAnimationsValue.GetObject();
  96. for (JSONObject::ConstIterator it = attributeAnimationsObject.Begin(); it != attributeAnimationsObject.End(); it++)
  97. {
  98. String name = it->first_;
  99. JSONValue value = it->second_;
  100. SharedPtr<ValueAnimation> animation(new ValueAnimation(context_));
  101. if (!animation->LoadJSON(value))
  102. return false;
  103. String wrapModeString = value.Get("wrapmode").GetString();
  104. WrapMode wrapMode = WM_LOOP;
  105. for (int i = 0; i <= WM_CLAMP; ++i)
  106. {
  107. if (wrapModeString == wrapModeNames[i])
  108. {
  109. wrapMode = (WrapMode)i;
  110. break;
  111. }
  112. }
  113. float speed = value.Get("speed").GetFloat();
  114. AddAttributeAnimation(name, animation, wrapMode, speed);
  115. }
  116. return true;
  117. }
  118. bool ObjectAnimation::SaveJSON(JSONValue& dest) const
  119. {
  120. JSONValue attributeAnimationsValue;
  121. for (HashMap<String, SharedPtr<ValueAnimationInfo>>::ConstIterator i = attributeAnimationInfos_.Begin();
  122. i != attributeAnimationInfos_.End(); ++i)
  123. {
  124. JSONValue animValue;
  125. animValue.Set("name", i->first_);
  126. const ValueAnimationInfo* info = i->second_;
  127. if (!info->GetAnimation()->SaveJSON(animValue))
  128. return false;
  129. animValue.Set("wrapmode", wrapModeNames[info->GetWrapMode()]);
  130. animValue.Set("speed", (float) info->GetSpeed());
  131. attributeAnimationsValue.Set(i->first_, animValue);
  132. }
  133. dest.Set("attributeanimations", attributeAnimationsValue);
  134. return true;
  135. }
  136. void ObjectAnimation::AddAttributeAnimation(const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed)
  137. {
  138. if (!attributeAnimation)
  139. return;
  140. attributeAnimation->SetOwner(this);
  141. attributeAnimationInfos_[name] = new ValueAnimationInfo(attributeAnimation, wrapMode, speed);
  142. SendAttributeAnimationAddedEvent(name);
  143. }
  144. void ObjectAnimation::RemoveAttributeAnimation(const String& name)
  145. {
  146. HashMap<String, SharedPtr<ValueAnimationInfo>>::Iterator i = attributeAnimationInfos_.Find(name);
  147. if (i != attributeAnimationInfos_.End())
  148. {
  149. SendAttributeAnimationRemovedEvent(name);
  150. i->second_->GetAnimation()->SetOwner(nullptr);
  151. attributeAnimationInfos_.Erase(i);
  152. }
  153. }
  154. void ObjectAnimation::RemoveAttributeAnimation(ValueAnimation* attributeAnimation)
  155. {
  156. if (!attributeAnimation)
  157. return;
  158. for (HashMap<String, SharedPtr<ValueAnimationInfo>>::Iterator i = attributeAnimationInfos_.Begin();
  159. i != attributeAnimationInfos_.End(); ++i)
  160. {
  161. if (i->second_->GetAnimation() == attributeAnimation)
  162. {
  163. SendAttributeAnimationRemovedEvent(i->first_);
  164. attributeAnimation->SetOwner(nullptr);
  165. attributeAnimationInfos_.Erase(i);
  166. return;
  167. }
  168. }
  169. }
  170. ValueAnimation* ObjectAnimation::GetAttributeAnimation(const String& name) const
  171. {
  172. ValueAnimationInfo* info = GetAttributeAnimationInfo(name);
  173. return info ? info->GetAnimation() : nullptr;
  174. }
  175. WrapMode ObjectAnimation::GetAttributeAnimationWrapMode(const String& name) const
  176. {
  177. ValueAnimationInfo* info = GetAttributeAnimationInfo(name);
  178. return info ? info->GetWrapMode() : WM_LOOP;
  179. }
  180. float ObjectAnimation::GetAttributeAnimationSpeed(const String& name) const
  181. {
  182. ValueAnimationInfo* info = GetAttributeAnimationInfo(name);
  183. return info ? info->GetSpeed() : 1.0f;
  184. }
  185. ValueAnimationInfo* ObjectAnimation::GetAttributeAnimationInfo(const String& name) const
  186. {
  187. HashMap<String, SharedPtr<ValueAnimationInfo>>::ConstIterator i = attributeAnimationInfos_.Find(name);
  188. if (i != attributeAnimationInfos_.End())
  189. return i->second_;
  190. return nullptr;
  191. }
  192. void ObjectAnimation::SendAttributeAnimationAddedEvent(const String& name)
  193. {
  194. using namespace AttributeAnimationAdded;
  195. VariantMap& eventData = GetEventDataMap();
  196. eventData[P_OBJECTANIMATION] = this;
  197. eventData[P_ATTRIBUTEANIMATIONNAME] = name;
  198. SendEvent(E_ATTRIBUTEANIMATIONADDED, eventData);
  199. }
  200. void ObjectAnimation::SendAttributeAnimationRemovedEvent(const String& name)
  201. {
  202. using namespace AttributeAnimationRemoved;
  203. VariantMap& eventData = GetEventDataMap();
  204. eventData[P_OBJECTANIMATION] = this;
  205. eventData[P_ATTRIBUTEANIMATIONNAME] = name;
  206. SendEvent(E_ATTRIBUTEANIMATIONREMOVED, eventData);
  207. }
  208. }