AkLateReverbComponent.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  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 "AkSettings.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 = nullptr;
  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)
  100. {
  101. ReverbDescriptor.SetReverbComponent(this);
  102. UBodySetup* bodySetup = Parent->GetBodySetup();
  103. if (bodySetup == nullptr || !AkComponentHelpers::HasSimpleCollisionGeometry(bodySetup))
  104. {
  105. if (UBrushComponent* brush = Cast<UBrushComponent>(Parent))
  106. brush->BuildSimpleBrushCollision();
  107. else
  108. AkComponentHelpers::LogSimpleGeometryWarning(Parent, this);
  109. }
  110. }
  111. else
  112. {
  113. bEnable = false;
  114. AkComponentHelpers::LogAttachmentError(this, SceneParent, "UPrimitiveComponent");
  115. return;
  116. }
  117. }
  118. else // will happen when this component gets detached from its parent
  119. {
  120. Parent = nullptr;
  121. ReverbDescriptor.SetPrimitive(nullptr);
  122. bEnable = false;
  123. }
  124. }
  125. void UAkLateReverbComponent::BeginPlay()
  126. {
  127. Super::BeginPlay();
  128. DecayEstimationNeedsUpdate = true;
  129. PredelayEstimationNeedsUpdate = true;
  130. UAkRoomComponent* pRoomCmpt = nullptr;
  131. if (Parent)
  132. {
  133. pRoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent);
  134. }
  135. if (!pRoomCmpt || !pRoomCmpt->RoomIsActive())
  136. {
  137. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  138. if (AkAudioDevice && LateReverbIsActive())
  139. {
  140. AkAudioDevice->IndexLateReverb(this);
  141. }
  142. }
  143. }
  144. void UAkLateReverbComponent::BeginDestroy()
  145. {
  146. Super::BeginDestroy();
  147. if (TextureSetComponent != nullptr)
  148. {
  149. TextureSetComponent->SetReverbDescriptor(nullptr);
  150. }
  151. ReverbDescriptor.SetPrimitive(nullptr);
  152. #if WITH_EDITOR
  153. if (AkSpatialAudioHelper::GetObjectReplacedEvent())
  154. {
  155. AkSpatialAudioHelper::GetObjectReplacedEvent()->RemoveAll(this);
  156. }
  157. #endif
  158. }
  159. void UAkLateReverbComponent::OnRegister()
  160. {
  161. Super::OnRegister();
  162. SetRelativeTransform(FTransform::Identity);
  163. InitializeParent();
  164. ParentChanged();
  165. // During runtime (non editor), we only want to tick if we'll ever need to update the reverb parameters.
  166. PrimaryComponentTick.bCanEverTick = ReverbDescriptor.RequiresUpdates();
  167. PrimaryComponentTick.bStartWithTickEnabled = ReverbDescriptor.RequiresUpdates();
  168. #if WITH_EDITOR
  169. // In editor builds we always want to tick in case the global RTPCs become active, or aux bus assignment is enabled.
  170. bTickInEditor = true;
  171. PrimaryComponentTick.bCanEverTick = true;
  172. PrimaryComponentTick.bStartWithTickEnabled = true;
  173. #endif
  174. }
  175. void UAkLateReverbComponent::ParentChanged()
  176. {
  177. if (IsValid(Parent))
  178. {
  179. #if WITH_EDITOR
  180. RegisterAuxBusMapChangedCallback();
  181. RegisterReverbRTPCChangedCallback();
  182. #endif
  183. // 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.
  184. // 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.
  185. if (UAkSurfaceReflectorSetComponent* surfaceComponent = AkComponentHelpers::GetChildComponentOfType<UAkSurfaceReflectorSetComponent>(*Parent))
  186. {
  187. AssociateAkTextureSetComponent(surfaceComponent);
  188. }
  189. else if (UAkGeometryComponent* geometryComponent = AkComponentHelpers::GetChildComponentOfType<UAkGeometryComponent>(*Parent))
  190. {
  191. AssociateAkTextureSetComponent(geometryComponent);
  192. }
  193. }
  194. DecayEstimationNeedsUpdate = true;
  195. PredelayEstimationNeedsUpdate = true;
  196. }
  197. void UAkLateReverbComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
  198. {
  199. Super::EndPlay(EndPlayReason);
  200. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  201. if (AkAudioDevice && IsIndexed)
  202. {
  203. AkAudioDevice->UnindexLateReverb(this);
  204. }
  205. }
  206. void UAkLateReverbComponent::OnUnregister()
  207. {
  208. Super::OnUnregister();
  209. #if WITH_EDITOR
  210. auto* World = GetWorld();
  211. if(World && World->IsPlayInEditor())
  212. {
  213. DestroyTextVisualizers();
  214. }
  215. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  216. if (AkSettings != nullptr)
  217. {
  218. if (AuxBusChangedHandle.IsValid())
  219. {
  220. AkSettings->OnAuxBusAssignmentMapChanged.Remove(AuxBusChangedHandle);
  221. }
  222. if (RTPCChangedHandle.IsValid())
  223. {
  224. AkSettings->OnReverbRTPCChanged.Remove(RTPCChangedHandle);
  225. }
  226. }
  227. #endif
  228. }
  229. bool UAkLateReverbComponent::MoveComponentImpl(
  230. const FVector & Delta,
  231. const FQuat & NewRotation,
  232. bool bSweep,
  233. FHitResult * Hit,
  234. EMoveComponentFlags MoveFlags,
  235. ETeleportType Teleport)
  236. {
  237. if (AkComponentHelpers::DoesMovementRecenterChild(this, Parent, Delta))
  238. Super::MoveComponentImpl(Delta, NewRotation, bSweep, Hit, MoveFlags, Teleport);
  239. return false;
  240. }
  241. void UAkLateReverbComponent::OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport)
  242. {
  243. DecayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimateDecay();
  244. PredelayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimatePredelay();
  245. if (IsIndexed)
  246. {
  247. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  248. if (AkAudioDevice)
  249. AkAudioDevice->ReindexLateReverb(this);
  250. }
  251. #if WITH_EDITOR
  252. if (TextVisualizerLabels != nullptr)
  253. {
  254. TextVisualizerLabels->SetWorldScale3D(FVector::OneVector);
  255. if (IsValid(Parent))
  256. {
  257. TextVisualizerLabels->SetWorldLocation(GetTextVisualizersLocation());
  258. }
  259. }
  260. if (TextVisualizerValues != nullptr)
  261. {
  262. TextVisualizerValues->SetWorldScale3D(FVector::OneVector);
  263. if (IsValid(Parent))
  264. {
  265. TextVisualizerValues->SetWorldLocation(GetTextVisualizersLocation());
  266. }
  267. }
  268. #endif
  269. }
  270. void UAkLateReverbComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
  271. {
  272. Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
  273. // Update decay and time to first reflection estimations when the size is changed, every PARAM_ESTIMATION_UPDATE_PERIOD seconds.
  274. if (SecondsSinceDecayUpdate < PARAM_ESTIMATION_UPDATE_PERIOD)
  275. {
  276. SecondsSinceDecayUpdate += DeltaTime;
  277. }
  278. if (DecayEstimationNeedsUpdate && SecondsSinceDecayUpdate >= PARAM_ESTIMATION_UPDATE_PERIOD)
  279. {
  280. RecalculateDecay();
  281. DecayEstimationNeedsUpdate = false;
  282. }
  283. if (SecondsSincePredelayUpdate < PARAM_ESTIMATION_UPDATE_PERIOD)
  284. {
  285. SecondsSincePredelayUpdate += DeltaTime;
  286. }
  287. if (PredelayEstimationNeedsUpdate && SecondsSincePredelayUpdate >= PARAM_ESTIMATION_UPDATE_PERIOD)
  288. {
  289. RecalculatePredelay();
  290. PredelayEstimationNeedsUpdate = false;
  291. }
  292. #if WITH_EDITOR
  293. UWorld* World = GetWorld();
  294. if (World == nullptr)
  295. return;
  296. if (GCurrentLevelEditingViewportClient != nullptr && World->WorldType == EWorldType::Editor)
  297. {
  298. // Keep the text renderers pointing to the camera.
  299. if (IsValid(TextVisualizerLabels))
  300. {
  301. FVector PointTo = GCurrentLevelEditingViewportClient->GetViewLocation() - TextVisualizerLabels->GetComponentLocation();
  302. TextVisualizerLabels->SetWorldRotation(PointTo.Rotation());
  303. }
  304. if (IsValid(TextVisualizerValues))
  305. {
  306. FVector PointTo = GCurrentLevelEditingViewportClient->GetViewLocation() - TextVisualizerValues->GetComponentLocation();
  307. TextVisualizerValues->SetWorldRotation(PointTo.Rotation());
  308. }
  309. }
  310. if (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::PIE)
  311. {
  312. // Only show the text renderer for selected actors.
  313. if (GetOwner()->IsSelected() && !WasSelected)
  314. {
  315. WasSelected = true;
  316. UpdateValuesLabels();
  317. }
  318. if (!GetOwner()->IsSelected() && WasSelected)
  319. {
  320. WasSelected = false;
  321. UpdateValuesLabels();
  322. }
  323. }
  324. if (bTextStatusNeedsUpdate)
  325. {
  326. UpdateTextVisualizerStatus();
  327. bTextStatusNeedsUpdate = false;
  328. }
  329. #endif
  330. }
  331. void UAkLateReverbComponent::RecalculateDecay()
  332. {
  333. if (ReverbDescriptor.ShouldEstimateDecay())
  334. {
  335. ReverbDescriptor.CalculateT60();
  336. SecondsSinceDecayUpdate = 0.0f;
  337. }
  338. }
  339. void UAkLateReverbComponent::RecalculatePredelay()
  340. {
  341. if (ReverbDescriptor.ShouldEstimatePredelay())
  342. {
  343. ReverbDescriptor.CalculateTimeToFirstReflection();
  344. SecondsSincePredelayUpdate = 0.0f;
  345. }
  346. }
  347. #if WITH_EDITOR
  348. void UAkLateReverbComponent::RegisterReverbInfoEnabledCallback()
  349. {
  350. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  351. if (AkSettings == nullptr || ShowReverbInfoChangedHandle.IsValid())
  352. return;
  353. ShowReverbInfoChangedHandle = AkSettings->OnShowReverbInfoChanged.AddLambda([this, AkSettings]()
  354. {
  355. bTextStatusNeedsUpdate = true;
  356. });
  357. }
  358. void UAkLateReverbComponent::OnComponentDestroyed(bool bDestroyingHierarchy)
  359. {
  360. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  361. if (!AkSettings)
  362. return;
  363. AkSettings->OnShowRoomsPortalsChanged.Remove(ShowReverbInfoChangedHandle);
  364. ShowReverbInfoChangedHandle.Reset();
  365. }
  366. void UAkLateReverbComponent::InitializeComponent()
  367. {
  368. Super::InitializeComponent();
  369. RegisterReverbInfoEnabledCallback();
  370. }
  371. void UAkLateReverbComponent::OnComponentCreated()
  372. {
  373. Super::OnComponentCreated();
  374. RegisterReverbInfoEnabledCallback();
  375. }
  376. void UAkLateReverbComponent::HandleObjectsReplaced(const TMap<UObject*, UObject*>& ReplacementMap)
  377. {
  378. if (ReplacementMap.Contains(Parent))
  379. {
  380. InitializeParent();
  381. DecayEstimationNeedsUpdate = true;
  382. PredelayEstimationNeedsUpdate = true;
  383. }
  384. if (ReplacementMap.Contains(TextureSetComponent))
  385. {
  386. if (Parent != nullptr)
  387. {
  388. if (UAkSurfaceReflectorSetComponent* SurfaceComponent = AkComponentHelpers::GetChildComponentOfType<UAkSurfaceReflectorSetComponent>(*Parent))
  389. {
  390. AssociateAkTextureSetComponent(SurfaceComponent);
  391. }
  392. else if (UAkGeometryComponent* GeomComponent = AkComponentHelpers::GetChildComponentOfType<UAkGeometryComponent>(*Parent))
  393. {
  394. AssociateAkTextureSetComponent(GeomComponent);
  395. }
  396. }
  397. }
  398. }
  399. void UAkLateReverbComponent::UpdateTextVisualizerStatus()
  400. {
  401. bool bShowReverbInfo = GetDefault<UAkSettings>()->bShowReverbInfo;
  402. // 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.
  403. // We only want to show the text renderers when the reverb parameter estimation is in use.
  404. if ((!bShowReverbInfo || !ReverbDescriptor.RequiresUpdates()) && TextVisualizersInitialized())
  405. {
  406. DestroyTextVisualizers();
  407. }
  408. else if ((bShowReverbInfo && ReverbDescriptor.RequiresUpdates()) && !TextVisualizersInitialized())
  409. {
  410. InitTextVisualizers();
  411. DecayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimateDecay();
  412. PredelayEstimationNeedsUpdate = ReverbDescriptor.ShouldEstimatePredelay();
  413. }
  414. }
  415. bool UAkLateReverbComponent::TextVisualizersInitialized() const
  416. {
  417. return IsValid(TextVisualizerLabels) && IsValid(TextVisualizerValues);
  418. }
  419. FText UAkLateReverbComponent::GetValuesLabels() const
  420. {
  421. // Get a nicely formatted string showing the values of all of the reverb properties in a left-aligned block.
  422. // They will appear adjacent to a right-aligned block showing the property labels.
  423. FString BusName = FString("NONE");
  424. if (AuxBus != nullptr)
  425. AuxBus->GetName(BusName);
  426. FNumberFormattingOptions NumberFormat;
  427. NumberFormat.MaximumFractionalDigits = 2;
  428. FString volumeString = FText::AsNumber(EnvironmentVolume, &NumberFormat).ToString();
  429. FString areaString = FText::AsNumber(SurfaceArea, &NumberFormat).ToString();
  430. const FString missingRoomString = FString("Requires sibling AkRoom component");
  431. FString decayString = missingRoomString;
  432. FString reflectionTimeString = missingRoomString;
  433. FString dampingString = missingRoomString;
  434. if (AutoAssignAuxBus)
  435. {
  436. decayString = FText::AsNumber(EnvironmentDecayEstimate, &NumberFormat).ToString() + " seconds";
  437. }
  438. if (Parent != nullptr && AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent))
  439. {
  440. decayString = ReverbDescriptor.ShouldEstimateDecay() ? FText::AsNumber(EnvironmentDecayEstimate, &NumberFormat).ToString() + " seconds" : FString("Invalid Late Reverb or Room Primitive Component");
  441. reflectionTimeString = FString("Invalid Late Reverb or Room Primitive Component");
  442. if (ReverbDescriptor.ShouldEstimatePredelay())
  443. {
  444. reflectionTimeString = FText::AsNumber(TimeToFirstReflection, &NumberFormat).ToString() + " ms";
  445. if (TimeToFirstReflection > 100.0f)
  446. {
  447. reflectionTimeString = FText::AsNumber(TimeToFirstReflection / 1000.0f, &NumberFormat).ToString() + " s";
  448. }
  449. }
  450. dampingString = "No associated geometry component.";
  451. if (TextureSetComponent != nullptr)
  452. {
  453. dampingString = ReverbDescriptor.ShouldEstimateDamping() ? FText::AsNumber(HFDamping, &NumberFormat).ToString() : FString("Invalid Late Reverb or Room Primitive Component");
  454. }
  455. }
  456. const UAkSettings* AkSettings = GetDefault<UAkSettings>();
  457. if (AkSettings != nullptr)
  458. {
  459. if (!AkSettings->DecayRTPCInUse())
  460. {
  461. decayString += FString(" (RTPC not in use)");
  462. }
  463. if (!AkSettings->PredelayRTPCInUse())
  464. {
  465. reflectionTimeString += FString(" (RTPC not in use)");
  466. }
  467. if (!AkSettings->DampingRTPCInUse())
  468. {
  469. dampingString += FString(" (RTPC not in use)");
  470. }
  471. }
  472. return FText::FromString(FString::Format(TEXT("{1} cubic meters{0}{2} square meters{0}{3}{0}{4}{0}{5}{0}{6}"),
  473. { LINE_TERMINATOR, volumeString, areaString, decayString, BusName, reflectionTimeString, dampingString }));
  474. }
  475. void UAkLateReverbComponent::InitTextVisualizers()
  476. {
  477. if (!HasAnyFlags(RF_Transient) && bEnable)
  478. {
  479. if (ReverbDescriptor.RequiresUpdates())
  480. {
  481. FString OwnerName;
  482. #if WITH_EDITOR
  483. OwnerName = GetOwner()->GetActorLabel();
  484. #else
  485. OwnerName = GetOwner()->GetName();
  486. #endif
  487. FString TextVizName = OwnerName + GetName();
  488. UMaterialInterface* mat = Cast<UMaterialInterface>(FAkAudioStyle::GetAkForegroundTextMaterial());
  489. if (!IsValid(TextVisualizerLabels))
  490. {
  491. TextVisualizerLabels = NewObject<UTextRenderComponent>(GetOuter(), *(TextVizName + TEXT("TextLabels")));
  492. if (IsValid(TextVisualizerLabels))
  493. {
  494. if (mat != nullptr)
  495. TextVisualizerLabels->SetTextMaterial(mat);
  496. TextVisualizerLabels->SetHorizontalAlignment(EHorizTextAligment::EHTA_Right);
  497. TextVisualizerLabels->RegisterComponentWithWorld(GetWorld());
  498. TextVisualizerLabels->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
  499. TextVisualizerLabels->ResetRelativeTransform();
  500. TextVisualizerLabels->SetWorldScale3D(FVector::OneVector);
  501. if (IsValid(Parent))
  502. {
  503. TextVisualizerLabels->SetWorldLocation(GetTextVisualizersLocation());
  504. UWorld* World = TextVisualizerLabels->GetWorld();
  505. if (World != nullptr && World->WorldType == EWorldType::EditorPreview)
  506. {
  507. TextVisualizerLabels->SetWorldRotation(FVector(100, 0, 0).Rotation());
  508. }
  509. }
  510. TextVisualizerLabels->bIsEditorOnly = true;
  511. // Creates a right-aligned block of text showing the property labels.
  512. TextVisualizerLabels->SetText(FText::FromString(FString::Format(TEXT("Volume {0}Area {0}Decay {0}AuxBus {0}Time to first reflection {0}HFDamping "), { LINE_TERMINATOR })));
  513. TextVisualizerLabels->bSelectable = false;
  514. }
  515. }
  516. if (!IsValid(TextVisualizerValues))
  517. {
  518. TextVisualizerValues = NewObject<UTextRenderComponent>(GetOuter(), *(TextVizName + TEXT("TextValues")));
  519. if (IsValid(TextVisualizerValues))
  520. {
  521. if (mat != nullptr)
  522. TextVisualizerValues->SetTextMaterial(mat);
  523. TextVisualizerValues->SetHorizontalAlignment(EHorizTextAligment::EHTA_Left);
  524. TextVisualizerValues->RegisterComponentWithWorld(GetWorld());
  525. TextVisualizerValues->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform);
  526. TextVisualizerValues->ResetRelativeTransform();
  527. TextVisualizerValues->SetWorldScale3D(FVector::OneVector);
  528. if (IsValid(Parent))
  529. {
  530. TextVisualizerValues->SetWorldLocation(GetTextVisualizersLocation());
  531. UWorld* World = TextVisualizerValues->GetWorld();
  532. if (World != nullptr && World->WorldType == EWorldType::EditorPreview)
  533. {
  534. TextVisualizerValues->SetWorldRotation(FVector(100, 0, 0).Rotation());
  535. }
  536. }
  537. TextVisualizerValues->bIsEditorOnly = true;
  538. TextVisualizerValues->bSelectable = false;
  539. UpdateValuesLabels();
  540. }
  541. }
  542. }
  543. }
  544. }
  545. void UAkLateReverbComponent::DestroyTextVisualizers()
  546. {
  547. if (IsValid(TextVisualizerLabels))
  548. {
  549. TextVisualizerLabels->DestroyComponent();
  550. TextVisualizerLabels = nullptr;
  551. }
  552. if (IsValid(TextVisualizerValues))
  553. {
  554. TextVisualizerValues->DestroyComponent();
  555. TextVisualizerValues = nullptr;
  556. }
  557. }
  558. void UAkLateReverbComponent::UpdateValuesLabels()
  559. {
  560. if (!GetDefault<UAkSettings>()->bShowReverbInfo)
  561. return;
  562. if (!TextVisualizersInitialized())
  563. InitTextVisualizers();
  564. if (IsValid(TextVisualizerValues))
  565. {
  566. TextVisualizerValues->SetText(GetValuesLabels());
  567. bool visible = false;
  568. if (GetWorld() != nullptr)
  569. {
  570. EWorldType::Type WorldType = GetWorld()->WorldType;
  571. if (WorldType == EWorldType::Editor)
  572. {
  573. visible = GetOwner() != nullptr && GetOwner()->IsSelected();
  574. }
  575. else if (WorldType == EWorldType::EditorPreview)
  576. {
  577. visible = true;
  578. }
  579. }
  580. if (GetOwner() != nullptr)
  581. {
  582. TextVisualizerValues->SetVisibility(visible);
  583. if (IsValid(TextVisualizerLabels))
  584. TextVisualizerLabels->SetVisibility(visible);
  585. }
  586. }
  587. }
  588. #endif // WITH_EDITOR
  589. void UAkLateReverbComponent::UpdateRTPCs(const UAkRoomComponent* room) const
  590. {
  591. // The global RTPCs are set on the room ids.
  592. ReverbDescriptor.UpdateAllRTPCs(room);
  593. }
  594. void UAkLateReverbComponent::AssociateAkTextureSetComponent(UAkAcousticTextureSetComponent* textureSetComponent)
  595. {
  596. if (TextureSetComponent != nullptr)
  597. TextureSetComponent->SetReverbDescriptor(nullptr);
  598. TextureSetComponent = textureSetComponent;
  599. TextureSetComponent->SetReverbDescriptor(&ReverbDescriptor);
  600. }
  601. void UAkLateReverbComponent::UpdateDecayEstimation(float decay, float volume, float surfaceArea)
  602. {
  603. if (AutoAssignAuxBus)
  604. {
  605. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  606. if (AkSettings != nullptr)
  607. {
  608. AkSettings->GetAuxBusForDecayValue(decay, AuxBus);
  609. }
  610. }
  611. #if WITH_EDITOR
  612. EnvironmentVolume = volume;
  613. SurfaceArea = surfaceArea;
  614. EnvironmentDecayEstimate = decay;
  615. UpdateValuesLabels();
  616. #endif // WITH_EDITOR
  617. }
  618. #if WITH_EDITOR
  619. void UAkLateReverbComponent::UpdateHFDampingEstimation(float hfDamping)
  620. {
  621. HFDamping = hfDamping;
  622. UpdateValuesLabels();
  623. }
  624. void UAkLateReverbComponent::UpdatePredelayEstimation(float predelay)
  625. {
  626. TimeToFirstReflection = predelay;
  627. UpdateValuesLabels();
  628. }
  629. void UAkLateReverbComponent::PreEditChange(FProperty* PropertyAboutToChange)
  630. {
  631. if (PropertyAboutToChange != nullptr)
  632. {
  633. if (!AutoAssignAuxBus
  634. && (PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus)
  635. || PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AuxBus)))
  636. {
  637. AuxBusManual = AuxBus;
  638. }
  639. if (AutoAssignAuxBus
  640. && PropertyAboutToChange->NamePrivate == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus))
  641. {
  642. AuxBus = AuxBusManual;
  643. }
  644. }
  645. }
  646. void UAkLateReverbComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
  647. {
  648. Super::PostEditChangeProperty(PropertyChangedEvent);
  649. const FName MemberPropertyName = (PropertyChangedEvent.MemberProperty != nullptr) ? PropertyChangedEvent.MemberProperty->GetFName() : NAME_None;
  650. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AutoAssignAuxBus))
  651. {
  652. PrimaryComponentTick.bCanEverTick = AutoAssignAuxBus;
  653. PrimaryComponentTick.bStartWithTickEnabled = AutoAssignAuxBus;
  654. bTickInEditor = AutoAssignAuxBus;
  655. DecayEstimationNeedsUpdate = true;
  656. bTextStatusNeedsUpdate = true;
  657. if (!AutoAssignAuxBus)
  658. {
  659. AuxBus = AuxBusManual;
  660. }
  661. }
  662. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, AuxBus))
  663. {
  664. if (!AutoAssignAuxBus)
  665. {
  666. AuxBusManual = AuxBus;
  667. }
  668. if (AkComponentHelpers::IsInGameWorld(this))
  669. {
  670. UAkRoomComponent* RoomCmpt = nullptr;
  671. if (Parent)
  672. {
  673. RoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent);
  674. }
  675. if (!RoomCmpt || !RoomCmpt->RoomIsActive())
  676. {
  677. // No room, or inactive room. Update the late reverb in the oct tree.
  678. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  679. if (AkAudioDevice && bEnable && IsIndexed)
  680. {
  681. AkAudioDevice->ReindexLateReverb(this);
  682. }
  683. }
  684. else if (RoomCmpt && RoomCmpt->RoomIsActive())
  685. {
  686. // Late reverb is inside an active room. Update the room such that the reverb aux bus is correctly updated.
  687. RoomCmpt->UpdateSpatialAudioRoom();
  688. }
  689. }
  690. }
  691. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, bEnable))
  692. {
  693. if (AkComponentHelpers::IsInGameWorld(this))
  694. {
  695. UAkRoomComponent* RoomCmpt = nullptr;
  696. if (Parent)
  697. {
  698. RoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent);
  699. }
  700. if (!RoomCmpt || !RoomCmpt->RoomIsActive())
  701. {
  702. // No room, or inactive room. Update the late reverb in the oct tree.
  703. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  704. if (AkAudioDevice)
  705. {
  706. if (!bEnable && IsIndexed)
  707. {
  708. AkAudioDevice->UnindexLateReverb(this);
  709. }
  710. else if (bEnable && !IsIndexed)
  711. {
  712. AkAudioDevice->IndexLateReverb(this);
  713. }
  714. }
  715. }
  716. else if (RoomCmpt && RoomCmpt->RoomIsActive())
  717. {
  718. // Late reverb is inside an active room. Update the room such that the reverb aux bus is correctly updated.
  719. RoomCmpt->UpdateSpatialAudioRoom();
  720. }
  721. }
  722. else if (CreationMethod == EComponentCreationMethod::Instance && bEnable
  723. && GetDefault<UAkSettings>()->bShowReverbInfo)
  724. {
  725. InitTextVisualizers();
  726. }
  727. }
  728. if (MemberPropertyName == GET_MEMBER_NAME_CHECKED(UAkLateReverbComponent, SendLevel))
  729. {
  730. UWorld* World = GetWorld();
  731. if (World != nullptr && (World->WorldType == EWorldType::Game || World->WorldType == EWorldType::PIE))
  732. {
  733. UAkRoomComponent* RoomCmpt = nullptr;
  734. if (Parent)
  735. {
  736. RoomCmpt = AkComponentHelpers::GetChildComponentOfType<UAkRoomComponent>(*Parent);
  737. }
  738. if (!RoomCmpt || !RoomCmpt->RoomIsActive())
  739. {
  740. // No room, or inactive room. Update the late reverb in the oct tree.
  741. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  742. if (AkAudioDevice && bEnable && IsIndexed)
  743. {
  744. AkAudioDevice->ReindexLateReverb(this);
  745. }
  746. }
  747. else if (RoomCmpt&& RoomCmpt->RoomIsActive())
  748. {
  749. // Late reverb is inside an active room. Update the room such that the reverb send level is correctly updated.
  750. RoomCmpt->UpdateSpatialAudioRoom();
  751. }
  752. }
  753. }
  754. }
  755. void UAkLateReverbComponent::OnAttachmentChanged()
  756. {
  757. Super::OnAttachmentChanged();
  758. // In other cases of CreationMethod, OnRegister() gets called to initialize the parent
  759. if (CreationMethod == EComponentCreationMethod::Instance)
  760. {
  761. // OnAttachmentChanged can be called when this component is getting detached from its parent
  762. // in this case InitializeParent will disable the component and set the parent and the ReverbDescriptor's primitive to null
  763. InitializeParent();
  764. ParentChanged();
  765. }
  766. }
  767. FVector UAkLateReverbComponent::GetTextVisualizersLocation()
  768. {
  769. if (!IsValid(Parent))
  770. return FVector();
  771. FBoxSphereBounds bounds = Parent->CalcBounds(Parent->GetComponentTransform());
  772. return Parent->GetComponentLocation() + FVector(0.0f, 0.0f, bounds.BoxExtent.Z + TextVisualizerHeightOffset);
  773. }
  774. void UAkLateReverbComponent::RegisterAuxBusMapChangedCallback()
  775. {
  776. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  777. if (AkSettings != nullptr)
  778. {
  779. if (AuxBusChangedHandle.IsValid())
  780. AkSettings->OnAuxBusAssignmentMapChanged.Remove(AuxBusChangedHandle);
  781. AuxBusChangedHandle = AkSettings->OnAuxBusAssignmentMapChanged.AddLambda([this]()
  782. {
  783. DecayEstimationNeedsUpdate = true;
  784. bTextStatusNeedsUpdate = true;
  785. });
  786. }
  787. }
  788. void UAkLateReverbComponent::RegisterReverbRTPCChangedCallback()
  789. {
  790. UAkSettings* AkSettings = GetMutableDefault<UAkSettings>();
  791. if (AkSettings != nullptr)
  792. {
  793. if (RTPCChangedHandle.IsValid())
  794. AkSettings->OnReverbRTPCChanged.Remove(RTPCChangedHandle);
  795. RTPCChangedHandle = AkSettings->OnReverbRTPCChanged.AddLambda([this]()
  796. {
  797. DecayEstimationNeedsUpdate = true;
  798. PredelayEstimationNeedsUpdate = true;
  799. bTextStatusNeedsUpdate = true;
  800. });
  801. }
  802. }
  803. #endif
  804. bool UAkLateReverbComponent::EncompassesPoint(FVector Point, float SphereRadius/*=0.f*/, float* OutDistanceToPoint) const
  805. {
  806. if (IsValid(Parent))
  807. {
  808. return AkComponentHelpers::EncompassesPoint(*Parent, Point, SphereRadius, OutDistanceToPoint);
  809. }
  810. FString actorString = FString("NONE");
  811. if (GetOwner() != nullptr)
  812. {
  813. #if WITH_EDITOR
  814. actorString = GetOwner()->GetActorLabel();
  815. #else
  816. actorString = GetOwner()->GetName();
  817. #endif
  818. }
  819. UE_LOG(LogAkAudio, Error, TEXT("UAkLateReverbComponent::EncompassesPoint : Error. In actor %s, AkLateReverbComponent %s has an invalid Parent."), *actorString, *GetName());
  820. return false;
  821. }