AudioMultiPositionComponent.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 "AudioMultiPositionComponent.h"
  9. #include <AzCore/Component/TransformBus.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <LmbrCentral/Audio/AudioProxyComponentBus.h>
  13. namespace LmbrCentral
  14. {
  15. //=========================================================================
  16. void AudioMultiPositionComponent::Reflect(AZ::ReflectContext* context)
  17. {
  18. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  19. {
  20. serializeContext->Class<AudioMultiPositionComponent, AZ::Component>()
  21. ->Version(0)
  22. ->Field("Entity Refs", &AudioMultiPositionComponent::m_entityRefs)
  23. ->Field("Behavior Type", &AudioMultiPositionComponent::m_behaviorType)
  24. ;
  25. }
  26. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  27. {
  28. behaviorContext->Enum<static_cast<AZ::u32>(Audio::MultiPositionBehaviorType::Separate)>("MultiPositionBehaviorType_Separate")
  29. ->Enum<static_cast<AZ::u32>(Audio::MultiPositionBehaviorType::Blended)>("MultiPositionBehaviorType_Blended")
  30. ;
  31. behaviorContext->EBus<AudioMultiPositionComponentRequestBus>("Multi-Position Audio Requests", "AudioMultiPositionComponentRequestBus")
  32. ->Attribute(AZ::Script::Attributes::Category, "Audio")
  33. ->Event("Add Entity", &AudioMultiPositionComponentRequestBus::Events::AddEntity, "AddEntity")
  34. ->Event("RemoveEntity", &AudioMultiPositionComponentRequestBus::Events::RemoveEntity)
  35. ->Event("SetBehaviorType", &AudioMultiPositionComponentRequestBus::Events::SetBehaviorType)
  36. ;
  37. }
  38. }
  39. //=========================================================================
  40. AudioMultiPositionComponent::AudioMultiPositionComponent(const AZStd::vector<AZ::EntityId>& entities, Audio::MultiPositionBehaviorType type)
  41. : m_behaviorType(type)
  42. {
  43. // Remove duplicates when building the game entity.
  44. AZStd::unordered_set<AZ::EntityId> setOfEntities(entities.begin(), entities.end());
  45. m_entityRefs.assign(setOfEntities.begin(), setOfEntities.end());
  46. m_entityPositions.reserve(m_entityRefs.size());
  47. }
  48. //=========================================================================
  49. void AudioMultiPositionComponent::Activate()
  50. {
  51. for (const auto& entityId : m_entityRefs)
  52. {
  53. AZ::EntityBus::MultiHandler::BusConnect(entityId);
  54. }
  55. AudioMultiPositionComponentRequestBus::Handler::BusConnect(GetEntityId());
  56. }
  57. //=========================================================================
  58. void AudioMultiPositionComponent::Deactivate()
  59. {
  60. AudioMultiPositionComponentRequestBus::Handler::BusDisconnect();
  61. AZ::EntityBus::MultiHandler::BusDisconnect();
  62. }
  63. //=========================================================================
  64. void AudioMultiPositionComponent::SetBehaviorType(Audio::MultiPositionBehaviorType type)
  65. {
  66. if (m_behaviorType != type)
  67. {
  68. m_behaviorType = type;
  69. // Re-send if all entities are activated...
  70. if (m_entityPositions.size() == m_entityRefs.size())
  71. {
  72. SendMultiplePositions();
  73. }
  74. }
  75. }
  76. //=========================================================================
  77. void AudioMultiPositionComponent::AddEntity(const AZ::EntityId& entityId)
  78. {
  79. auto iter = AZStd::find(m_entityRefs.begin(), m_entityRefs.end(), entityId);
  80. if (iter == m_entityRefs.end())
  81. {
  82. m_entityRefs.push_back(entityId);
  83. AZ::EntityBus::MultiHandler::BusConnect(entityId);
  84. }
  85. }
  86. //=========================================================================
  87. void AudioMultiPositionComponent::RemoveEntity(const AZ::EntityId& entityId)
  88. {
  89. auto iter = AZStd::find(m_entityRefs.begin(), m_entityRefs.end(), entityId);
  90. if (iter != m_entityRefs.end())
  91. {
  92. m_entityRefs.erase(iter);
  93. AZ::EntityBus::MultiHandler::BusDisconnect(entityId);
  94. }
  95. }
  96. //=========================================================================
  97. void AudioMultiPositionComponent::OnEntityActivated(const AZ::EntityId& entityId)
  98. {
  99. AZ_Assert(m_entityPositions.size() < m_entityRefs.size(), "Multi-Position Audio: Seen more entities activated than entities being tracked.\n");
  100. AZ::Vector3 position;
  101. AZ::TransformBus::EventResult(position, entityId, &AZ::TransformBus::Events::GetWorldTranslation);
  102. m_entityPositions.push_back(AZStd::make_pair(entityId, position));
  103. if (m_entityPositions.size() == m_entityRefs.size())
  104. {
  105. SendMultiplePositions();
  106. }
  107. }
  108. //=========================================================================
  109. void AudioMultiPositionComponent::OnEntityDeactivated(const AZ::EntityId& entityId)
  110. {
  111. auto iter = AZStd::find_if(m_entityPositions.begin(), m_entityPositions.end(),
  112. [&entityId](const auto& entityPositionPair) -> bool
  113. {
  114. return entityPositionPair.first == entityId;
  115. }
  116. );
  117. if (iter != m_entityPositions.end())
  118. {
  119. m_entityPositions.erase(iter);
  120. }
  121. }
  122. //=========================================================================
  123. void AudioMultiPositionComponent::SendMultiplePositions()
  124. {
  125. // Sends the vector of positions out to be processed.
  126. Audio::MultiPositionParams params;
  127. params.m_type = m_behaviorType;
  128. for (const auto& entityPosPair : m_entityPositions)
  129. {
  130. params.m_positions.emplace_back(entityPosPair.second);
  131. }
  132. AudioProxyComponentRequestBus::Event(GetEntityId(), &AudioProxyComponentRequestBus::Events::SetMultiplePositions, params);
  133. }
  134. } // namespace LmbrCentral