AkLateReverbComponent.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. /*=============================================================================
  16. AkLateReverbComponent.cpp:
  17. =============================================================================*/
  18. #include "AkLateReverbComponent.h"
  19. #include "AkCustomVersion.h"
  20. #include "AkSettingsPerUser.h"
  21. #include "AkComponentHelpers.h"
  22. #include "AkAudioDevice.h"
  23. #include "AkAuxBus.h"
  24. #include "AkRoomComponent.h"
  25. #include "AkSurfaceReflectorSetComponent.h"
  26. #include "AkGeometryComponent.h"
  27. #include "AkAcousticTextureSetComponent.h"
  28. #include "Components/BrushComponent.h"
  29. #include "Model.h"
  30. #include "GameFramework/Volume.h"
  31. #include "Engine/Canvas.h"
  32. #include "CanvasItem.h"
  33. #if WITH_EDITOR
  34. #include "Editor.h"
  35. #include "LevelEditorViewport.h"
  36. #include "AkAudioStyle.h"
  37. #include "AkSpatialAudioHelper.h"
  38. #endif
  39. /*------------------------------------------------------------------------------------
  40. UAkLateReverbComponent
  41. ------------------------------------------------------------------------------------*/
  42. #if WITH_EDITOR
  43. float UAkLateReverbComponent::TextVisualizerHeightOffset = 80.0f;
  44. #endif
  45. UAkLateReverbComponent::UAkLateReverbComponent(const class FObjectInitializer& ObjectInitializer) :
  46. Super(ObjectInitializer)
  47. {
  48. Parent = TWeakObjectPtr<UPrimitiveComponent>();
  49. bUseAttachParentBound = true;
  50. // Property initialization
  51. SendLevel = 1.0f;
  52. FadeRate = 0.5f;
  53. Priority = 1.0f;
  54. bEnable = true;
  55. bWantsOnUpdateTransform = true;
  56. #if WITH_EDITOR
  57. if (AkSpatialAudioHelper::GetObjectReplacedEvent())
  58. {
  59. AkSpatialAudioHelper::GetObjectReplacedEvent()->AddUObject(this, &UAkLateReverbComponent::HandleObjectsReplaced);
  60. }
  61. #endif
  62. }
  63. void UAkLateReverbComponent::PostLoad()
  64. {
  65. Super::PostLoad();
  66. const int32 AkVersion = GetLinkerCustomVersion(FAkCustomVersion::GUID);
  67. if (AkVersion < FAkCustomVersion::ReverbAuxBusAutoAssignment)
  68. {
  69. AutoAssignAuxBus = false;
  70. AuxBusManual = AuxBus;
  71. }
  72. #if WITH_EDITOR
  73. RegisterReverbInfoEnabledCallback();
  74. #endif
  75. }
  76. void UAkLateReverbComponent::Serialize(FArchive& Ar)
  77. {
  78. Ar.UsingCustomVersion(FAkCustomVersion::GUID);
  79. Super::Serialize(Ar);
  80. }
  81. bool UAkLateReverbComponent::HasEffectOnLocation(const FVector& Location) const
  82. {
  83. // Need to add a small radius, because on the Mac, EncompassesPoint returns false if
  84. // Location is exactly equal to the Volume's location
  85. static float RADIUS = 0.01f;
  86. return LateReverbIsActive() && EncompassesPoint(Location, RADIUS);
  87. }
  88. uint32 UAkLateReverbComponent::GetAuxBusId() const
  89. {
  90. return FAkAudioDevice::GetShortID(AuxBus, AuxBusName);
  91. }
  92. void UAkLateReverbComponent::InitializeParent()
  93. {
  94. USceneComponent* SceneParent = GetAttachParent();
  95. if (SceneParent != nullptr)
  96. {
  97. ReverbDescriptor.SetPrimitive(Cast<UPrimitiveComponent>(SceneParent));
  98. Parent = Cast<UPrimitiveComponent>(SceneParent);
  99. if (Parent.IsValid())
  100. {
  101. ReverbDescriptor.SetReverbComponent(this);
  102. RecalculateDecay();
  103. RecalculatePredelay();
  104. UBodySetup* bodySetup = Parent->GetBodySetup();
  105. if (bodySetup == nullptr || !AkComponentHelpers::HasSimpleCollisionGeometry(bodySetup))
  106. {
  107. if (UBrushComponent* brush = Cast<UBrushComponent>(Parent.Get()))
  108. brush->BuildSimpleBrushCollision();
  109. else
  110. AkComponentHelpers::LogSimpleGeometryWarning(Parent.Get(), this);
  111. }
  112. }
  113. else
  114. {
  115. bEnable = false;
  116. AkComponentHelpers::LogAttachmentError(this, SceneParent, "UPrimitiveComponent");
  117. return;
  118. }
  119. }
  120. else // will happen when this component gets detached from its parent
  121. {
  122. Parent = TWeakObjectPtr<UPrimitiveComponent>();
  123. ReverbDescriptor.SetPrimitive(nullptr);
  124. bEnable = false;
  125. }
  126. }
  127. void UAkLateReverbComponent::BeginPlay()
  128. {
  129. Super::BeginPlay();
  130. DecayEstimationNeedsUpdate = true;
  131. PredelayEstimationNeedsUpdate = true;
  132. UAkRoomComponent* pRoomCmpt = nullptr;
  133. if (Parent.IsValid())
  134. {
  135. pRoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent.Get());
  136. }
  137. if (!pRoomCmpt || !pRoomCmpt->RoomIsActive())
  138. {
  139. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  140. if (AkAudioDevice && LateReverbIsActive())
  141. {
  142. AkAudioDevice->IndexLateReverb(this);
  143. }
  144. }
  145. }
  146. void UAkLateReverbComponent::BeginDestroy()
  147. {
  148. Super::BeginDestroy();
  149. if (TextureSetComponent != nullptr)
  150. {
  151. TextureSetComponent->SetReverbDescriptor(nullptr);
  152. }
  153. ReverbDescriptor.SetPrimitive(nullptr);
  154. #if WITH_EDITOR
  155. if (AkSpatialAudioHelper::GetObjectReplacedEvent())
  156. {
  157. AkSpatialAudioHelper::GetObjectReplacedEvent()->RemoveAll(this);
  158. }
  159. #endif
  160. }
  161. void UAkLateReverbComponent::OnRegister()
  162. {
  163. Super::OnRegister();
  164. SetRelativeTransform(FTransform::Identity);
  165. InitializeParent();
  166. ParentChanged();
  167. // During runtime (non editor), we only want to tick if we'll ever need to update the reverb parameters.
  168. PrimaryComponentTick.bCanEverTick = ReverbDescriptor.RequiresUpdates();
  169. PrimaryComponentTick.bStartWithTickEnabled = ReverbDescriptor.RequiresUpdates();
  170. #if WITH_EDITOR
  171. // In editor builds we always want to tick in case the global RTPCs become active, or aux bus assignment is enabled.
  172. bTickInEditor = true;
  173. PrimaryComponentTick.bCanEverTick = true;
  174. PrimaryComponentTick.bStartWithTickEnabled = true;
  175. #endif
  176. }
  177. void UAkLateReverbComponent::ParentChanged()
  178. {
  179. if (Parent.IsValid())
  180. {
  181. #if WITH_EDITOR
  182. RegisterReverbAssignmentChangedCallback();
  183. RegisterGlobalDecayAbsorptionChangedCallback();
  184. RegisterReverbRTPCChangedCallback();
  185. #endif
  186. // In the case where a blueprint class has a texture set component and a late reverb component as siblings, We can't know which will be registered first.
  187. // We need to check for the sibling in each OnRegister function and associate the texture set component to the late reverb when they are both registered.
  188. if (UAkSurfaceReflectorSetComponent* surfaceComponent = AkComponentHelpers::GetChildComponentOfType<UAkSurfaceReflectorSetComponent>(*Parent.Get()))
  189. {
  190. AssociateAkTextureSetComponent(surfaceComponent);
  191. }
  192. else if (UAkGeometryComponent* geometryComponent = AkComponentHelpers::GetChildComponentOfType<UAkGeometryComponent>(*Parent.Get()))
  193. {
  194. AssociateAkTextureSetComponent(geometryComponent);
  195. }
  196. }
  197. }
  198. void UAkLateReverbComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
  199. {
  200. Super::EndPlay(EndPlayReason);
  201. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  202. if (AkAudioDevice && IsIndexed)
  203. {
  204. AkAudioDevice->UnindexLateReverb(this);
  205. }
  206. }
  207. void UAkLateReverbComponent::OnUnregister()
  208. {
  209. Super::OnUnregister();
  210. #if WITH_EDITOR
  211. auto* World = GetWorld();
  212. if(World && World->IsPlayInEditor())
  213. {
  214. DestroyTextVisualizers();
  215. }
  216. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  217. if (AkSettings != nullptr)
  218. {
  219. if (ReverbAssignmentChangedHandle.IsValid())
  220. {
  221. AkSettings->OnReverbAssignmentChanged.Remove(ReverbAssignmentChangedHandle);
  222. }
  223. if (GlobalDecayAbsorptionChangedHandle.IsValid())
  224. {
  225. AkSettings->OnGlobalDecayAbsorptionChanged.Remove(GlobalDecayAbsorptionChangedHandle);
  226. }
  227. if (RTPCChangedHandle.IsValid())
  228. {
  229. AkSettings->OnReverbRTPCChanged.Remove(RTPCChangedHandle);
  230. }
  231. }
  232. #endif
  233. }
  234. bool UAkLateReverbComponent::MoveComponentImpl(
  235. const FVector & Delta,
  236. const FQuat & NewRotation,
  237. bool bSweep,
  238. FHitResult * Hit,
  239. EMoveComponentFlags MoveFlags,
  240. ETeleportType Teleport)
  241. {
  242. if (AkComponentHelpers::DoesMovementRecenterChild(this, Parent.Get(), Delta))
  243. Super::MoveComponentImpl(Delta, NewRotation, bSweep, Hit, MoveFlags, Teleport);
  244. return false;
  245. }
  246. void UAkLateReverbComponent::OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport)
  247. {
  248. DecayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimateDecay();
  249. PredelayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimatePredelay();
  250. if (IsIndexed)
  251. {
  252. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  253. if (AkAudioDevice)
  254. AkAudioDevice->ReindexLateReverb(this);
  255. }
  256. #if WITH_EDITOR
  257. if (TextVisualizerLabels != nullptr)
  258. {
  259. TextVisualizerLabels->SetWorldScale3D(FVector::OneVector);
  260. if (Parent.IsValid())
  261. {
  262. TextVisualizerLabels->SetWorldLocation(GetTextVisualizersLocation());
  263. }
  264. }
  265. if (TextVisualizerValues != nullptr)
  266. {
  267. TextVisualizerValues->SetWorldScale3D(FVector::OneVector);
  268. if (Parent.IsValid())
  269. {
  270. TextVisualizerValues->SetWorldLocation(GetTextVisualizersLocation());
  271. }
  272. }
  273. #endif
  274. }
  275. void UAkLateReverbComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
  276. {
  277. Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
  278. // Update decay and time to first reflection estimations when the size is changed, every PARAM_ESTIMATION_UPDATE_PERIOD seconds.
  279. if (SecondsSinceDecayUpdate < PARAM_ESTIMATION_UPDATE_PERIOD)
  280. {
  281. SecondsSinceDecayUpdate += DeltaTime;
  282. }
  283. if ((TextureSetHasChanged || DecayEstimationNeedsUpdate) && SecondsSinceDecayUpdate >= PARAM_ESTIMATION_UPDATE_PERIOD)
  284. {
  285. RecalculateDecay();
  286. DecayEstimationNeedsUpdate = false;
  287. TextureSetHasChanged = false;
  288. }
  289. if (SecondsSincePredelayUpdate < PARAM_ESTIMATION_UPDATE_PERIOD)
  290. {
  291. SecondsSincePredelayUpdate += DeltaTime;
  292. }
  293. if (PredelayEstimationNeedsUpdate && SecondsSincePredelayUpdate >= PARAM_ESTIMATION_UPDATE_PERIOD)
  294. {
  295. RecalculatePredelay();
  296. PredelayEstimationNeedsUpdate = false;
  297. }
  298. if (ReverbAssignmentNeedsUpdate)
  299. {
  300. UpdateDecayEstimation(ReverbDescriptor.T60Decay, ReverbDescriptor.PrimitiveVolume, ReverbDescriptor.PrimitiveSurfaceArea);
  301. ReverbAssignmentNeedsUpdate = false;
  302. }
  303. if (ReverbParamsChanged)
  304. {
  305. OnReverbParamsChanged();
  306. ReverbParamsChanged = false;
  307. }
  308. #if WITH_EDITOR
  309. UWorld* World = GetWorld();
  310. if (World == nullptr)
  311. return;
  312. if (GCurrentLevelEditingViewportClient != nullptr && World->WorldType == EWorldType::Editor)
  313. {
  314. // Keep the text renderers pointing to the camera.
  315. if (IsValid(TextVisualizerLabels))
  316. {
  317. FVector PointTo = GCurrentLevelEditingViewportClient->GetViewLocation() - TextVisualizerLabels->GetComponentLocation();
  318. TextVisualizerLabels->SetWorldRotation(PointTo.Rotation());
  319. }
  320. if (IsValid(TextVisualizerValues))
  321. {
  322. FVector PointTo = GCurrentLevelEditingViewportClient->GetViewLocation() - TextVisualizerValues->GetComponentLocation();
  323. TextVisualizerValues->SetWorldRotation(PointTo.Rotation());
  324. }
  325. }
  326. if (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::PIE)
  327. {
  328. // Only show the text renderer for selected actors.
  329. if (GetOwner()->IsSelected() && !WasSelected)
  330. {
  331. WasSelected = true;
  332. UpdateValuesLabels();
  333. }
  334. if (!GetOwner()->IsSelected() && WasSelected)
  335. {
  336. WasSelected = false;
  337. UpdateValuesLabels();
  338. }
  339. }
  340. if (bTextStatusNeedsUpdate)
  341. {
  342. UpdateTextVisualizerStatus();
  343. bTextStatusNeedsUpdate = false;
  344. }
  345. #endif
  346. }
  347. void UAkLateReverbComponent::RecalculateDecay()
  348. {
  349. if (ReverbDescriptor.ShouldEstimateDecay())
  350. {
  351. ReverbDescriptor.CalculateT60(this);
  352. SecondsSinceDecayUpdate = 0.0f;
  353. }
  354. }
  355. void UAkLateReverbComponent::RecalculatePredelay()
  356. {
  357. if (ReverbDescriptor.ShouldEstimatePredelay())
  358. {
  359. ReverbDescriptor.CalculateTimeToFirstReflection();
  360. SecondsSincePredelayUpdate = 0.0f;
  361. }
  362. }
  363. void UAkLateReverbComponent::TextureSetUpdated()
  364. {
  365. TextureSetHasChanged = true;
  366. }
  367. #if WITH_EDITOR
  368. void UAkLateReverbComponent::RegisterReverbInfoEnabledCallback()
  369. {
  370. UAkSettingsPerUser* AkSettingsPerUser = GetMutableDefault<UAkSettingsPerUser>();
  371. if (AkSettingsPerUser == nullptr || ShowReverbInfoChangedHandle.IsValid())
  372. return;
  373. ShowReverbInfoChangedHandle = AkSettingsPerUser->OnShowReverbInfoChanged.AddLambda([this, AkSettingsPerUser]()
  374. {
  375. bTextStatusNeedsUpdate = true;
  376. });
  377. }
  378. void UAkLateReverbComponent::OnComponentDestroyed(bool bDestroyingHierarchy)
  379. {
  380. UAkSettingsPerUser* AkSettingsPerUser = GetMutableDefault<UAkSettingsPerUser>();
  381. if (!AkSettingsPerUser)
  382. return;
  383. AkSettingsPerUser->OnShowRoomsPortalsChanged.Remove(ShowReverbInfoChangedHandle);
  384. ShowReverbInfoChangedHandle.Reset();
  385. }
  386. void UAkLateReverbComponent::InitializeComponent()
  387. {
  388. Super::InitializeComponent();
  389. RegisterReverbInfoEnabledCallback();
  390. }
  391. void UAkLateReverbComponent::OnComponentCreated()
  392. {
  393. Super::OnComponentCreated();
  394. RegisterReverbInfoEnabledCallback();
  395. }
  396. void UAkLateReverbComponent::HandleObjectsReplaced(const TMap<UObject*, UObject*>& ReplacementMap)
  397. {
  398. if (ReplacementMap.Contains(Parent.Get()))
  399. {
  400. InitializeParent();
  401. DecayEstimationNeedsUpdate = true;
  402. PredelayEstimationNeedsUpdate = true;
  403. }
  404. if (ReplacementMap.Contains(TextureSetComponent))
  405. {
  406. if (Parent.IsValid())
  407. {
  408. if (UAkSurfaceReflectorSetComponent* SurfaceComponent = AkComponentHelpers::GetChildComponentOfType<UAkSurfaceReflectorSetComponent>(*Parent.Get()))
  409. {
  410. AssociateAkTextureSetComponent(SurfaceComponent);
  411. }
  412. else if (UAkGeometryComponent* GeomComponent = AkComponentHelpers::GetChildComponentOfType<UAkGeometryComponent>(*Parent.Get()))
  413. {
  414. AssociateAkTextureSetComponent(GeomComponent);
  415. }
  416. }
  417. }
  418. }
  419. void UAkLateReverbComponent::UpdateTextVisualizerStatus()
  420. {
  421. bool bShowReverbInfo = GetDefault<UAkSettingsPerUser>()->bShowReverbInfo;
  422. // The reverb descriptor may or may not require updates depending on which global RTPCs are in use, and whether auto assign aux bus is selected.
  423. // We only want to show the text renderers when the reverb parameter estimation is in use.
  424. if ((!bShowReverbInfo || !ReverbDescriptor.RequiresUpdates()) && TextVisualizersInitialized())
  425. {
  426. DestroyTextVisualizers();
  427. }
  428. else if ((bShowReverbInfo && ReverbDescriptor.RequiresUpdates()) && !TextVisualizersInitialized())
  429. {
  430. InitTextVisualizers();
  431. DecayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimateDecay();
  432. PredelayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimatePredelay();
  433. }
  434. }
  435. bool UAkLateReverbComponent::TextVisualizersInitialized() const
  436. {
  437. return IsValid(TextVisualizerLabels) && IsValid(TextVisualizerValues);
  438. }
  439. FText UAkLateReverbComponent::GetValuesLabels() const
  440. {
  441. // Get a nicely formatted string showing the values of all of the reverb properties in a left-aligned block.
  442. // They will appear adjacent to a right-aligned block showing the property labels.
  443. FString BusName = FString("NONE");
  444. if (AuxBus != nullptr)
  445. AuxBus->GetName(BusName);
  446. FNumberFormattingOptions NumberFormat;
  447. NumberFormat.MaximumFractionalDigits = 2;
  448. FString volumeString = FText::AsNumber(EnvironmentVolume, &NumberFormat).ToString();
  449. FString areaString = FText::AsNumber(SurfaceArea, &NumberFormat).ToString();
  450. const FString missingRoomString = FString("Requires sibling AkRoom component");
  451. FString decayString = missingRoomString;
  452. FString reflectionTimeString = missingRoomString;
  453. FString dampingString = missingRoomString;
  454. if (AutoAssignAuxBus)
  455. {
  456. decayString = FText::AsNumber(EnvironmentDecayEstimate, &NumberFormat).ToString() + " seconds";
  457. }
  458. if (Parent.IsValid() && AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent.Get()))
  459. {
  460. decayString = ReverbDescriptor.ShouldEstimateDecay() ? FText::AsNumber(EnvironmentDecayEstimate, &NumberFormat).ToString() + " seconds" : FString("Invalid Late Reverb or Room Primitive Component");
  461. reflectionTimeString = FString("Invalid Late Reverb or Room Primitive Component");
  462. if (ReverbDescriptor.ShouldEstimatePredelay())
  463. {
  464. reflectionTimeString = FText::AsNumber(TimeToFirstReflection, &NumberFormat).ToString() + " ms";
  465. if (TimeToFirstReflection > 100.0f)
  466. {
  467. reflectionTimeString = FText::AsNumber(TimeToFirstReflection / 1000.0f, &NumberFormat).ToString() + " s";
  468. }
  469. }
  470. dampingString = "No associated geometry component.";
  471. if (TextureSetComponent != nullptr)
  472. {
  473. dampingString = ReverbDescriptor.ShouldEstimateDamping() ? FText::AsNumber(HFDamping, &NumberFormat).ToString() : FString("Invalid Late Reverb or Room Primitive Component");
  474. }
  475. }
  476. const UAkSettings* AkSettings = GetDefault<UAkSettings>();
  477. if (AkSettings != nullptr)
  478. {
  479. if (!AkSettings->DecayRTPCInUse())
  480. {
  481. decayString += FString(" (RTPC not in use)");
  482. }
  483. if (!AkSettings->PredelayRTPCInUse())
  484. {
  485. reflectionTimeString += FString(" (RTPC not in use)");
  486. }
  487. if (!AkSettings->DampingRTPCInUse())
  488. {
  489. dampingString += FString(" (RTPC not in use)");
  490. }
  491. }
  492. return FText::FromString(FString::Format(TEXT("{1} cubic meters{0}{2} square meters{0}{3}{0}{4}{0}{5}{0}{6}"),
  493. { LINE_TERMINATOR, volumeString, areaString, decayString, BusName, reflectionTimeString, dampingString }));
  494. }
  495. void UAkLateReverbComponent::InitTextVisualizers()
  496. {
  497. if (!HasAnyFlags(RF_Transient) && bEnable)
  498. {
  499. if (ReverbDescriptor.RequiresUpdates())
  500. {
  501. FString OwnerName;
  502. #if WITH_EDITOR
  503. OwnerName = GetOwner()->GetActorLabel();
  504. #else
  505. OwnerName = GetOwner()->GetName();
  506. #endif
  507. FString TextVizName = OwnerName + GetName();
  508. UMaterialInterface* mat = Cast<UMaterialInterface>(FAkAudioStyle::GetAkForegroundTextMaterial());
  509. if (!IsValid(TextVisualizerLabels))
  510. {
  511. TextVisualizerLabels = NewObject<UTextRenderComponent>(GetOuter(), *(TextVizName + TEXT("TextLabels")));
  512. if (IsValid(TextVisualizerLabels))
  513. {
  514. if (mat != nullptr)
  515. TextVisualizerLabels->SetTextMaterial(mat);
  516. TextVisualizerLabels->SetHorizontalAlignment(EHorizTextAligment::EHTA_Right);
  517. TextVisualizerLabels->RegisterComponentWithWorld(GetWorld());
  518. TextVisualizerLabels->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
  519. TextVisualizerLabels->ResetRelativeTransform();
  520. TextVisualizerLabels->SetWorldScale3D(FVector::OneVector);
  521. if (Parent.IsValid())
  522. {
  523. TextVisualizerLabels->SetWorldLocation(GetTextVisualizersLocation());
  524. UWorld* World = TextVisualizerLabels->GetWorld();
  525. if (World != nullptr && World->WorldType == EWorldType::EditorPreview)
  526. {
  527. TextVisualizerLabels->SetWorldRotation(FVector(100, 0, 0).Rotation());
  528. }
  529. }
  530. TextVisualizerLabels->bIsEditorOnly = true;
  531. // Creates a right-aligned block of text showing the property labels.
  532. TextVisualizerLabels->SetText(FText::FromString(FString::Format(TEXT("Volume {0}Area {0}Decay {0}AuxBus {0}Time to first reflection {0}HFDamping "), { LINE_TERMINATOR })));
  533. TextVisualizerLabels->bSelectable = false;
  534. }
  535. }
  536. if (!IsValid(TextVisualizerValues))
  537. {
  538. TextVisualizerValues = NewObject<UTextRenderComponent>(GetOuter(), *(TextVizName + TEXT("TextValues")));
  539. if (IsValid(TextVisualizerValues))
  540. {
  541. if (mat != nullptr)
  542. TextVisualizerValues->SetTextMaterial(mat);
  543. TextVisualizerValues->SetHorizontalAlignment(EHorizTextAligment::EHTA_Left);
  544. TextVisualizerValues->RegisterComponentWithWorld(GetWorld());
  545. TextVisualizerValues->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
  546. TextVisualizerValues->ResetRelativeTransform();
  547. TextVisualizerValues->SetWorldScale3D(FVector::OneVector);
  548. if (Parent.IsValid())
  549. {
  550. TextVisualizerValues->SetWorldLocation(GetTextVisualizersLocation());
  551. UWorld* World = TextVisualizerValues->GetWorld();
  552. if (World != nullptr && World->WorldType == EWorldType::EditorPreview)
  553. {
  554. TextVisualizerValues->SetWorldRotation(FVector(100, 0, 0).Rotation());
  555. }
  556. }
  557. TextVisualizerValues->bIsEditorOnly = true;
  558. TextVisualizerValues->bSelectable = false;
  559. UpdateValuesLabels();
  560. }
  561. }
  562. }
  563. }
  564. }
  565. void UAkLateReverbComponent::DestroyTextVisualizers()
  566. {
  567. if (IsValid(TextVisualizerLabels))
  568. {
  569. TextVisualizerLabels->DestroyComponent();
  570. TextVisualizerLabels = nullptr;
  571. }
  572. if (IsValid(TextVisualizerValues))
  573. {
  574. TextVisualizerValues->DestroyComponent();
  575. TextVisualizerValues = nullptr;
  576. }
  577. }
  578. void UAkLateReverbComponent::UpdateValuesLabels()
  579. {
  580. if (!GetDefault<UAkSettingsPerUser>()->bShowReverbInfo)
  581. return;
  582. if (!TextVisualizersInitialized())
  583. InitTextVisualizers();
  584. if (IsValid(TextVisualizerValues))
  585. {
  586. TextVisualizerValues->SetText(GetValuesLabels());
  587. bool visible = false;
  588. if (GetWorld() != nullptr)
  589. {
  590. EWorldType::Type WorldType = GetWorld()->WorldType;
  591. if (WorldType == EWorldType::Editor)
  592. {
  593. visible = GetOwner() != nullptr && GetOwner()->IsSelected();
  594. }
  595. else if (WorldType == EWorldType::EditorPreview)
  596. {
  597. visible = true;
  598. }
  599. }
  600. if (GetOwner() != nullptr)
  601. {
  602. TextVisualizerValues->SetVisibility(visible);
  603. if (IsValid(TextVisualizerLabels))
  604. TextVisualizerLabels->SetVisibility(visible);
  605. }
  606. }
  607. }
  608. #endif // WITH_EDITOR
  609. void UAkLateReverbComponent::UpdateRTPCs(const UAkRoomComponent* room) const
  610. {
  611. // The global RTPCs are set on the room ids.
  612. ReverbDescriptor.UpdateAllRTPCs(room);
  613. }
  614. void UAkLateReverbComponent::AssociateAkTextureSetComponent(UAkAcousticTextureSetComponent* textureSetComponent)
  615. {
  616. if (TextureSetComponent != nullptr)
  617. TextureSetComponent->SetReverbDescriptor(nullptr);
  618. TextureSetComponent = textureSetComponent;
  619. TextureSetComponent->SetReverbDescriptor(&ReverbDescriptor);
  620. }
  621. UAkAcousticTextureSetComponent* UAkLateReverbComponent::GetAttachedTextureSetComponent()
  622. {
  623. return TextureSetComponent;
  624. }
  625. void UAkLateReverbComponent::UpdateDecayEstimation(float decay, float volume, float surfaceArea)
  626. {
  627. if (AutoAssignAuxBus)
  628. {
  629. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  630. if (AkSettings != nullptr)
  631. {
  632. auto newAuxBus = AkSettings->GetAuxBusForDecayValue(decay);
  633. if (AuxBus != newAuxBus)
  634. {
  635. AuxBus = newAuxBus;
  636. ReverbParamsChanged = true;
  637. }
  638. }
  639. }
  640. #if WITH_EDITOR
  641. EnvironmentVolume = volume;
  642. SurfaceArea = surfaceArea;
  643. EnvironmentDecayEstimate = decay;
  644. UpdateValuesLabels();
  645. #endif // WITH_EDITOR
  646. }
  647. #if WITH_EDITOR
  648. void UAkLateReverbComponent::UpdateHFDampingEstimation(float hfDamping)
  649. {
  650. HFDamping = hfDamping;
  651. UpdateValuesLabels();
  652. }
  653. void UAkLateReverbComponent::UpdatePredelayEstimation(float predelay)
  654. {
  655. TimeToFirstReflection = predelay;
  656. UpdateValuesLabels();
  657. }
  658. void UAkLateReverbComponent::PreEditChange(FProperty* PropertyAboutToChange)
  659. {
  660. if (PropertyAboutToChange != nullptr)
  661. {
  662. if (!AutoAssignAuxBus
  663. && (PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus)
  664. || PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AuxBus)))
  665. {
  666. AuxBusManual = AuxBus;
  667. }
  668. if (AutoAssignAuxBus
  669. && PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus))
  670. {
  671. AuxBus = AuxBusManual;
  672. }
  673. }
  674. }
  675. void UAkLateReverbComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
  676. {
  677. Super::PostEditChangeProperty(PropertyChangedEvent);
  678. const FName MemberPropertyName = (PropertyChangedEvent.MemberProperty != nullptr) ? PropertyChangedEvent.MemberProperty->GetFName() : NAME_None;
  679. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus))
  680. {
  681. PrimaryComponentTick.bCanEverTick = AutoAssignAuxBus;
  682. PrimaryComponentTick.bStartWithTickEnabled = AutoAssignAuxBus;
  683. bTickInEditor = AutoAssignAuxBus;
  684. DecayEstimationNeedsUpdate = true;
  685. bTextStatusNeedsUpdate = true;
  686. if (!AutoAssignAuxBus)
  687. {
  688. AuxBus = AuxBusManual;
  689. ReverbParamsChanged = true;
  690. }
  691. }
  692. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AuxBus))
  693. {
  694. if (!AutoAssignAuxBus)
  695. {
  696. AuxBusManual = AuxBus;
  697. }
  698. ReverbParamsChanged = true;
  699. }
  700. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, bEnable))
  701. {
  702. if (AkComponentHelpers::IsInGameWorld(this))
  703. {
  704. UAkRoomComponent* RoomCmpt = nullptr;
  705. if (Parent.IsValid())
  706. {
  707. RoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent.Get());
  708. }
  709. if (!RoomCmpt || !RoomCmpt->RoomIsActive())
  710. {
  711. // No room, or inactive room. Update the late reverb in the oct tree.
  712. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  713. if (AkAudioDevice)
  714. {
  715. if (!bEnable && IsIndexed)
  716. {
  717. AkAudioDevice->UnindexLateReverb(this);
  718. }
  719. else if (bEnable && !IsIndexed)
  720. {
  721. AkAudioDevice->IndexLateReverb(this);
  722. }
  723. }
  724. }
  725. else if (RoomCmpt && RoomCmpt->RoomIsActive())
  726. {
  727. // Late reverb is inside an active room. Update the room such that the reverb aux bus is correctly updated.
  728. RoomCmpt->UpdateSpatialAudioRoom();
  729. }
  730. }
  731. else if (CreationMethod == EComponentCreationMethod::Instance && bEnable
  732. && GetDefault<UAkSettingsPerUser>()->bShowReverbInfo)
  733. {
  734. InitTextVisualizers();
  735. }
  736. }
  737. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, SendLevel))
  738. {
  739. ReverbParamsChanged = true;
  740. }
  741. }
  742. void UAkLateReverbComponent::OnAttachmentChanged()
  743. {
  744. Super::OnAttachmentChanged();
  745. // In other cases of CreationMethod, OnRegister() gets called to initialize the parent
  746. if (CreationMethod == EComponentCreationMethod::Instance)
  747. {
  748. // OnAttachmentChanged can be called when this component is getting detached from its parent
  749. // in this case InitializeParent will disable the component and set the parent and the ReverbDescriptor's primitive to null
  750. InitializeParent();
  751. ParentChanged();
  752. }
  753. }
  754. FVector UAkLateReverbComponent::GetTextVisualizersLocation()
  755. {
  756. if (!Parent.IsValid())
  757. return FVector();
  758. FBoxSphereBounds bounds = Parent->CalcBounds(Parent->GetComponentTransform());
  759. return Parent->GetComponentLocation() + FVector(0.0f, 0.0f, bounds.BoxExtent.Z + TextVisualizerHeightOffset);
  760. }
  761. void UAkLateReverbComponent::RegisterReverbAssignmentChangedCallback()
  762. {
  763. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  764. if (AkSettings != nullptr)
  765. {
  766. if (ReverbAssignmentChangedHandle.IsValid())
  767. {
  768. AkSettings->OnReverbAssignmentChanged.Remove(ReverbAssignmentChangedHandle);
  769. }
  770. ReverbAssignmentChangedHandle = AkSettings->OnReverbAssignmentChanged.AddLambda([this]()
  771. {
  772. ReverbAssignmentNeedsUpdate = true;
  773. bTextStatusNeedsUpdate = true;
  774. });
  775. }
  776. }
  777. void UAkLateReverbComponent::RegisterGlobalDecayAbsorptionChangedCallback()
  778. {
  779. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  780. if (AkSettings != nullptr)
  781. {
  782. if (GlobalDecayAbsorptionChangedHandle.IsValid())
  783. {
  784. AkSettings->OnGlobalDecayAbsorptionChanged.Remove(GlobalDecayAbsorptionChangedHandle);
  785. }
  786. GlobalDecayAbsorptionChangedHandle = AkSettings->OnGlobalDecayAbsorptionChanged.AddLambda([this]()
  787. {
  788. DecayEstimationNeedsUpdate = true;
  789. bTextStatusNeedsUpdate = true;
  790. });
  791. }
  792. }
  793. void UAkLateReverbComponent::RegisterReverbRTPCChangedCallback()
  794. {
  795. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  796. if (AkSettings != nullptr)
  797. {
  798. if (RTPCChangedHandle.IsValid())
  799. {
  800. AkSettings->OnReverbRTPCChanged.Remove(RTPCChangedHandle);
  801. }
  802. RTPCChangedHandle = AkSettings->OnReverbRTPCChanged.AddLambda([this]()
  803. {
  804. DecayEstimationNeedsUpdate = true;
  805. PredelayEstimationNeedsUpdate = true;
  806. bTextStatusNeedsUpdate = true;
  807. });
  808. }
  809. }
  810. #endif
  811. bool UAkLateReverbComponent::EncompassesPoint(FVector Point, float SphereRadius/*=0.f*/, float* OutDistanceToPoint) const
  812. {
  813. if (Parent.IsValid())
  814. {
  815. return AkComponentHelpers::EncompassesPoint(*Parent.Get(), Point, SphereRadius, OutDistanceToPoint);
  816. }
  817. FString actorString = FString("NONE");
  818. if (GetOwner() != nullptr)
  819. {
  820. #if WITH_EDITOR
  821. actorString = GetOwner()->GetActorLabel();
  822. #else
  823. actorString = GetOwner()->GetName();
  824. #endif
  825. }
  826. UE_LOG(LogAkAudio, Error, TEXT("UAkLateReverbComponent::EncompassesPoint : Error. In actor %s, AkLateReverbComponent %s has an invalid Parent."), *actorString, *GetName());
  827. return false;
  828. }
  829. void UAkLateReverbComponent::OnReverbParamsChanged()
  830. {
  831. if (AkComponentHelpers::IsInGameWorld(this))
  832. {
  833. UAkRoomComponent* RoomCmpt = nullptr;
  834. if (Parent.IsValid())
  835. {
  836. RoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent.Get());
  837. }
  838. if (!RoomCmpt || !RoomCmpt->RoomIsActive())
  839. {
  840. // No room, or inactive room. Update the late reverb in the oct tree.
  841. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  842. if (AkAudioDevice && bEnable && IsIndexed)
  843. {
  844. AkAudioDevice->ReindexLateReverb(this);
  845. }
  846. }
  847. else if (RoomCmpt && RoomCmpt->RoomIsActive())
  848. {
  849. // Late reverb is inside an active room. Update the room such that the reverb aux bus is correctly updated.
  850. RoomCmpt->UpdateSpatialAudioRoom();
  851. }
  852. }
  853. }