ScriptedEntityTweenerSubtask.cpp 19 KB

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