MovieSceneAkAudioRTPCTrackEditor.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. #include "MovieSceneAkAudioRTPCTrackEditor.h"
  16. #include "AkAudioDevice.h"
  17. #include "AkRtpc.h"
  18. #include "MovieScene.h"
  19. #include "MovieSceneCommonHelpers.h"
  20. #include "MovieSceneAkAudioRTPCTrack.h"
  21. #include "MovieSceneAkAudioRTPCSection.h"
  22. #include "SequencerUtilities.h"
  23. #include "ISequencerSection.h"
  24. #include "ISequencerObjectChangeListener.h"
  25. #include "ISectionLayoutBuilder.h"
  26. #include "SequencerSectionPainter.h"
  27. #include "AkAudioStyle.h"
  28. #include "ContentBrowserModule.h"
  29. #include "IContentBrowserSingleton.h"
  30. #include "ScopedTransaction.h"
  31. #include "Widgets/Layout/SBorder.h"
  32. #include "Widgets/Layout/SUniformGridPanel.h"
  33. #include "Widgets/Layout/SExpandableArea.h"
  34. #include "Widgets/Input/SEditableTextBox.h"
  35. #include "Widgets/Input/SButton.h"
  36. #include "Editor.h"
  37. #define LOCTEXT_NAMESPACE "MovieSceneAkAudioRTPCTrackEditor"
  38. /**
  39. * Class that draws a transform section in the sequencer
  40. */
  41. class FMovieSceneAkAudioRTPCSection
  42. : public ISequencerSection
  43. {
  44. public:
  45. FMovieSceneAkAudioRTPCSection(UMovieSceneSection& InSection)
  46. : Section(Cast<UMovieSceneAkAudioRTPCSection>(&InSection))
  47. { }
  48. public:
  49. // ISequencerSection interface
  50. virtual UMovieSceneSection* GetSectionObject() override { return Section; }
  51. virtual FText GetSectionTitle() const override
  52. {
  53. return FText::FromString(Section->GetRTPCName());
  54. }
  55. virtual int32 OnPaintSection(FSequencerSectionPainter& InPainter) const override
  56. {
  57. return InPainter.PaintSectionBackground();
  58. }
  59. private:
  60. /** The section we are visualizing */
  61. UMovieSceneAkAudioRTPCSection* Section;
  62. };
  63. FMovieSceneAkAudioRTPCTrackEditor::FMovieSceneAkAudioRTPCTrackEditor(TSharedRef<ISequencer> InSequencer)
  64. : FKeyframeTrackEditor<UMovieSceneAkAudioRTPCTrack>(InSequencer)
  65. {
  66. }
  67. TSharedRef<ISequencerTrackEditor> FMovieSceneAkAudioRTPCTrackEditor::CreateTrackEditor(TSharedRef<ISequencer> InSequencer)
  68. {
  69. return MakeShareable(new FMovieSceneAkAudioRTPCTrackEditor(InSequencer));
  70. }
  71. TSharedRef<ISequencerSection> FMovieSceneAkAudioRTPCTrackEditor::MakeSectionInterface(UMovieSceneSection& SectionObject, UMovieSceneTrack& Track, FGuid ObjectBinding)
  72. {
  73. return MakeShareable(new FMovieSceneAkAudioRTPCSection(SectionObject));
  74. }
  75. const FSlateBrush* FMovieSceneAkAudioRTPCTrackEditor::GetIconBrush() const
  76. {
  77. return FAkAudioStyle::Get().GetBrush("AudiokineticTools.RTPCIcon");
  78. }
  79. struct FRTPCSectionCreateDialogOptions
  80. {
  81. FString RTPCName;
  82. UAkRtpc* RTPC = nullptr;
  83. bool OkClicked;
  84. FRTPCSectionCreateDialogOptions() : OkClicked(false) {}
  85. bool Validate()
  86. {
  87. return OkClicked && (RTPC != nullptr || RTPCName.Len() > 0);
  88. }
  89. };
  90. class SCreateAkAudioRTPCSectionDialog
  91. : public SCompoundWidget
  92. {
  93. public:
  94. SLATE_BEGIN_ARGS(SCreateAkAudioRTPCSectionDialog) { }
  95. SLATE_END_ARGS()
  96. /** Construct this widget. */
  97. void Construct(const FArguments& InArgs, FRTPCSectionCreateDialogOptions& InOptions, TSharedRef<SWindow> InWindow)
  98. {
  99. Options = &InOptions;
  100. Window = InWindow;
  101. FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
  102. FAssetPickerConfig AssetPickerConfig;
  103. AssetPickerConfig.InitialAssetViewType = EAssetViewType::List;
  104. AssetPickerConfig.bAllowNullSelection = false;
  105. #if UE_5_1_OR_LATER
  106. AssetPickerConfig.Filter.ClassPaths.Add(UAkRtpc::StaticClass()->GetClassPathName());
  107. #else
  108. AssetPickerConfig.Filter.ClassNames.Add(UAkRtpc::StaticClass()->GetFName());
  109. #endif
  110. AssetPickerConfig.OnAssetSelected = FOnAssetSelected::CreateLambda([&InOptions](const FAssetData& InRTPCAssetData) {
  111. if (InRTPCAssetData.IsValid())
  112. {
  113. InOptions.RTPC = CastChecked<UAkRtpc>(InRTPCAssetData.GetAsset());
  114. }
  115. });
  116. ChildSlot
  117. [
  118. SNew(SBorder)
  119. .Visibility(EVisibility::Visible)
  120. .BorderImage(FAkAppStyle::Get().GetBrush("Menu.Background"))
  121. [
  122. SNew(SVerticalBox)
  123. + SVerticalBox::Slot()
  124. .AutoHeight()
  125. .VAlign(VAlign_Top)
  126. .Padding(4)
  127. [
  128. SNew(SBorder)
  129. .BorderImage(FAkAppStyle::Get().GetBrush("ToolPanel.GroupBorder"))
  130. .Padding(4.0f)
  131. .Content()
  132. [
  133. SNew(SHorizontalBox)
  134. + SHorizontalBox::Slot()
  135. .AutoWidth()
  136. .Padding(2, 2, 6, 2)
  137. [
  138. SNew(STextBlock)
  139. .Text(LOCTEXT("AkAudioRTPC", "RTPC"))
  140. ]
  141. + SHorizontalBox::Slot()
  142. .AutoWidth()
  143. .Padding(2, 0, 2, 0)
  144. [
  145. SNew(SBox)
  146. .WidthOverride(300.0f)
  147. .HeightOverride(300.f)
  148. [
  149. ContentBrowserModule.Get().CreateAssetPicker(AssetPickerConfig)
  150. ]
  151. ]
  152. ]
  153. ]
  154. + SVerticalBox::Slot()
  155. .FillHeight(1)
  156. .VAlign(VAlign_Top)
  157. .Padding(4)
  158. [
  159. SNew(SExpandableArea)
  160. .AreaTitle(LOCTEXT("Advanced", "Advanced"))
  161. .InitiallyCollapsed(true)
  162. .BodyContent()
  163. [
  164. SNew(SBorder)
  165. .BorderImage(FAkAppStyle::Get().GetBrush("ToolPanel.GroupBorder"))
  166. .Padding(4.0f)
  167. .Content()
  168. [
  169. SNew(SHorizontalBox)
  170. + SHorizontalBox::Slot()
  171. .AutoWidth()
  172. .Padding(2, 2, 6, 2)
  173. [
  174. SNew(STextBlock)
  175. .Text(LOCTEXT("AkAudioRTPCName", "RTPC Name"))
  176. ]
  177. + SHorizontalBox::Slot()
  178. .AutoWidth()
  179. .Padding(2, 0, 2, 0)
  180. [
  181. SNew(SEditableTextBox)
  182. .HintText(LOCTEXT("AkAudioRTPCNameHint", "Name of the AkAudioRTPC"))
  183. .OnTextCommitted(this, &SCreateAkAudioRTPCSectionDialog::OnEventNameCommitted)
  184. .OnTextChanged(this, &SCreateAkAudioRTPCSectionDialog::OnEventNameCommitted, ETextCommit::Default)
  185. .MinDesiredWidth(200)
  186. .RevertTextOnEscape(true)
  187. ]
  188. ]
  189. ]
  190. ]
  191. + SVerticalBox::Slot()
  192. .AutoHeight()
  193. .HAlign(HAlign_Right)
  194. .VAlign(VAlign_Bottom)
  195. .Padding(8)
  196. [
  197. SNew(SUniformGridPanel)
  198. .SlotPadding(FAkAppStyle::Get().GetMargin("StandardDialog.SlotPadding"))
  199. .MinDesiredSlotWidth(FAkAppStyle::Get().GetFloat("StandardDialog.MinDesiredSlotWidth"))
  200. .MinDesiredSlotHeight(FAkAppStyle::Get().GetFloat("StandardDialog.MinDesiredSlotHeight"))
  201. + SUniformGridPanel::Slot(0, 0)
  202. [
  203. SNew(SButton)
  204. .HAlign(HAlign_Center)
  205. .ContentPadding(FAkAppStyle::Get().GetMargin("StandardDialog.ContentPadding"))
  206. .OnClicked_Lambda([this]() -> FReply { CloseDialog(true); return FReply::Handled(); })
  207. .Text(LOCTEXT("OkButtonLabel", "OK"))
  208. ]
  209. + SUniformGridPanel::Slot(1, 0)
  210. [
  211. SNew(SButton)
  212. .HAlign(HAlign_Center)
  213. .ContentPadding(FAkAppStyle::Get().GetMargin("StandardDialog.ContentPadding"))
  214. .OnClicked_Lambda([this]() -> FReply { CloseDialog(false); return FReply::Handled(); })
  215. .Text(LOCTEXT("CancelButtonLabel", "Cancel"))
  216. ]
  217. ]
  218. ]
  219. ];
  220. }
  221. protected:
  222. void CloseDialog(bool InOkClicked)
  223. {
  224. Options->OkClicked = InOkClicked;
  225. if (Window.IsValid())
  226. {
  227. Window.Pin()->RequestDestroyWindow();
  228. }
  229. }
  230. private:
  231. void OnEventNameCommitted(const FText& InText, ETextCommit::Type InCommitType)
  232. {
  233. Options->RTPCName = InText.ToString();
  234. if (InCommitType == ETextCommit::OnEnter || InCommitType == ETextCommit::OnCleared)
  235. {
  236. CloseDialog(InCommitType == ETextCommit::OnEnter);
  237. }
  238. }
  239. FRTPCSectionCreateDialogOptions* Options;
  240. TWeakPtr<SWindow> Window;
  241. };
  242. bool ConfigureRTPCSection(FRTPCSectionCreateDialogOptions& Options)
  243. {
  244. TSharedRef<SWindow> Window = SNew(SWindow)
  245. .Title(LOCTEXT("CreateAkAudioRTPCSectionDialog", "Enter AkAudioRTPC Name"))
  246. .ClientSize(FVector2D(372, 418))
  247. .SupportsMinimize(false)
  248. .SupportsMaximize(false);
  249. Window->SetContent(SNew(SCreateAkAudioRTPCSectionDialog, Options, Window));
  250. GEditor->EditorAddModalWindow(Window);
  251. return Options.Validate();
  252. }
  253. void FMovieSceneAkAudioRTPCTrackEditor::TryAddAkAudioRTPCTrack(FCreateAkAudioRTPCTrack DoCreateAkAudioRTPCTrack)
  254. {
  255. FRTPCSectionCreateDialogOptions Options;
  256. if (ConfigureRTPCSection(Options))
  257. {
  258. auto FocusedMovieScene = GetFocusedMovieScene();
  259. if (FocusedMovieScene == nullptr)
  260. {
  261. return;
  262. }
  263. const FScopedTransaction Transaction(LOCTEXT("AddAkAudioRTPCTrack_Transaction", "Add AkAudioRTPC Track"));
  264. FocusedMovieScene->Modify();
  265. auto NewTrack = DoCreateAkAudioRTPCTrack.Execute(FocusedMovieScene);
  266. ensure(NewTrack);
  267. auto NewSection = NewTrack->CreateNewSection();
  268. ensure(NewSection);
  269. auto RTPCSection = Cast<UMovieSceneAkAudioRTPCSection>(NewSection);
  270. ensure(RTPCSection);
  271. if (Options.RTPC)
  272. {
  273. RTPCSection->SetRTPC(Options.RTPC);
  274. }
  275. else
  276. {
  277. RTPCSection->SetRTPCName(Options.RTPCName);
  278. }
  279. NewSection->SetRange(TRange<FFrameNumber>::All());
  280. NewTrack->AddSection(*NewSection);
  281. GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded);
  282. }
  283. }
  284. void FMovieSceneAkAudioRTPCTrackEditor::BuildAddTrackMenu(FMenuBuilder& MenuBuilder)
  285. {
  286. auto CreateAkAudioRTPCTrack = [=](UMovieScene* MovieScene)
  287. {
  288. #if UE_5_2_OR_LATER
  289. auto NewTrack = MovieScene->AddTrack<UMovieSceneAkAudioRTPCTrack>();
  290. #else
  291. auto NewTrack = MovieScene->AddMasterTrack<UMovieSceneAkAudioRTPCTrack>();
  292. #endif
  293. if (NewTrack != nullptr)
  294. {
  295. NewTrack->SetIsAMasterTrack(true);
  296. }
  297. return NewTrack;
  298. };
  299. MenuBuilder.AddMenuEntry(
  300. LOCTEXT("AddAkAudioRTPCTrack", "AkAudioRTPC"),
  301. LOCTEXT("AddAkAudioRTPCMasterTrackTooltip", "Adds a master AkAudioRTPC track."),
  302. FSlateIcon(FAkAudioStyle::GetStyleSetName(), "AudiokineticTools.RTPCIcon"),
  303. FUIAction(FExecuteAction::CreateLambda([this, CreateAkAudioRTPCTrack = MoveTemp(CreateAkAudioRTPCTrack)]
  304. {
  305. TryAddAkAudioRTPCTrack(FCreateAkAudioRTPCTrack::CreateLambda(CreateAkAudioRTPCTrack));
  306. }))
  307. );
  308. }
  309. bool FMovieSceneAkAudioRTPCTrackEditor::SupportsSequence(UMovieSceneSequence* InSequence) const
  310. {
  311. #if UE_5_1_OR_LATER
  312. static UClass* LevelSequenceClass = UClass::TryFindTypeSlow<UClass>(TEXT("/Script/LevelSequence.LevelSequence"), EFindFirstObjectOptions::ExactClass);
  313. #else
  314. static UClass* LevelSequenceClass = FindObject<UClass>(ANY_PACKAGE, TEXT("LevelSequence"), true);
  315. #endif
  316. return InSequence != nullptr && LevelSequenceClass != nullptr && InSequence->GetClass()->IsChildOf(LevelSequenceClass);
  317. }
  318. void FMovieSceneAkAudioRTPCTrackEditor::BuildObjectBindingTrackMenu(FMenuBuilder& MenuBuilder, const TArray<FGuid>& ObjectBindings, const UClass* ObjectClass)
  319. {
  320. auto ObjectBinding = ObjectBindings[0];
  321. if (!ObjectClass->IsChildOf(AActor::StaticClass()) && !ObjectClass->IsChildOf(USceneComponent::StaticClass()))
  322. {
  323. return;
  324. }
  325. auto CreateAkAudioRTPCTrack = [=](UMovieScene* MovieScene) { return MovieScene->AddTrack<UMovieSceneAkAudioRTPCTrack>(ObjectBinding); };
  326. MenuBuilder.AddMenuEntry(
  327. LOCTEXT("AddAkAudioRTPCTrack", "AkAudioRTPC"),
  328. LOCTEXT("AddAkAudioRTPCTrackTooltip", "Adds an AkAudioRTPC track."),
  329. FSlateIcon(FAkAudioStyle::GetStyleSetName(), "AudiokineticTools.RTPCIcon"),
  330. FUIAction(FExecuteAction::CreateLambda([this, CreateAkAudioRTPCTrack = MoveTemp(CreateAkAudioRTPCTrack)]
  331. {
  332. TryAddAkAudioRTPCTrack(FCreateAkAudioRTPCTrack::CreateLambda(CreateAkAudioRTPCTrack));
  333. }))
  334. );
  335. }
  336. #undef LOCTEXT_NAMESPACE