123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- /*******************************************************************************
- The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
- Technology released in source code form as part of the game integration package.
- The content of this file may not be used without valid licenses to the
- AUDIOKINETIC Wwise Technology.
- Note that the use of the game engine is subject to the Unreal(R) Engine End User
- License Agreement at https://www.unrealengine.com/en-US/eula/unreal
-
- License Usage
-
- Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
- this file in accordance with the end user license agreement provided with the
- software or, alternatively, in accordance with the terms contained
- in a written agreement between you and Audiokinetic Inc.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #include "SAcousticSurfacesController.h"
- #include "AkSurfaceReflectorSetComponent.h"
- #include "DetailCategoryBuilder.h"
- #include "DetailLayoutBuilder.h"
- #include "EditorModeManager.h"
- #include "EditorModes.h"
- #include "Engine/Selection.h"
- #include "Editor/TransBuffer.h"
- #include "EditorSupportDelegates.h"
- #include "PropertyCustomizationHelpers.h"
- #include "Widgets/SBoxPanel.h"
- #include "Widgets/Input/SButton.h"
- #include "Widgets/Input/SCheckBox.h"
- #include "Widgets/Input/SNumericEntryBox.h"
- #include "Widgets/Input/SSlider.h"
- #include "Widgets/Layout/SBox.h"
- #include "Widgets/SOverlay.h"
- #include "Widgets/Text/STextBlock.h"
- #if AK_SUPPORT_WAAPI
- #include "AkWaapiClient.h"
- #include "AkWaapiUtils.h"
- #include "Async/Async.h"
- #endif
- #define LOCTEXT_NAMESPACE "AkAudio"
- namespace AkAcousticSurfacesUI
- {
- static FText OverrideButtonText = FText::FromString(FString("Override"));
- static int OverrideButtonPadding = 5;
- static int LabelWidth = 102;
- }
- class SOverrideControls : public SCompoundWidget
- {
- public:
- SLATE_BEGIN_ARGS(SOverrideControls) {}
- /** Called when the button is clicked */
- SLATE_EVENT(FOnClicked, OnButtonClicked)
- SLATE_END_ARGS()
- void Construct(const FArguments& InArgs)
- {
- OnButtonClicked = InArgs._OnButtonClicked;
- ChildSlot
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Label
- .AutoWidth()
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- [
- SNew(STextBlock)
- .Text(FText::FromString(FString(TEXT("Multiple Values"))))
- ]
- + SHorizontalBox::Slot() // Button
- .AutoWidth()
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .Padding(AkAcousticSurfacesUI::OverrideButtonPadding, 0)
- [
- SNew(SButton)
- .Text(AkAcousticSurfacesUI::OverrideButtonText)
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .OnClicked(this, &SOverrideControls::CallClicked)
- ]
- ];
- }
- private:
- FOnClicked OnButtonClicked;
- FReply CallClicked() { return OnButtonClicked.Execute(); }
- };
- // ==================================================
- // SAcousticSurfacesLabels
- // ==================================================
- void SAcousticSurfacesLabels::Construct(const FArguments& InArgs, TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized)
- {
- ComponentsBeingCustomized = ObjectsBeingCustomized;
- ChildSlot
- [
- SNew(SVerticalBox)
- + SVerticalBox::Slot() // Acoustic Surface Parameters
- .FillHeight(1.0f)
- [
- SNew(SVerticalBox)
- + SVerticalBox::Slot() // Texture
- .FillHeight(0.33f)
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Label
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SBox)
- .WidthOverride(AkAcousticSurfacesUI::LabelWidth)
- [
- SNew(STextBlock)
- .ToolTipText(FText::FromString("The Acoustic Texture associated with the selected surfaces. When set to None, the texture is completely reflective. If the Surface Reflector component is disabled, the geometry is not used for reflections or diffractions. In this case, Acoustic Textures are used exclusively to measure Environment Decay and HFDamping as part of the Reverb Estimation process."))
- .Text(FText::FromString(FString(TEXT("AkAcousticTexture"))))
- .Font(IDetailLayoutBuilder::GetDetailFont())
- ]
- ]
- ]
- + SVerticalBox::Slot() // Occlusion
- .FillHeight(0.33f)
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return TransmissionLossEnableSurfaceVisibility(); })
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Label
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SBox)
- .WidthOverride(AkAcousticSurfacesUI::LabelWidth)
- [
- SNew(STextBlock)
- .ToolTipText(FText::FromString("Indicates how much sound is transmitted through the selected surfaces. With a Transmission Loss value of 0, all sounds pass through the surface, and the Acoustic Texture has no effect. With a value of 1, 100% Transmission Loss is applied to sounds that pass through the selected surfaces."))
- .Text(FText::FromString(FString(TEXT("Transmission Loss"))))
- .Font(IDetailLayoutBuilder::GetDetailFont())
- ]
- ]
- ]
- ]
- + SVerticalBox::Slot() // EnableSurface
- .FillHeight(0.33f)
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Label
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SBox)
- .WidthOverride(AkAcousticSurfacesUI::LabelWidth)
- [
- SNew(STextBlock)
- .ToolTipText(FText::FromString("An enabled surface is associated with the selected Acoustic Texture and Transmission Loss value above. A disabled surface is not associated with an Acoustic Texture, and has a Transmission Loss value of 0 (sound passes through the surface). If Surface Reflector Set is disabled, there is no Transmission Loss property to customize. In this case, enabled surfaces do not let sound pass through (equivalent to a Transmission Loss value of 1) and disabled surfaces let sound pass through (equivalent to a Transmission Loss value of 0)."))
- .Text(FText::FromString(FString(TEXT("Enable Surface"))))
- .Font(IDetailLayoutBuilder::GetDetailFont())
- ]
- ]
- ]
- ]
- ];
- }
- EVisibility SAcousticSurfacesLabels::TransmissionLossEnableSurfaceVisibility()
- {
- for (TWeakObjectPtr<UObject> ObjectBeingCustomized : ComponentsBeingCustomized)
- {
- UAkSurfaceReflectorSetComponent* reflectorSetComponent = Cast<UAkSurfaceReflectorSetComponent>(ObjectBeingCustomized.Get());
- if (reflectorSetComponent && reflectorSetComponent->bEnableSurfaceReflectors)
- {
- return EVisibility::Visible;
- }
- }
- return EVisibility::Collapsed;
- }
- // ==================================================
- // SAcousticSurfacesController
- // ==================================================
- void SAcousticSurfacesController::Construct(const FArguments& InArgs, TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized, const TSharedPtr<IDetailLayoutBuilder>& InLayoutBuilder)
- {
- ensure(ObjectsBeingCustomized.Num() > 0);
- LayoutBuilder = InLayoutBuilder;
- FCoreUObjectDelegates::FOnObjectPropertyChanged::FDelegate OnPropertyChangedDelegate = FCoreUObjectDelegates::FOnObjectPropertyChanged::FDelegate::CreateRaw(this, &SAcousticSurfacesController::OnPropertyChanged);
- OnPropertyChangedHandle = FCoreUObjectDelegates::OnObjectPropertyChanged.Add(OnPropertyChangedDelegate);
- GLevelEditorModeTools().OnEditorModeIDChanged().AddRaw(this, &SAcousticSurfacesController::OnEditorModeChanged);
- ComponentsToEdit = ObjectsBeingCustomized;
- if (GLevelEditorModeTools().IsModeActive(FEditorModeID(TEXT("EM_Geometry"))))
- {
- // In geometry edit mode, we only want to apply to all faces when no individual faces are selected.
- bool individualSelection = false;
- // Loop through all selected components to check if any indivdual faces are selected.
- // If no individual faces are selected, we'll just apply the changes to every face on each component.
- for (TWeakObjectPtr<UObject> ObjectBeingCustomized : ComponentsToEdit)
- {
- UAkSurfaceReflectorSetComponent* reflectorSetComponent = Cast<UAkSurfaceReflectorSetComponent>(ObjectBeingCustomized.Get());
- if (reflectorSetComponent)
- {
- TSet<int> FacesToEdit = reflectorSetComponent->GetSelectedFaceIndices();
- if (FacesToEdit.Num() > 0)
- {
- individualSelection = true;
- break;
- }
- }
- }
- ApplyToAllFaces = !individualSelection;
- }
- else
- {
- ApplyToAllFaces = true;
- }
- InitReflectorSetsFacesToEdit();
- UpdateCurrentValues();
- #if AK_SUPPORT_WAAPI
- RegisterTextureDeletedCallback();
- #endif
- BuildSlate();
- }
- SAcousticSurfacesController::~SAcousticSurfacesController()
- {
- #if AK_SUPPORT_WAAPI
- RemoveTextureDeletedCallback();
- #endif
- FCoreUObjectDelegates::OnObjectPropertyChanged.Remove(OnPropertyChangedHandle);
- GLevelEditorModeTools().OnEditorModeIDChanged().RemoveAll(this);
- }
- void SAcousticSurfacesController::InitReflectorSetsFacesToEdit()
- {
- NumFacesSelected = 0;
- for (TWeakObjectPtr<UObject> ObjectBeingCustomized : ComponentsToEdit)
- {
- UAkSurfaceReflectorSetComponent* reflectorSetComponent = Cast<UAkSurfaceReflectorSetComponent>(ObjectBeingCustomized.Get());
- if (reflectorSetComponent)
- {
- TSet<int> FacesToEdit;
- if (ApplyToAllFaces)
- {
- for (int i = 0; i < reflectorSetComponent->AcousticPolys.Num(); ++i)
- FacesToEdit.Add(i);
- }
- else
- {
- FacesToEdit = reflectorSetComponent->GetSelectedFaceIndices();
- }
- NumFacesSelected += FacesToEdit.Num();
- if (FacesToEdit.Num() > 0)
- ReflectorSetsFacesToEdit.Add(reflectorSetComponent, FacesToEdit);
- }
- }
- UpdateCurrentValues();
- }
- FAkSurfacePoly& SAcousticSurfacesController::GetAcousticSurfaceChecked(UAkSurfaceReflectorSetComponent* reflectorSet, int faceIndex)
- {
- ensure(faceIndex <= reflectorSet->AcousticPolys.Num());
- return reflectorSet->AcousticPolys[faceIndex];
- }
- void SAcousticSurfacesController::RefreshEditor(bool reinitVisualizers /*= false*/) const
- {
- FEditorSupportDelegates::RedrawAllViewports.Broadcast();
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- if (reinitVisualizers)
- {
- ReflectorSetComponent->CacheAcousticProperties();
- ReflectorSetComponent->UpdatePolys();
- }
- else
- {
- ReflectorSetComponent->SurfacePropertiesChanged();
- }
- }
- }
- RefreshLayout();
- }
- void SAcousticSurfacesController::RefreshLayout() const
- {
- if (!LayoutBuilder.IsValid())
- {
- return;
- }
- IDetailLayoutBuilder* Layout = nullptr;
- if (auto LockedLayoutBuilder = LayoutBuilder.Pin())
- {
- Layout = LockedLayoutBuilder.Get();
- }
- if (LIKELY(Layout))
- {
- Layout->ForceRefreshDetails();
- }
- }
- void SAcousticSurfacesController::BeginModify(FText TransactionText)
- {
- if (GEditor && GEditor->Trans)
- {
- UTransBuffer* TransBuffer = CastChecked<UTransBuffer>(GEditor->Trans);
- if (TransBuffer != nullptr)
- TransBuffer->Begin(*FString("AkSurfaceReflectorSet Acoustic Surfaces"), TransactionText);
- }
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- ReflectorSetComponent->Modify();
- }
- }
- void SAcousticSurfacesController::EndModify()
- {
- if (GEditor && GEditor->Trans)
- {
- UTransBuffer* TransBuffer = CastChecked<UTransBuffer>(GEditor->Trans);
- if (TransBuffer != nullptr)
- TransBuffer->End();
- }
- }
- void SAcousticSurfacesController::OnPropertyChanged(UObject* ObjectBeingModified, FPropertyChangedEvent& PropertyChangedEvent)
- {
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ObjectBeingModified == ReflectorSetComponent)
- {
- if (PropertyChangedEvent.MemberProperty == nullptr)
- {
- // OnPropertyChanged is called with a null MemberProperty when undoing
- RefreshLayout();
- }
- else
- {
- const FName memberPropertyName = PropertyChangedEvent.MemberProperty->GetFName();
- if (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkSurfaceReflectorSetComponent, AcousticPolys))
- {
- UpdateCurrentValues();
- }
- }
- return;
- }
- }
- }
- void SAcousticSurfacesController::OnEditorModeChanged(const FEditorModeID& InEditorModeID, bool bIsEnteringMode)
- {
- if (InEditorModeID == FEditorModeID(TEXT("EM_Geometry")))
- {
- if (bIsEnteringMode)
- {
- ApplyToAllFaces = false;
- InitReflectorSetsFacesToEdit();
- Invalidate(EInvalidateWidgetReason::Paint);
- }
- else
- {
- ApplyToAllFaces = true;
- InitReflectorSetsFacesToEdit();
- Invalidate(EInvalidateWidgetReason::Paint);
- }
- }
- }
- FText SAcousticSurfacesController::GetSelectionText() const
- {
- FString selectionInfo = "(All faces)";
- if (!ApplyToAllFaces && NumFacesSelected > 0)
- {
- selectionInfo = "(" + FString::FromInt(NumFacesSelected) + " faces selected)";
- }
- return FText::FromString(selectionInfo);
- }
- FText SAcousticSurfacesController::GetSelectionTextTooltip() const
- {
- if (!ApplyToAllFaces && NumFacesSelected > 0)
- {
- return FText::FromString(FString("Changes will apply to all selected faces."));
- }
- return FText::FromString(FString("Changes will apply to all faces. Use ") + GEOMETRY_EDIT_DISPLAY_NAME + " to select individual faces. You can enable " GEOMETRY_EDIT_DISPLAY_NAME " by clicking 'Enable Edit Surfaces'.");
- }
- void SAcousticSurfacesController::UpdateCurrentValues()
- {
- CurrentTexture = GetCollectiveTexture(TexturesDiffer);
- CurrentOcclusion = GetCollectiveOcclusion(OcclusionsDiffer);
- CurrentEnablement = GetCollectiveEnableSurface(EnablementsDiffer);
- }
- void SAcousticSurfacesController::OnTextureAssetChanged(const FAssetData& InAssetData)
- {
- BeginModify(FText::FromString(FString("Set Textures")));
- CurrentTexture = Cast<UAkAcousticTexture>(InAssetData.GetAsset());
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = elem.Value;
- for (const int& i : FacesToEdit)
- {
- GetAcousticSurfaceChecked(ReflectorSetComponent, i).Texture = CurrentTexture;
- }
- }
- }
- RefreshEditor();
- EndModify();
- }
- FString SAcousticSurfacesController::GetSelectedTextureAssetPath() const
- {
- if (CurrentTexture == nullptr)
- {
- return "";
- }
-
- FSoftObjectPath path(CurrentTexture);
- return path.GetAssetPathString();
- }
- EVisibility SAcousticSurfacesController::TransmissionLossEnableSurfaceVisibility()
- {
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr && ReflectorSetComponent->bEnableSurfaceReflectors)
- return EVisibility::Visible;
- }
- return EVisibility::Collapsed;
- }
- EVisibility SAcousticSurfacesController::OverrideTextureControlsVisibility()
- {
- if (TexturesDiffer)
- return EVisibility::Visible;
- return EVisibility::Collapsed;
- }
- FReply SAcousticSurfacesController::OnOverrideTextureButtonClicked()
- {
- BeginModify(FText::FromString(FString("Override Textures")));
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = elem.Value;
- for (const int& i : FacesToEdit)
- {
- GetAcousticSurfaceChecked(ReflectorSetComponent, i).Texture = nullptr;
- }
- }
- }
- RefreshEditor();
- EndModify();
- return FReply::Handled();
- }
- UAkAcousticTexture* SAcousticSurfacesController::GetCollectiveTexture(bool& ValuesDiffer)
- {
- ValuesDiffer = false;
- if (ReflectorSetsFacesToEdit.Num() == 0)
- return nullptr;
- auto it = ReflectorSetsFacesToEdit.CreateIterator();
- ensure(it.Key() != nullptr);
- int firstIndex = *(it.Value().begin());
- UAkAcousticTexture* texture = it.Key()->AcousticPolys[firstIndex].Texture;
- for (; it; ++it)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = it.Key();
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = it.Value();
- for (const int& i : FacesToEdit)
- {
- if (GetAcousticSurfaceChecked(ReflectorSetComponent, i).Texture != texture)
- {
- ValuesDiffer = true;
- texture = nullptr;
- break;
- }
- }
- }
- }
- return texture;
- }
- EVisibility SAcousticSurfacesController::OverrideOcclusionControlsVisibility()
- {
- return OcclusionsDiffer ? EVisibility::Visible : EVisibility::Collapsed;
- }
- FReply SAcousticSurfacesController::OnOverrideOcclusionButtonClicked()
- {
- BeginModify(FText::FromString(FString("Override Transmission Loss Values")));
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = elem.Value;
- for (const int& i : FacesToEdit)
- {
- GetAcousticSurfaceChecked(ReflectorSetComponent, i).Occlusion = 0.0f;
- }
- }
- }
- RefreshEditor();
- EndModify();
- return FReply::Handled();
- }
- float SAcousticSurfacesController::GetCollectiveOcclusion(bool& ValuesDiffer)
- {
- ValuesDiffer = false;
- if (ReflectorSetsFacesToEdit.Num() == 0)
- return 0.0f;
- auto it = ReflectorSetsFacesToEdit.CreateIterator();
- ensure(it.Key() != nullptr);
- int firstIndex = *(it.Value().begin());
- float occlusion = it.Key()->AcousticPolys[firstIndex].Occlusion;
- for (; it; ++it)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = it.Key();
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = it.Value();
- for (const int& i : FacesToEdit)
- {
- if (GetAcousticSurfaceChecked(ReflectorSetComponent, i).Occlusion != occlusion)
- {
- ValuesDiffer = true;
- occlusion = 0.0f;
- break;
- }
- }
- }
- }
- return occlusion;
- }
- TOptional<float> SAcousticSurfacesController::GetOcclusionSliderValue() const
- {
- return CurrentOcclusion;
- }
- void SAcousticSurfacesController::OnOcclusionSliderChanged(float NewValue, ETextCommit::Type Commit)
- {
- // TODO: Remove this when fixed.
- // There is a bug in UE5.1 when modifying numerical properties and pressing Enter.
- // This is the case for the occlusion(transmission loss) value of acoustic surfaces.
- // This function is getting called a second time with a wrong occlusion value.
- // When that happens, LayoutBuilder is invalid, so we check it to make sure the value is valid as well.
- if (!LayoutBuilder.IsValid())
- {
- return;
- }
- // Only apply valid values
- if (NewValue >= 0.0f && NewValue <= 1.0f)
- {
- BeginModify(FText::FromString(FString("Set Transmission Loss Values")));
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = elem.Value;
- for (const int& i : FacesToEdit)
- {
- GetAcousticSurfaceChecked(ReflectorSetComponent, i).Occlusion = NewValue;
- }
- }
- }
- RefreshEditor();
- EndModify();
- }
- }
- bool SAcousticSurfacesController::GetCollectiveEnableSurface(bool& ValuesDiffer)
- {
- ValuesDiffer = false;
- if (ReflectorSetsFacesToEdit.Num() == 0)
- return false;
- auto it = ReflectorSetsFacesToEdit.CreateIterator();
- ensure(it.Key() != nullptr);
- int firstIndex = *(it.Value().begin());
- bool enableSurface = it.Key()->AcousticPolys[firstIndex].EnableSurface;
- for (; it; ++it)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = it.Key();
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = it.Value();
- for (const int& i : FacesToEdit)
- {
- if (GetAcousticSurfaceChecked(ReflectorSetComponent, i).EnableSurface != enableSurface)
- {
- ValuesDiffer = true;
- enableSurface = false;
- break;
- }
- }
- }
- }
- return enableSurface;
- }
- ECheckBoxState SAcousticSurfacesController::GetEnableSurfaceCheckBoxState() const
- {
- return EnablementsDiffer ? ECheckBoxState::Undetermined
- : (CurrentEnablement ? ECheckBoxState::Checked : ECheckBoxState::Unchecked);
- }
- void SAcousticSurfacesController::OnEnableCheckboxChanged(ECheckBoxState NewState)
- {
- BeginModify(FText::FromString(FString("Set Enable Surfaces")));
- for (auto elem : ReflectorSetsFacesToEdit)
- {
- UAkSurfaceReflectorSetComponent* ReflectorSetComponent = elem.Key;
- if (ReflectorSetComponent != nullptr)
- {
- TSet<int> FacesToEdit = elem.Value;
- if (NewState != ECheckBoxState::Undetermined)
- {
- bool enable = NewState == ECheckBoxState::Checked;
- for (const int& i : FacesToEdit)
- {
- GetAcousticSurfaceChecked(ReflectorSetComponent, i).EnableSurface = enable;
- }
- }
- }
- }
- RefreshEditor(true);
- EndModify();
- }
- #if AK_SUPPORT_WAAPI
- void SAcousticSurfacesController::RegisterTextureDeletedCallback()
- {
- FAkWaapiClient* waapiClient = FAkWaapiClient::Get();
- if (waapiClient != nullptr && waapiClient->IsConnected())
- {
- auto textureDeletedCallback = WampEventCallback::CreateLambda([this](uint64_t id, TSharedPtr<FJsonObject> jsonObject)
- {
- const TSharedPtr<FJsonObject> itemObj = jsonObject->GetObjectField(WwiseWaapiHelper::OBJECT);
- if (itemObj != nullptr)
- {
- const FString itemIdString = itemObj->GetStringField(WwiseWaapiHelper::ID);
- FGuid itemID = FGuid::NewGuid();
- FGuid::ParseExact(itemIdString, EGuidFormats::DigitsWithHyphensInBraces, itemID);
- if (CurrentTexture != nullptr && itemID == CurrentTexture->AcousticTextureInfo.WwiseGuid)
- {
- AsyncTask(ENamedThreads::GameThread, [this, itemID]
- {
- CurrentTexture = nullptr;
- });
- }
- }
- });
- TSharedRef<FJsonObject> options = MakeShareable(new FJsonObject());
- options->SetArrayField(WwiseWaapiHelper::RETURN, TArray<TSharedPtr<FJsonValue>> { MakeShareable(new FJsonValueString(WwiseWaapiHelper::ID)) });
- TSharedPtr<FJsonObject> outJsonResult;
- if (!waapiClient->Subscribe(ak::wwise::core::object::preDeleted, options, textureDeletedCallback, TextureDeleteSubscriptionID, outJsonResult))
- {
- UE_LOG(LogAkAudio, Warning, TEXT("AkSettings: WAAPI: Acoustic texture object preDeleted subscription failed."));
- }
- }
- }
- void SAcousticSurfacesController::RemoveTextureDeletedCallback()
- {
- FAkWaapiClient* waapiClient = FAkWaapiClient::Get();
- if (waapiClient != nullptr && waapiClient->IsConnected() && TextureDeleteSubscriptionID != 0)
- {
- TSharedPtr<FJsonObject> unsubscribeResult;
- waapiClient->Unsubscribe(TextureDeleteSubscriptionID, unsubscribeResult);
- }
- }
- #endif
- void SAcousticSurfacesController::BuildSlate()
- {
- FSlateFontInfo SelectionInfoFont = FAkAppStyle::Get().GetFontStyle("TinyText");
- if (LayoutBuilder.IsValid())
- {
- if (auto LockedDetailBuilder = LayoutBuilder.Pin())
- {
- SelectionInfoFont = LockedDetailBuilder->GetDetailFontItalic();
- }
- }
- ChildSlot
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Acoustic Surface Parameters
- .AutoWidth()
- [
- SNew(SVerticalBox)
- + SVerticalBox::Slot() // Texture
- .FillHeight(0.33f)
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Control
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SOverlay)
- + SOverlay::Slot()
- [
- SNew(SObjectPropertyEntryBox)
- .AllowedClass(UAkAcousticTexture::StaticClass())
- .OnObjectChanged(this, &SAcousticSurfacesController::OnTextureAssetChanged)
- .ObjectPath(this, &SAcousticSurfacesController::GetSelectedTextureAssetPath)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- .Visibility_Lambda([this]() { return (OverrideTextureControlsVisibility() == EVisibility::Collapsed) ? EVisibility::Visible : EVisibility::Collapsed; })
- ]
- + SOverlay::Slot() // Multiple values controls
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return OverrideTextureControlsVisibility(); })
- [
- SNew(SOverrideControls)
- .OnButtonClicked(this, &SAcousticSurfacesController::OnOverrideTextureButtonClicked)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- ]
- ]
- ]
- ]
- + SVerticalBox::Slot() // Occlusion
- .FillHeight(0.33f)
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return TransmissionLossEnableSurfaceVisibility(); })
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Control
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SOverlay)
- + SOverlay::Slot()
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return (OverrideOcclusionControlsVisibility() == EVisibility::Collapsed) ? EVisibility::Visible : EVisibility::Collapsed; })
- [
- SNew(SNumericEntryBox<float>)
- .MinValue(0.0f)
- .MaxValue(1.0f)
- .MinSliderValue(0.0f)
- .MaxSliderValue(1.0f)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- .Value(this, &SAcousticSurfacesController::GetOcclusionSliderValue)
- .OnValueCommitted(this, &SAcousticSurfacesController::OnOcclusionSliderChanged)
- ]
- ]
- + SOverlay::Slot() // Multiple values controls
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return OverrideOcclusionControlsVisibility(); })
- [
- SNew(SOverrideControls)
- .OnButtonClicked(this, &SAcousticSurfacesController::OnOverrideOcclusionButtonClicked)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- ]
- ]
- ]
- ]
- ]
- + SVerticalBox::Slot() // EnableSurface
- .FillHeight(0.33f)
- [
- SNew(SHorizontalBox)
- + SHorizontalBox::Slot() // Control
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- .AutoWidth()
- [
- SNew(SCheckBox)
- .IsChecked(ECheckBoxState::Undetermined)
- .OnCheckStateChanged(this, &SAcousticSurfacesController::OnEnableCheckboxChanged)
- .IsChecked(this, &SAcousticSurfacesController::GetEnableSurfaceCheckBoxState)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- ]
- ]
- ]
- + SHorizontalBox::Slot() // Selection Info
- .AutoWidth()
- [
- SNew(SVerticalBox)
- + SVerticalBox::Slot() // Texture
- .FillHeight(0.33f)
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- [
- SNew(STextBlock)
- .Text(this, &SAcousticSurfacesController::GetSelectionText)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- .Font(SelectionInfoFont)
- ]
- + SVerticalBox::Slot() // Occlusion
- .FillHeight(0.33f)
- [
- SNew(SBox)
- .Visibility_Lambda([this]() { return TransmissionLossEnableSurfaceVisibility(); })
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- [
- SNew(STextBlock)
- .Text(this, &SAcousticSurfacesController::GetSelectionText)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- .Font(SelectionInfoFont)
- ]
- ]
- + SVerticalBox::Slot() // EnableSurface
- .FillHeight(0.33f)
- .HAlign(HAlign_Left)
- .VAlign(VAlign_Center)
- [
- SNew(STextBlock)
- .Text(this, &SAcousticSurfacesController::GetSelectionText)
- .ToolTipText(this, &SAcousticSurfacesController::GetSelectionTextTooltip)
- .Font(SelectionInfoFont)
- ]
- ]
- ];
- }
- #undef LOCTEXT_NAMESPACE
|