ProximitySensor.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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
  4. * of this distribution.
  5. *
  6. * SPDX-License-Identifier: Apache-2.0 OR MIT
  7. *
  8. */
  9. #include "ProximitySensor.h"
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <AzCore/Math/Transform.h>
  12. #include <AzCore/Serialization/EditContext.h>
  13. #include <AzCore/Serialization/EditContextConstants.inl>
  14. #include <AzCore/std/string/string.h>
  15. #include <WarehouseAutomation/ProximitySensor/ProximitySensorNotificationBus.h>
  16. #include <WarehouseAutomation/ProximitySensor/ProximitySensorNotificationBusHandler.h>
  17. #include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
  18. #include <Atom/RPI.Public/Scene.h>
  19. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  20. #include <AzFramework/Physics/Common/PhysicsTypes.h>
  21. #include <AzFramework/Physics/PhysicsScene.h>
  22. namespace WarehouseAutomation
  23. {
  24. void ProximitySensor::Reflect(AZ::ReflectContext* context)
  25. {
  26. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  27. {
  28. serialize->Class<ProximitySensor, AZ::Component>()
  29. ->Version(1)
  30. ->Field("visualize", &ProximitySensor::m_visualize)
  31. ->Field("frequency", &ProximitySensor::m_frequency)
  32. ->Field("detectionDistance", &ProximitySensor::m_detectionDistance);
  33. if (AZ::EditContext* editContext = serialize->GetEditContext())
  34. {
  35. editContext->Class<ProximitySensor>("Proximity Sensor", "Proximity object detection component")
  36. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  37. ->Attribute(AZ::Edit::Attributes::Category, "WarehouseAutomation")
  38. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
  39. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/ProximitySensor.svg")
  40. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/ProximitySensor.svg")
  41. ->DataElement(
  42. AZ::Edit::UIHandlers::Default, &ProximitySensor::m_visualize, "Visualize", "Whether the detection beam is shown")
  43. ->DataElement(AZ::Edit::UIHandlers::Default, &ProximitySensor::m_frequency, "Frequency", "Detection frequency")
  44. ->DataElement(
  45. AZ::Edit::UIHandlers::Default,
  46. &ProximitySensor::m_detectionDistance,
  47. "Detection distance",
  48. "The maximum distance from where object is detected")
  49. ->Attribute(AZ::Edit::Attributes::Min, 0.f);
  50. }
  51. }
  52. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  53. {
  54. behaviorContext->EBus<ProximitySensorNotificationBus>("ProximitySensor", "ProximitySensorNotificationBus")
  55. ->Attribute(AZ::Edit::Attributes::Category, "WarehouseAutomation/ProximitySensor")
  56. ->Handler<ProximitySensorNotificationBusHandler>();
  57. }
  58. }
  59. ProximitySensor::ProximitySensor()
  60. {
  61. }
  62. void ProximitySensor::Activate()
  63. {
  64. if (m_visualize)
  65. {
  66. auto* entityScene = AZ::RPI::Scene::GetSceneForEntityId(GetEntityId());
  67. m_drawQueue = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(entityScene);
  68. }
  69. AZ::Transform entityTransform;
  70. AZ::TransformBus::EventResult(entityTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  71. m_detectionDirection = entityTransform.TransformVector(AZ::Vector3::CreateAxisX());
  72. m_detectionDirection.Normalize();
  73. AZ::TickBus::Handler::BusConnect();
  74. }
  75. void ProximitySensor::Deactivate()
  76. {
  77. AZ::TickBus::Handler::BusDisconnect();
  78. }
  79. void ProximitySensor::Visualize()
  80. {
  81. if (m_drawQueue)
  82. {
  83. AZStd::vector<AZ::Vector3> linePoints;
  84. AZ::Vector3 entityTranslation;
  85. AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
  86. AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs;
  87. linePoints.push_back(entityTranslation);
  88. if (m_position)
  89. {
  90. drawArgs.m_colors = &AZ::Colors::Green;
  91. linePoints.push_back(m_position.value());
  92. }
  93. else
  94. {
  95. drawArgs.m_colors = &AZ::Colors::Red;
  96. linePoints.push_back(entityTranslation + m_detectionDirection * m_detectionDistance);
  97. }
  98. const uint8_t pixelSize = 5;
  99. drawArgs.m_verts = linePoints.data();
  100. drawArgs.m_vertCount = linePoints.size();
  101. drawArgs.m_colorCount = 1;
  102. drawArgs.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque;
  103. drawArgs.m_size = pixelSize;
  104. m_drawQueue->DrawLines(drawArgs);
  105. }
  106. }
  107. void ProximitySensor::OnTick(float deltaTime, AZ::ScriptTimePoint time)
  108. {
  109. if (m_visualize)
  110. {
  111. Visualize();
  112. }
  113. AZ_Assert(m_frequency > 0.f, "ProximitySensor frequency must be greater than zero");
  114. auto frameTime = 1.f / m_frequency;
  115. m_timeElapsedSinceLastTick += deltaTime;
  116. if (m_timeElapsedSinceLastTick < frameTime)
  117. {
  118. return;
  119. }
  120. m_timeElapsedSinceLastTick -= frameTime;
  121. if (deltaTime > frameTime)
  122. { // Frequency higher than possible, not catching
  123. // up, just keep going with each frame.
  124. m_timeElapsedSinceLastTick = 0.0f;
  125. }
  126. DetectionCheck();
  127. }
  128. void ProximitySensor::DetectionCheck()
  129. {
  130. auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
  131. AZ::Vector3 entityTranslation;
  132. AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
  133. AzPhysics::RayCastRequest request;
  134. request.m_start = entityTranslation;
  135. request.m_direction = m_detectionDirection;
  136. request.m_distance = m_detectionDistance;
  137. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  138. sceneHandle != AzPhysics::InvalidSceneHandle)
  139. {
  140. AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &request);
  141. m_position = !result.m_hits.empty() ? std::make_optional(result.m_hits.front().m_position) : std::nullopt;
  142. if (m_position)
  143. {
  144. ProximitySensorNotificationBus::Event(GetEntityId(), &ProximitySensorNotifications::OnObjectInRange);
  145. }
  146. else
  147. {
  148. ProximitySensorNotificationBus::Event(GetEntityId(), &ProximitySensorNotifications::OnObjectOutOfRange);
  149. }
  150. }
  151. }
  152. } // namespace WarehouseAutomation