Files
UnrealEngineUWP/Engine/Source/Editor/AudioEditor/Private/AudioEditorModule.cpp
Aaron McLeran 447ea21ca1 Copying //UE4/Dev-Audio to //UE4/Dev-Main (Source: //UE4/Dev-Audio @ 4332921)
#lockdown Nick.Penwarden


============================
  MAJOR FEATURES & CHANGES
============================

Change 4233107 by Aaron.McLeran

	New filter submix effect.

	#jira none

Change 4233108 by Aaron.McLeran

	Adding dry-level for submix effect reverb.

	#jira none

Change 4233112 by Aaron.McLeran

	Submix envelope following feature.

	- To use, register a BP delegate callback via AddEnvelopeFollowerDelegate.
	- Envelope value returned is a value for each channel in the submix (i.e. 2 for stereo, 6 for 5.1, etc)

	#jira none

Change 4309683 by Aaron.McLeran

	Making unregistering a sound class happen on the audio thread.

	#jira none

Change 4309690 by Aaron.McLeran

	Making unregistering a sound class happen on the audio thread.

	Fixing CL 4309683 typo

	#jira none

Change 4312378 by Aaron.McLeran

	Checking in audio device hot swap fix code

	#jira none

Change 4312381 by Aaron.McLeran

	Change label to Play When Silent for bVirtualizeWhenSilent

	#jira none

Change 4315516 by Aaron.McLeran

	Fix for audio mixer source initialization state.

	#jira none

Change 4317052 by Ethan.Geller

	Unshelved from pending changelist '4017367':

	PR #4680: Refactor Voice Subsystems (Contributed by erebuswolf)


Change 4317784 by Aaron.McLeran

	New audio icons.

	#jira none

Change 4317785 by Aaron.McLeran

	Hooking up new audio icons in C++.

	- Made preprocessor macros to help setting icons for audio assets
	- Moving icon definitions of other audio assets to AudioEditor module.

	#jira none

Change 4317787 by Aaron.McLeran

	Fix for warning during cooking of source buses.

	#jira none

Change 4319727 by Aaron.McLeran

	Updating icons w/ transparent backgrounds

	#jira none

Change 4320672 by Kevin.Neilson

	Adding test map for Effects testing (and pan bug)

Change 4321142 by Aaron.McLeran

	Making source buses not render as sound wave thumbnails

	#jira none

Change 4321143 by Aaron.McLeran

	Fixing source buses so that new source buses will work after creating.

	#jira none

Change 4321191 by Kevin.Neilson

	adding the Send_Test map to allow for crash repro

Change 4321456 by Aaron.McLeran

	Fix for persistent submix effect settings between PIE sessions.

	#jira none

Change 4321503 by Aaron.McLeran

	Fix for google resonance plugin when using -AudioPIEOnly and PIE shutdown.

	- Changed check to a warning.
	- Issue is when using AudioPIEOnly, decoding stream is never initialized...

Change 4321504 by Aaron.McLeran

	Fixing TSharedPtr bug on PIE shutdown

	- Removing TSharedPtr for a lot of objects, which was causing object refs to leak
	- Moved to using TWeakPtr where it makes sense to keep the safety but avoid leaky refs
	- Fixing setting reset for both submix and source effect presets.

	#jira none

Change 4322887 by Aaron.McLeran

	#jira UE-63419

	Fix for CIS error

Change 4324325 by Ethan.Geller

	fix for AudioMixerSubmix voice lookup crash #fyi aaron.mcleran #rb none

Change 4324340 by Ethan.Geller

	Come to think of it, it would also potentially crash here if we did not have a valid entry in the map. #fyi aaron.mcleran #rb none

Change 4324512 by Aaron.McLeran

	#jira UE-63396 Fixing memory overwrite

Change 4324668 by Aaron.McLeran

	Removing unnecessary InitSoundSubmixes when creating source buses.

	- This function should only be called on engine init!

	#jira none

Change 4329745 by Ethan.Geller

	Fix InitSoundSubmix call to avoid a bad check on creating a USoundSubmix asset.
	#jira none #codereview aaron.mcleran #fyi kevin.neilson #rb none

Change 4315524 by Aaron.McLeran

	Making source effects be per-buffer vs per-frame.

	- Allows source effects to be more cache-coherent and opens door to SIMD-able source effects.
	- Also cleaned up DSP API to be more consistent and clear with respect to process functions
	- Optimized a few DSP objects (e.g. one-pole filters, etc)

	#jira none

[CL 4333130 by Aaron McLeran in Main branch]
2018-08-30 13:57:45 -04:00

