SmoothedTransform.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../Scene/Scene.h"
  6. #include "../Scene/SceneEvents.h"
  7. #include "../Scene/SmoothedTransform.h"
  8. #include "../DebugNew.h"
  9. namespace Urho3D
  10. {
  11. SmoothedTransform::SmoothedTransform(Context* context) :
  12. Component(context),
  13. targetPosition_(Vector3::ZERO),
  14. targetRotation_(Quaternion::IDENTITY),
  15. smoothingMask_(SMOOTH_NONE),
  16. subscribed_(false)
  17. {
  18. }
  19. SmoothedTransform::~SmoothedTransform() = default;
  20. void SmoothedTransform::RegisterObject(Context* context)
  21. {
  22. context->RegisterFactory<SmoothedTransform>();
  23. }
  24. void SmoothedTransform::Update(float constant, float squaredSnapThreshold)
  25. {
  26. if (smoothingMask_ && node_)
  27. {
  28. Vector3 position = node_->GetPosition();
  29. Quaternion rotation = node_->GetRotation();
  30. if (smoothingMask_ & SMOOTH_POSITION)
  31. {
  32. // If position snaps, snap everything to the end
  33. float delta = (position - targetPosition_).LengthSquared();
  34. if (delta > squaredSnapThreshold)
  35. constant = 1.0f;
  36. if (delta < M_EPSILON || constant >= 1.0f)
  37. {
  38. position = targetPosition_;
  39. smoothingMask_ &= ~SMOOTH_POSITION;
  40. }
  41. else
  42. position = position.Lerp(targetPosition_, constant);
  43. node_->SetPosition(position);
  44. }
  45. if (smoothingMask_ & SMOOTH_ROTATION)
  46. {
  47. float delta = (rotation - targetRotation_).LengthSquared();
  48. if (delta < M_EPSILON || constant >= 1.0f)
  49. {
  50. rotation = targetRotation_;
  51. smoothingMask_ &= ~SMOOTH_ROTATION;
  52. }
  53. else
  54. rotation = rotation.Slerp(targetRotation_, constant);
  55. node_->SetRotation(rotation);
  56. }
  57. }
  58. // If smoothing has completed, unsubscribe from the update event
  59. if (!smoothingMask_)
  60. {
  61. UnsubscribeFromEvent(GetScene(), E_UPDATESMOOTHING);
  62. subscribed_ = false;
  63. }
  64. }
  65. void SmoothedTransform::SetTargetPosition(const Vector3& position)
  66. {
  67. targetPosition_ = position;
  68. smoothingMask_ |= SMOOTH_POSITION;
  69. // Subscribe to smoothing update if not yet subscribed
  70. if (!subscribed_)
  71. {
  72. SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, URHO3D_HANDLER(SmoothedTransform, HandleUpdateSmoothing));
  73. subscribed_ = true;
  74. }
  75. SendEvent(E_TARGETPOSITION);
  76. }
  77. void SmoothedTransform::SetTargetRotation(const Quaternion& rotation)
  78. {
  79. targetRotation_ = rotation;
  80. smoothingMask_ |= SMOOTH_ROTATION;
  81. if (!subscribed_)
  82. {
  83. SubscribeToEvent(GetScene(), E_UPDATESMOOTHING, URHO3D_HANDLER(SmoothedTransform, HandleUpdateSmoothing));
  84. subscribed_ = true;
  85. }
  86. SendEvent(E_TARGETROTATION);
  87. }
  88. void SmoothedTransform::SetTargetWorldPosition(const Vector3& position)
  89. {
  90. if (node_ && node_->GetParent())
  91. SetTargetPosition(node_->GetParent()->GetWorldTransform().Inverse() * position);
  92. else
  93. SetTargetPosition(position);
  94. }
  95. void SmoothedTransform::SetTargetWorldRotation(const Quaternion& rotation)
  96. {
  97. if (node_ && node_->GetParent())
  98. SetTargetRotation(node_->GetParent()->GetWorldRotation().Inverse() * rotation);
  99. else
  100. SetTargetRotation(rotation);
  101. }
  102. Vector3 SmoothedTransform::GetTargetWorldPosition() const
  103. {
  104. if (node_ && node_->GetParent())
  105. return node_->GetParent()->GetWorldTransform() * targetPosition_;
  106. else
  107. return targetPosition_;
  108. }
  109. Quaternion SmoothedTransform::GetTargetWorldRotation() const
  110. {
  111. if (node_ && node_->GetParent())
  112. return node_->GetParent()->GetWorldRotation() * targetRotation_;
  113. else
  114. return targetRotation_;
  115. }
  116. void SmoothedTransform::OnNodeSet(Node* node)
  117. {
  118. if (node)
  119. {
  120. // Copy initial target transform
  121. targetPosition_ = node->GetPosition();
  122. targetRotation_ = node->GetRotation();
  123. }
  124. }
  125. void SmoothedTransform::HandleUpdateSmoothing(StringHash eventType, VariantMap& eventData)
  126. {
  127. using namespace UpdateSmoothing;
  128. float constant = eventData[P_CONSTANT].GetFloat();
  129. float squaredSnapThreshold = eventData[P_SQUAREDSNAPTHRESHOLD].GetFloat();
  130. Update(constant, squaredSnapThreshold);
  131. }
  132. }