ScriptedEntityTweenerSubtask.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Math/Color.h>
  9. #include <ScriptedEntityTweener/ScriptedEntityTweenerBus.h>
  10. #include "ScriptedEntityTweenerSubtask.h"
  11. AZ_PUSH_DISABLE_WARNING(4244, "-Wunknown-warning-option")
  12. #include "ScriptedEntityTweenerMath.h"
  13. AZ_POP_DISABLE_WARNING
  14. namespace ScriptedEntityTweener
  15. {
  16. namespace SubtaskHelper
  17. {
  18. template <typename T>
  19. AZ_INLINE void DoSafeSet(AZ::BehaviorEBus::VirtualProperty* prop, AZ::EntityId entityId, T& data)
  20. {
  21. if (!prop || !prop->m_setter)
  22. {
  23. return;
  24. }
  25. if (prop->m_setter->m_event)
  26. {
  27. prop->m_setter->m_event->Invoke(entityId, data);
  28. }
  29. else if (prop->m_setter->m_broadcast)
  30. {
  31. prop->m_setter->m_broadcast->Invoke(data);
  32. }
  33. }
  34. template <typename T>
  35. AZ_INLINE void DoSafeGet(AZ::BehaviorEBus::VirtualProperty* prop, AZ::EntityId entityId, T& data)
  36. {
  37. if (!prop || !prop->m_getter)
  38. {
  39. return;
  40. }
  41. if (prop->m_getter->m_event)
  42. {
  43. prop->m_getter->m_event->InvokeResult(data, entityId);
  44. }
  45. else if (prop->m_getter->m_broadcast)
  46. {
  47. prop->m_getter->m_broadcast->InvokeResult(data);
  48. }
  49. }
  50. }
  51. bool ScriptedEntityTweenerSubtask::Initialize(const AnimationParameterAddressData& animParamData, const AZStd::any& targetValue, const AnimationProperties& properties)
  52. {
  53. Reset();
  54. if (CacheVirtualProperty(animParamData))
  55. {
  56. // Set initial value
  57. if (GetVirtualValue(m_valueInitial))
  58. {
  59. if (GetValueFromAny(m_valueTarget, targetValue))
  60. {
  61. m_isActive = true;
  62. m_animationProperties = properties;
  63. if (m_animationProperties.m_isFrom)
  64. {
  65. EntityAnimatedValue initialValue = m_valueInitial;
  66. m_valueInitial = m_valueTarget;
  67. m_valueTarget = initialValue;
  68. }
  69. return true;
  70. }
  71. }
  72. }
  73. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::Initialize - Initialization failed for [%s, %s]", m_animParamData.m_componentName.c_str(), m_animParamData.m_virtualPropertyName.c_str());
  74. return false;
  75. }
  76. void ScriptedEntityTweenerSubtask::Update(float deltaTime, AZStd::set<CallbackData>& callbacks)
  77. {
  78. if (m_isPaused || !m_isActive)
  79. {
  80. return;
  81. }
  82. //TODO: Use m_animationProperties.m_amplitudeOverride
  83. float timeAnimationActive = AZ::GetClamp(m_timeSinceStart + m_animationProperties.m_timeIntoAnimation, .0f, m_animationProperties.m_timeDuration);
  84. //If animation is meant to complete instantly, set timeToComplete and timeAnimationActive to the same non-zero value, so GetEasingResult will return m_valueTarget
  85. if (m_animationProperties.m_timeDuration == 0)
  86. {
  87. m_animationProperties.m_timeDuration = timeAnimationActive = 1.0f;
  88. }
  89. EntityAnimatedValue currentValue;
  90. if (m_virtualPropertyTypeId == AZ::AzTypeInfo<float>::Uuid())
  91. {
  92. float initialValue;
  93. m_valueInitial.GetValue(initialValue);
  94. float targetValue;
  95. m_valueTarget.GetValue(targetValue);
  96. currentValue.SetValue(EasingEquations::GetEasingResult(m_animationProperties.m_easeMethod, m_animationProperties.m_easeType, timeAnimationActive, m_animationProperties.m_timeDuration, initialValue, targetValue));
  97. SetVirtualValue(currentValue);
  98. }
  99. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Vector3>::Uuid() || m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Color>::Uuid())
  100. {
  101. AZ::Vector3 initialValue;
  102. m_valueInitial.GetValue(initialValue);
  103. AZ::Vector3 targetValue;
  104. m_valueTarget.GetValue(targetValue);
  105. currentValue.SetValue(EasingEquations::GetEasingResult(m_animationProperties.m_easeMethod, m_animationProperties.m_easeType, timeAnimationActive, m_animationProperties.m_timeDuration, initialValue, targetValue));
  106. SetVirtualValue(currentValue);
  107. }
  108. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Quaternion>::Uuid())
  109. {
  110. AZ::Quaternion initialValue;
  111. m_valueInitial.GetValue(initialValue);
  112. AZ::Quaternion targetValue;
  113. m_valueTarget.GetValue(targetValue);
  114. currentValue.SetValue(EasingEquations::GetEasingResult(m_animationProperties.m_easeMethod, m_animationProperties.m_easeType, timeAnimationActive, m_animationProperties.m_timeDuration, initialValue, targetValue));
  115. SetVirtualValue(currentValue);
  116. }
  117. float progressPercent = timeAnimationActive / m_animationProperties.m_timeDuration;
  118. if (m_animationProperties.m_isPlayingBackward)
  119. {
  120. progressPercent = 1.0f - progressPercent;
  121. }
  122. if (progressPercent >= 1.0f)
  123. {
  124. m_timesPlayed = m_timesPlayed + 1;
  125. if (m_timesPlayed >= m_animationProperties.m_timesToPlay && m_animationProperties.m_timesToPlay != -1)
  126. {
  127. m_isActive = false;
  128. if (m_animationProperties.m_onCompleteCallbackId != AnimationProperties::InvalidCallbackId)
  129. {
  130. callbacks.insert(CallbackData(CallbackTypes::OnComplete, m_animationProperties.m_onCompleteCallbackId));
  131. }
  132. if (m_animationProperties.m_onLoopCallbackId != AnimationProperties::InvalidCallbackId)
  133. {
  134. callbacks.insert(CallbackData(CallbackTypes::RemoveCallback, m_animationProperties.m_onLoopCallbackId));
  135. }
  136. if (m_animationProperties.m_onUpdateCallbackId != AnimationProperties::InvalidCallbackId)
  137. {
  138. callbacks.insert(CallbackData(CallbackTypes::RemoveCallback, m_animationProperties.m_onUpdateCallbackId));
  139. }
  140. }
  141. else
  142. {
  143. m_timeSinceStart = .0f;
  144. if (m_animationProperties.m_onLoopCallbackId != AnimationProperties::InvalidCallbackId)
  145. {
  146. callbacks.insert(CallbackData(CallbackTypes::OnLoop, m_animationProperties.m_onLoopCallbackId));
  147. }
  148. }
  149. }
  150. if (m_animationProperties.m_onUpdateCallbackId != AnimationProperties::InvalidCallbackId)
  151. {
  152. CallbackData updateCallback(CallbackTypes::OnUpdate, m_animationProperties.m_onUpdateCallbackId);
  153. GetValueAsAny(updateCallback.m_callbackData, currentValue);
  154. updateCallback.m_progressPercent = progressPercent;
  155. callbacks.insert(updateCallback);
  156. }
  157. if (m_animationProperties.m_isPlayingBackward)
  158. {
  159. deltaTime *= -1.0f;
  160. }
  161. m_timeSinceStart += (deltaTime * m_animationProperties.m_playbackSpeedMultiplier);
  162. }
  163. bool ScriptedEntityTweenerSubtask::CacheVirtualProperty(const AnimationParameterAddressData& animParamData)
  164. {
  165. /*
  166. Relies on some behavior context definitions for lookup
  167. behaviorContext->EBus<UiFaderBus>("UiFaderBus")
  168. ->Event("GetFadeValue", &UiFaderBus::Events::GetFadeValue)
  169. ->Event("SetFadeValue", &UiFaderBus::Events::SetFadeValue)
  170. ->VirtualProperty("Fade", "GetFadeValue", "SetFadeValue");
  171. behaviorContext->Class<UiFaderComponent>()->RequestBus("UiFaderBus");
  172. behaviorContext->EBus<UiFaderNotificationBus>("UiFaderNotificationBus")
  173. ->Handler<BehaviorUiFaderNotificationBusHandler>();
  174. */
  175. m_animParamData = animParamData;
  176. m_virtualProperty = nullptr;
  177. m_virtualPropertyTypeId = AZ::Uuid::CreateNull();
  178. AZ::BehaviorContext* behaviorContext = nullptr;
  179. AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationBus::Events::GetBehaviorContext);
  180. if (!behaviorContext)
  181. {
  182. AZ_Error("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::CacheVirtualProperty - failed to get behavior context for caching [%s]", animParamData.m_virtualPropertyName.c_str());
  183. return false;
  184. }
  185. auto findClassIter = behaviorContext->m_classes.find(animParamData.m_componentName);
  186. if (findClassIter == behaviorContext->m_classes.end())
  187. {
  188. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::CacheVirtualProperty - failed to find behavior component class by component name [%s]", animParamData.m_componentName.c_str());
  189. return false;
  190. }
  191. AZ::BehaviorEBus::VirtualProperty* virtualProperty = nullptr;
  192. AZ::Uuid virtualPropertyTypeId = AZ::Uuid::CreateNull();
  193. // Get the virtual property
  194. AZ::BehaviorClass* behaviorClass = findClassIter->second;
  195. for (auto reqBusName = behaviorClass->m_requestBuses.begin(); reqBusName != behaviorClass->m_requestBuses.end(); reqBusName++)
  196. {
  197. auto findBusIter = behaviorContext->m_ebuses.find(*reqBusName);
  198. if (findBusIter != behaviorContext->m_ebuses.end())
  199. {
  200. AZ::BehaviorEBus* behaviorEbus = findBusIter->second;
  201. auto virtualPropertyIter = behaviorEbus->m_virtualProperties.find(animParamData.m_virtualPropertyName);
  202. if (virtualPropertyIter != behaviorEbus->m_virtualProperties.end())
  203. {
  204. virtualProperty = &virtualPropertyIter->second;
  205. break;
  206. }
  207. }
  208. }
  209. AZ_Warning("ScriptedEntityTweenerSubtask", virtualProperty, "ScriptedEntityTweenerSubtask::CacheVirtualProperty - failed to find virtual property by name [%s]", animParamData.m_virtualPropertyName.c_str());
  210. // Virtual properties with event setters/getters require a valid entityId
  211. if (virtualProperty)
  212. {
  213. if (((virtualProperty->m_setter && virtualProperty->m_setter->m_event)
  214. || (virtualProperty->m_getter && virtualProperty->m_getter->m_event))
  215. && !m_entityId.IsValid())
  216. {
  217. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::CacheVirtualProperty - invalid entityId for virtual property's event setter/getter [%s, %s]", m_animParamData.m_componentName.c_str(), m_animParamData.m_virtualPropertyName.c_str());
  218. virtualProperty = nullptr;
  219. }
  220. }
  221. // Get the virtual property type
  222. if (virtualProperty)
  223. {
  224. if (virtualProperty->m_getter->m_event)
  225. {
  226. virtualPropertyTypeId = virtualProperty->m_getter->m_event->GetResult()->m_typeId;
  227. }
  228. else if (virtualProperty->m_getter->m_broadcast)
  229. {
  230. virtualPropertyTypeId = virtualProperty->m_getter->m_broadcast->GetResult()->m_typeId;
  231. }
  232. AZ_Warning("ScriptedEntityTweenerSubtask", !virtualPropertyTypeId.IsNull(), "ScriptedEntityTweenerSubtask::CacheVirtualProperty - failed to find virtual property type Id [%s]", animParamData.m_virtualPropertyName.c_str());
  233. }
  234. if (virtualProperty && !virtualPropertyTypeId.IsNull())
  235. {
  236. m_virtualProperty = virtualProperty;
  237. m_virtualPropertyTypeId = virtualPropertyTypeId;
  238. return true;
  239. }
  240. return false;
  241. }
  242. bool ScriptedEntityTweenerSubtask::IsVirtualPropertyCached()
  243. {
  244. return m_virtualProperty && !m_virtualPropertyTypeId.IsNull();
  245. }
  246. bool ScriptedEntityTweenerSubtask::GetValueFromAny(EntityAnimatedValue& value, const AZStd::any& anyValue)
  247. {
  248. if (!IsVirtualPropertyCached())
  249. {
  250. return false;
  251. }
  252. if (m_virtualPropertyTypeId == AZ::AzTypeInfo<float>::Uuid())
  253. {
  254. float floatVal;
  255. if (any_numeric_cast(&anyValue, floatVal))
  256. {
  257. value.SetValue(floatVal);
  258. }
  259. else
  260. {
  261. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::GetValueFromAny - numeric cast to float failed [%s]", m_animParamData.m_virtualPropertyName.c_str());
  262. return false;
  263. }
  264. }
  265. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Vector3>::Uuid() && anyValue.is<AZ::Vector3>())
  266. {
  267. value.SetValue(AZStd::any_cast<AZ::Vector3>(anyValue));
  268. }
  269. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Color>::Uuid() && anyValue.is<AZ::Color>())
  270. {
  271. AZ::Color color = AZStd::any_cast<AZ::Color>(anyValue);
  272. value.SetValue(color.GetAsVector3());
  273. }
  274. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Quaternion>::Uuid() && anyValue.is<AZ::Quaternion>())
  275. {
  276. value.SetValue(AZStd::any_cast<AZ::Quaternion>(anyValue));
  277. }
  278. else
  279. {
  280. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::GetValueFromAny - Virtual property type unsupported [%s]", m_animParamData.m_virtualPropertyName.c_str());
  281. return false;
  282. }
  283. return true;
  284. }
  285. bool ScriptedEntityTweenerSubtask::GetValueAsAny(AZStd::any& anyValue, const EntityAnimatedValue& value)
  286. {
  287. if (!IsVirtualPropertyCached())
  288. {
  289. return false;
  290. }
  291. if (m_virtualPropertyTypeId == AZ::AzTypeInfo<float>::Uuid())
  292. {
  293. float floatVal;
  294. value.GetValue(floatVal);
  295. anyValue = floatVal;
  296. }
  297. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Vector3>::Uuid())
  298. {
  299. AZ::Vector3 vectorValue;
  300. value.GetValue(vectorValue);
  301. anyValue = vectorValue;
  302. }
  303. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Color>::Uuid())
  304. {
  305. AZ::Vector3 vectorValue;
  306. value.GetValue(vectorValue);
  307. anyValue = AZ::Color::CreateFromVector3(vectorValue);
  308. }
  309. else if (m_virtualPropertyTypeId == AZ::AzTypeInfo<AZ::Quaternion>::Uuid())
  310. {
  311. AZ::Quaternion quatValue;
  312. value.GetValue(quatValue);
  313. anyValue = quatValue;
  314. }
  315. else
  316. {
  317. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::GetValueAsAny - Virtual property type unsupported [%s]", m_animParamData.m_virtualPropertyName.c_str());
  318. return false;
  319. }
  320. return true;
  321. }
  322. bool ScriptedEntityTweenerSubtask::GetVirtualValue(EntityAnimatedValue& animatedValue)
  323. {
  324. if (!IsVirtualPropertyCached())
  325. {
  326. return false;
  327. }
  328. if (m_virtualPropertyTypeId == AZ::AzTypeInfo<float>::Uuid())
  329. {
  330. float floatValue = 0.0f;
  331. SubtaskHelper::DoSafeGet(m_virtualProperty, m_entityId, floatValue);
  332. animatedValue.SetValue(floatValue);
  333. }
  334. else if (m_virtualPropertyTypeId == AZ::Vector3::TYPEINFO_Uuid())
  335. {
  336. AZ::Vector3 vector3Value(AZ::Vector3::CreateZero());
  337. SubtaskHelper::DoSafeGet(m_virtualProperty, m_entityId, vector3Value);
  338. animatedValue.SetValue(vector3Value);
  339. }
  340. else if (m_virtualPropertyTypeId == AZ::Color::TYPEINFO_Uuid())
  341. {
  342. AZ::Color colorValue(AZ::Color::CreateZero());
  343. SubtaskHelper::DoSafeGet(m_virtualProperty, m_entityId, colorValue);
  344. AZ::Vector3 vector3Value = colorValue.GetAsVector3();
  345. animatedValue.SetValue(vector3Value);
  346. }
  347. else if (m_virtualPropertyTypeId == AZ::Quaternion::TYPEINFO_Uuid())
  348. {
  349. AZ::Quaternion quaternionValue(AZ::Quaternion::CreateIdentity());
  350. SubtaskHelper::DoSafeGet(m_virtualProperty, m_entityId, quaternionValue);
  351. animatedValue.SetValue(quaternionValue);
  352. }
  353. else
  354. {
  355. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::GetVirtualValue - Trying to get unsupported parameter type for [%s]", m_animParamData.m_virtualPropertyName.c_str());
  356. return false;
  357. }
  358. return true;
  359. }
  360. bool ScriptedEntityTweenerSubtask::SetVirtualValue(const EntityAnimatedValue& value)
  361. {
  362. if (!IsVirtualPropertyCached())
  363. {
  364. return false;
  365. }
  366. if (m_virtualPropertyTypeId == AZ::AzTypeInfo<float>::Uuid())
  367. {
  368. float floatValue;
  369. value.GetValue(floatValue);
  370. SubtaskHelper::DoSafeSet(m_virtualProperty, m_entityId, floatValue);
  371. }
  372. else if (m_virtualPropertyTypeId == AZ::Vector3::TYPEINFO_Uuid())
  373. {
  374. AZ::Vector3 vector3Value;
  375. value.GetValue(vector3Value);
  376. SubtaskHelper::DoSafeSet(m_virtualProperty, m_entityId, vector3Value);
  377. }
  378. else if (m_virtualPropertyTypeId == AZ::Color::TYPEINFO_Uuid())
  379. {
  380. AZ::Vector3 vector3Value;
  381. value.GetValue(vector3Value);
  382. AZ::Color colorValue(AZ::Color::CreateFromVector3(vector3Value));
  383. SubtaskHelper::DoSafeSet(m_virtualProperty, m_entityId, colorValue);
  384. }
  385. else if (m_virtualPropertyTypeId == AZ::Quaternion::TYPEINFO_Uuid())
  386. {
  387. AZ::Quaternion quaternionValue;
  388. value.GetValue(quaternionValue);
  389. SubtaskHelper::DoSafeSet(m_virtualProperty, m_entityId, quaternionValue);
  390. }
  391. else
  392. {
  393. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::SetVirtualValue - Trying to set unsupported parameter type for [%s]", m_animParamData.m_virtualPropertyName.c_str());
  394. return false;
  395. }
  396. return true;
  397. }
  398. bool ScriptedEntityTweenerSubtask::GetVirtualPropertyValue(AZStd::any& returnVal, const AnimationParameterAddressData& animParamData)
  399. {
  400. // If this is called before initialization, the virtual property needs to be cached.
  401. // This method is available on the ScriptedEntityTweenerBus to retrieve a virtual property value on an entity
  402. // regardless of whether a task/subtask for that entity/virtual property has been created (added to an animation).
  403. // In that circumstance, a temproary task/subtask is created, but not initialized
  404. if (!IsVirtualPropertyCached())
  405. {
  406. CacheVirtualProperty(animParamData);
  407. }
  408. if (IsVirtualPropertyCached())
  409. {
  410. EntityAnimatedValue tempVal;
  411. if (GetVirtualValue(tempVal))
  412. {
  413. return GetValueAsAny(returnVal, tempVal);
  414. }
  415. }
  416. AZ_Warning("ScriptedEntityTweenerSubtask", false, "ScriptedEntityTweenerSubtask::GetVirtualPropertyValue - failed for [%s, %s]", m_animParamData.m_componentName.c_str(), m_animParamData.m_virtualPropertyName.c_str());
  417. return false;
  418. }
  419. }