338 lines
13 KiB
C++

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "AudioEditorModule.h"
#include "Modules/ModuleManager.h"
#include "Sound/SoundNodeDialoguePlayer.h"
#include "EdGraphUtilities.h"
#include "SoundCueGraphConnectionDrawingPolicy.h"
#include "Factories/SoundFactory.h"
#include "Factories/ReimportSoundFactory.h"
#include "SoundCueGraph/SoundCueGraphNode.h"
#include "SoundCueGraphNodeFactory.h"
#include "Factories/ReimportSoundSurroundFactory.h"
#include "AssetToolsModule.h"
#include "SoundClassEditor.h"
#include "Sound/SoundCue.h"
#include "Sound/SoundWave.h"
#include "Sound/SoundSubmix.h"
#include "Sound/SoundEffectPreset.h"
#include "SoundCueEditor.h"
#include "SoundSubmixEditor.h"
#include "Sound/AudioSettings.h"
#include "AssetTypeActions/AssetTypeActions_DialogueVoice.h"
#include "AssetTypeActions/AssetTypeActions_DialogueWave.h"
#include "AssetTypeActions/AssetTypeActions_SoundAttenuation.h"
#include "AssetTypeActions/AssetTypeActions_SoundConcurrency.h"
#include "AssetTypeActions/AssetTypeActions_SoundBase.h"
#include "AssetTypeActions/AssetTypeActions_SoundClass.h"
#include "AssetTypeActions/AssetTypeActions_SoundCue.h"
#include "AssetTypeActions/AssetTypeActions_SoundMix.h"
#include "AssetTypeActions/AssetTypeActions_SoundWave.h"
#include "AssetTypeActions/AssetTypeActions_ReverbEffect.h"
#include "AssetTypeActions/AssetTypeActions_SoundSubmix.h"
#include "AssetTypeActions/AssetTypeActions_SoundEffectPreset.h"
#include "AssetTypeActions/AssetTypeActions_SoundSourceBus.h"
#include "Utils.h"
#include "UObject/UObjectIterator.h"
#include "Styling/SlateStyle.h"
#include "Styling/SlateStyleRegistry.h"
const FName AudioEditorAppIdentifier = FName(TEXT("AudioEditorApp"));
DEFINE_LOG_CATEGORY(LogAudioEditor);
class FSlateStyleSet;
struct FGraphPanelPinConnectionFactory;
// Preprocessor macro to make defining audio icons simple...
// CLASS_NAME - name of the class to make the icon for
// ICON_NAME - base-name of the icon to use. Not necessarily based off class name
#define SET_AUDIO_ICON(CLASS_NAME, ICON_NAME) \
AudioStyleSet->Set( *FString::Printf(TEXT("ClassIcon.%s"), TEXT(#CLASS_NAME)), new FSlateImageBrush(FPaths::EngineContentDir() / FString::Printf(TEXT("Editor/Slate/Icons/AssetIcons/%s_16x.png"), TEXT(#ICON_NAME)), Icon16)); \
AudioStyleSet->Set( *FString::Printf(TEXT("ClassThumbnail.%s"), TEXT(#CLASS_NAME)), new FSlateImageBrush(FPaths::EngineContentDir() / FString::Printf(TEXT("Editor/Slate/Icons/AssetIcons/%s_64x.png"), TEXT(#ICON_NAME)), Icon64));
// Simpler version of SET_AUDIO_ICON, assumes same name of icon png and class name
#define SET_AUDIO_ICON_SIMPLE(CLASS_NAME) SET_AUDIO_ICON(CLASS_NAME, CLASS_NAME)
class FAudioEditorModule : public IAudioEditorModule
{
public:
FAudioEditorModule()
{
}
virtual void StartupModule() override
{
SoundClassExtensibility.Init();
SoundCueExtensibility.Init();
SoundSubmixExtensibility.Init();
// Register the sound cue graph connection policy with the graph editor
SoundCueGraphConnectionFactory = MakeShareable(new FSoundCueGraphConnectionDrawingPolicyFactory);
FEdGraphUtilities::RegisterVisualPinConnectionFactory(SoundCueGraphConnectionFactory);
TSharedPtr<FSoundCueGraphNodeFactory> SoundCueGraphNodeFactory = MakeShareable(new FSoundCueGraphNodeFactory());
FEdGraphUtilities::RegisterVisualNodeFactory(SoundCueGraphNodeFactory);
// Create reimport handler for sound node waves
UReimportSoundFactory::StaticClass();
// Create reimport handler for surround sound waves
UReimportSoundSurroundFactory::StaticClass();
SetupIcons();
}
virtual void ShutdownModule() override
{
SoundClassExtensibility.Reset();
SoundCueExtensibility.Reset();
SoundSubmixExtensibility.Reset();
if (SoundCueGraphConnectionFactory.IsValid())
{
FEdGraphUtilities::UnregisterVisualPinConnectionFactory(SoundCueGraphConnectionFactory);
}
}
virtual void RegisterAssetActions() override
{
// Register the audio editor asset type actions
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_DialogueVoice));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_DialogueWave));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundAttenuation));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundConcurrency));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundBase));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundClass));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundCue));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundMix));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundWave));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_ReverbEffect));
}
virtual void RegisterAudioMixerAssetActions() override
{
// Only register asset actions for when audio mixer data is enabled
if (GetDefault<UAudioSettings>()->IsAudioMixerEnabled())
{
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundSubmix));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundEffectSubmixPreset));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundEffectSourcePreset));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundEffectSourcePresetChain));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundSourceBus));
}
}
virtual void AddSoundWaveActionExtender(TSharedPtr<ISoundWaveAssetActionExtensions> InSoundWaveAssetActionExtender) override
{
if (InSoundWaveAssetActionExtender.IsValid())
{
SoundWaveAssetActionExtensions.AddUnique(InSoundWaveAssetActionExtender);
}
}
virtual void GetSoundWaveActionExtenders(TArray<TSharedPtr<ISoundWaveAssetActionExtensions>>& OutSoundwaveActionExtensions) override
{
OutSoundwaveActionExtensions = SoundWaveAssetActionExtensions;
}
virtual void RegisterEffectPresetAssetActions() override
{
// Only register asset actions for the case where audio mixer data is enabled
if (GetDefault<UAudioSettings>()->IsAudioMixerEnabled())
{
// Register the audio editor asset type actions
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
// Look for any sound effect presets to register
for (TObjectIterator<UClass> It; It; ++It)
{
UClass* ChildClass = *It;
if (ChildClass->HasAnyClassFlags(CLASS_Abstract))
{
continue;
}
// Look for submix or source preset classes
UClass* ParentClass = ChildClass->GetSuperClass();
if (ParentClass->IsChildOf(USoundEffectSourcePreset::StaticClass()) || ParentClass->IsChildOf(USoundEffectSubmixPreset::StaticClass()))
{
USoundEffectPreset* EffectPreset = ChildClass->GetDefaultObject<USoundEffectPreset>();
if (!RegisteredActions.Contains(EffectPreset) && EffectPreset->HasAssetActions())
{
RegisteredActions.Add(EffectPreset);
AssetTools.RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_SoundEffectPreset(EffectPreset)));
}
}
}
}
}
virtual TSharedRef<FAssetEditorToolkit> CreateSoundClassEditor( const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, USoundClass* InSoundClass ) override
{
TSharedRef<FSoundClassEditor> NewSoundClassEditor(new FSoundClassEditor());
NewSoundClassEditor->InitSoundClassEditor(Mode, InitToolkitHost, InSoundClass);
return NewSoundClassEditor;
}
virtual TSharedRef<FAssetEditorToolkit> CreateSoundSubmixEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, USoundSubmix* InSoundSubmix) override
{
TSharedRef<FSoundSubmixEditor> NewSoundSubmixEditor(new FSoundSubmixEditor());
NewSoundSubmixEditor->InitSoundSubmixEditor(Mode, InitToolkitHost, InSoundSubmix);
return NewSoundSubmixEditor;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundClassMenuExtensibilityManager() override
{
return SoundClassExtensibility.MenuExtensibilityManager;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundClassToolBarExtensibilityManager() override
{
return SoundClassExtensibility.ToolBarExtensibilityManager;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundSubmixMenuExtensibilityManager() override
{
return SoundSubmixExtensibility.MenuExtensibilityManager;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundSubmixToolBarExtensibilityManager() override
{
return SoundSubmixExtensibility.ToolBarExtensibilityManager;
}
virtual TSharedRef<ISoundCueEditor> CreateSoundCueEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, USoundCue* SoundCue) override
{
TSharedRef<FSoundCueEditor> NewSoundCueEditor(new FSoundCueEditor());
NewSoundCueEditor->InitSoundCueEditor(Mode, InitToolkitHost, SoundCue);
return NewSoundCueEditor;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundCueMenuExtensibilityManager() override
{
return SoundCueExtensibility.MenuExtensibilityManager;
}
virtual TSharedPtr<FExtensibilityManager> GetSoundCueToolBarExtensibilityManager() override
{
return SoundCueExtensibility.MenuExtensibilityManager;
}
virtual void ReplaceSoundNodesInGraph(USoundCue* SoundCue, UDialogueWave* DialogueWave, TArray<USoundNode*>& NodesToReplace, const FDialogueContextMapping& ContextMapping) override
{
// Replace any sound nodes in the graph.
TArray<USoundCueGraphNode*> GraphNodesToRemove;
for (USoundNode* const SoundNode : NodesToReplace)
{
// Create the new dialogue wave player.
USoundNodeDialoguePlayer* DialoguePlayer = SoundCue->ConstructSoundNode<USoundNodeDialoguePlayer>();
DialoguePlayer->SetDialogueWave(DialogueWave);
DialoguePlayer->DialogueWaveParameter.Context = ContextMapping.Context;
// We won't need the newly created graph node as we're about to move the dialogue wave player onto the original node.
GraphNodesToRemove.Add(CastChecked<USoundCueGraphNode>(DialoguePlayer->GetGraphNode()));
// Swap out the sound wave player in the graph node with the new dialogue wave player.
USoundCueGraphNode* SoundGraphNode = CastChecked<USoundCueGraphNode>(SoundNode->GetGraphNode());
SoundGraphNode->SetSoundNode(DialoguePlayer);
}
for (USoundCueGraphNode* const SoundGraphNode : GraphNodesToRemove)
{
SoundCue->GetGraph()->RemoveNode(SoundGraphNode);
}
// Make sure the cue is updated to match its graph.
SoundCue->CompileSoundNodesFromGraphNodes();
for (USoundNode* const SoundNode : NodesToReplace)
{
// Remove the old node from the list of available nodes.
SoundCue->AllNodes.Remove(SoundNode);
}
SoundCue->MarkPackageDirty();
}
USoundWave* ImportSoundWave(UPackage* const SoundWavePackage, const FString& InSoundWaveAssetName, const FString& InWavFilename) override
{
USoundFactory* SoundWaveFactory = NewObject<USoundFactory>();
// Setup sane defaults for importing localized sound waves
SoundWaveFactory->bAutoCreateCue = false;
SoundWaveFactory->SuppressImportOverwriteDialog();
return ImportObject<USoundWave>(SoundWavePackage, *InSoundWaveAssetName, RF_Public | RF_Standalone, *InWavFilename, nullptr, SoundWaveFactory);
}
private:
void SetupIcons()
{
// Setup icon sizes
FVector2D Icon16 = FVector2D(16.0f, 16.0f);
FVector2D Icon64 = FVector2D(64.0f, 64.0f);
// Setup the audio icon root
FString AudioIconRoot = TEXT("Icons/AssetIcons/");
// Create style set for audio asset icons
AudioStyleSet = MakeShareable(new FSlateStyleSet("AudioStyleSet"));
SET_AUDIO_ICON_SIMPLE(SoundAttenuation);
SET_AUDIO_ICON_SIMPLE(AmbientSound);
SET_AUDIO_ICON_SIMPLE(SoundClass);
SET_AUDIO_ICON_SIMPLE(SoundConcurrency);
SET_AUDIO_ICON_SIMPLE(SoundCue);
SET_AUDIO_ICON_SIMPLE(SoundMix);
SET_AUDIO_ICON_SIMPLE(AudioVolume);
SET_AUDIO_ICON_SIMPLE(SoundSourceBus);
SET_AUDIO_ICON_SIMPLE(SoundSubmix);
SET_AUDIO_ICON_SIMPLE(ReverbEffect);
SET_AUDIO_ICON(SoundEffectSubmixPreset, SubmixEffectPreset);
SET_AUDIO_ICON(SoundEffectSourcePreset, SourceEffectPreset);
SET_AUDIO_ICON(SoundEffectSourcePresetChain, SourceEffectPresetChain_1);
SET_AUDIO_ICON(ModularSynthPresetBank, SoundGenericIcon_2);
FSlateStyleRegistry::RegisterSlateStyle(*AudioStyleSet.Get());
}
struct FExtensibilityManagers
{
TSharedPtr<FExtensibilityManager> MenuExtensibilityManager;
TSharedPtr<FExtensibilityManager> ToolBarExtensibilityManager;
void Init()
{
MenuExtensibilityManager = MakeShareable(new FExtensibilityManager);
ToolBarExtensibilityManager = MakeShareable(new FExtensibilityManager);
}
void Reset()
{
MenuExtensibilityManager.Reset();
ToolBarExtensibilityManager.Reset();
}
};
FExtensibilityManagers SoundCueExtensibility;
FExtensibilityManagers SoundClassExtensibility;
FExtensibilityManagers SoundSubmixExtensibility;
TArray<TSharedPtr<ISoundWaveAssetActionExtensions>> SoundWaveAssetActionExtensions;
TSet<USoundEffectPreset*> RegisteredActions;
TSharedPtr<FGraphPanelPinConnectionFactory> SoundCueGraphConnectionFactory;
TSharedPtr<FSlateStyleSet> AudioStyleSet;
};
IMPLEMENT_MODULE( FAudioEditorModule, AudioEditor );