Advertisement
Guest User

Epic Games

a guest
Mar 21st, 2018
15,287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 72.60 KB | None | 0 0
  1. // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
  2.  
  3. #include "SSequencer.h"
  4. #include "Engine/Blueprint.h"
  5. #include "MovieScene.h"
  6. #include "Framework/MultiBox/MultiBoxDefs.h"
  7. #include "Widgets/Text/STextBlock.h"
  8. #include "Framework/MultiBox/MultiBoxBuilder.h"
  9. #include "GameFramework/Actor.h"
  10. #include "Misc/FeedbackContext.h"
  11. #include "Modules/ModuleManager.h"
  12. #include "Editor.h"
  13. #include "Widgets/Layout/SBorder.h"
  14. #include "ISequencerEditTool.h"
  15. #include "Layout/WidgetPath.h"
  16. #include "Framework/Application/MenuStack.h"
  17. #include "Framework/Application/SlateApplication.h"
  18. #include "Widgets/Layout/SSpacer.h"
  19. #include "Widgets/Images/SImage.h"
  20. #include "Widgets/Layout/SBox.h"
  21. #include "Widgets/Layout/SGridPanel.h"
  22. #include "Widgets/Layout/SScrollBar.h"
  23. #include "Widgets/Layout/SScrollBorder.h"
  24. #include "Widgets/Input/SComboButton.h"
  25. #include "Widgets/Layout/SSplitter.h"
  26. #include "Widgets/Input/SSpinBox.h"
  27. #include "EditorStyleSet.h"
  28. #include "Engine/Selection.h"
  29. #include "LevelEditorViewport.h"
  30. #include "Widgets/Navigation/SBreadcrumbTrail.h"
  31. #include "SequencerCommands.h"
  32. #include "DisplayNodes/SequencerObjectBindingNode.h"
  33. #include "DisplayNodes/SequencerTrackNode.h"
  34. #include "Widgets/Input/SNumericDropDown.h"
  35. #include "SequencerCommonHelpers.h"
  36. #include "SSequencerCurveEditor.h"
  37. #include "SSequencerCurveEditorToolBar.h"
  38. #include "SSequencerLabelBrowser.h"
  39. #include "ISequencerWidgetsModule.h"
  40. #include "ScopedTransaction.h"
  41. #include "SequencerTimeSliderController.h"
  42. #include "SSequencerSectionOverlay.h"
  43. #include "SSequencerTrackArea.h"
  44. #include "SSequencerTrackOutliner.h"
  45. #include "DragAndDrop/AssetDragDropOp.h"
  46. #include "DragAndDrop/ActorDragDropGraphEdOp.h"
  47. #include "DragAndDrop/ClassDragDropOp.h"
  48. #include "Widgets/Input/SSearchBox.h"
  49. #include "SSequencerTreeView.h"
  50. #include "MovieSceneSequence.h"
  51. #include "SSequencerSplitterOverlay.h"
  52. #include "SequencerHotspots.h"
  53. #include "VirtualTrackArea.h"
  54. #include "Framework/Commands/GenericCommands.h"
  55. #include "SequencerContextMenus.h"
  56. #include "Math/UnitConversion.h"
  57. #include "Widgets/Input/NumericUnitTypeInterface.inl"
  58. #include "SequencerSettings.h"
  59. #include "SSequencerGotoBox.h"
  60. #include "SSequencerTransformBox.h"
  61. #include "SSequencerDebugVisualizer.h"
  62. #include "ISequencerModule.h"
  63. #include "IVREditorModule.h"
  64. #include "EditorFontGlyphs.h"
  65. #include "HAL/PlatformApplicationMisc.h"
  66.  
  67. #define LOCTEXT_NAMESPACE "Sequencer"
  68.  
  69. DECLARE_DELEGATE_RetVal(bool, FOnGetShowFrames)
  70. DECLARE_DELEGATE_RetVal(uint8, FOnGetZeroPad)
  71.  
  72.  
  73. /* Numeric type interface for showing numbers as frames or times */
  74. struct FFramesOrTimeInterface : public TNumericUnitTypeInterface<float>
  75. {
  76. FFramesOrTimeInterface(FOnGetShowFrames InShowFrameNumbers,TSharedPtr<FSequencerTimeSliderController> InController, FOnGetZeroPad InOnGetZeroPad)
  77. : TNumericUnitTypeInterface(EUnit::Seconds)
  78. , ShowFrameNumbers(MoveTemp(InShowFrameNumbers))
  79. , TimeSliderController(MoveTemp(InController))
  80. , OnGetZeroPad(MoveTemp(InOnGetZeroPad))
  81. {}
  82.  
  83. private:
  84. FOnGetShowFrames ShowFrameNumbers;
  85. TSharedPtr<FSequencerTimeSliderController> TimeSliderController;
  86. FOnGetZeroPad OnGetZeroPad;
  87.  
  88. virtual FString ToString(const float& Value) const override
  89. {
  90. if (ShowFrameNumbers.Execute())
  91. {
  92. int32 Frame = TimeSliderController->TimeToFrame(Value);
  93. if (OnGetZeroPad.IsBound())
  94. {
  95. return FString::Printf(*FString::Printf(TEXT("%%0%dd"), OnGetZeroPad.Execute()), Frame);
  96. }
  97. return FString::Printf(TEXT("%d"), Frame);
  98. }
  99.  
  100. return FString::Printf(TEXT("%.2fs"), Value);
  101. }
  102.  
  103. virtual TOptional<float> FromString(const FString& InString, const float& InExistingValue) override
  104. {
  105. bool bShowFrameNumbers = ShowFrameNumbers.IsBound() ? ShowFrameNumbers.Execute() : false;
  106. if (bShowFrameNumbers)
  107. {
  108. // Convert existing value to frames
  109. float ExistingValueInFrames = TimeSliderController->TimeToFrame(InExistingValue);
  110. TOptional<float> Result = TNumericUnitTypeInterface<float>::FromString(InString, ExistingValueInFrames);
  111.  
  112. if (Result.IsSet())
  113. {
  114. int32 NewEndFrame = FMath::RoundToInt(Result.GetValue());
  115. return float(TimeSliderController->FrameToTime(NewEndFrame));
  116. }
  117. }
  118.  
  119. return TNumericUnitTypeInterface::FromString(InString, InExistingValue);
  120. }
  121. };
  122.  
  123.  
  124. /* SSequencer interface
  125. *****************************************************************************/
  126. PRAGMA_DISABLE_OPTIMIZATION
  127. void SSequencer::Construct(const FArguments& InArgs, TSharedRef<FSequencer> InSequencer)
  128. {
  129. SequencerPtr = InSequencer;
  130. bIsActiveTimerRegistered = false;
  131. bUserIsSelecting = false;
  132. CachedClampRange = TRange<float>::Empty();
  133. CachedViewRange = TRange<float>::Empty();
  134.  
  135. Settings = InSequencer->GetSettings();
  136. InSequencer->OnActivateSequence().AddSP(this, &SSequencer::OnSequenceInstanceActivated);
  137.  
  138. ISequencerWidgetsModule& SequencerWidgets = FModuleManager::Get().LoadModuleChecked<ISequencerWidgetsModule>( "SequencerWidgets" );
  139.  
  140. OnPlaybackRangeBeginDrag = InArgs._OnPlaybackRangeBeginDrag;
  141. OnPlaybackRangeEndDrag = InArgs._OnPlaybackRangeEndDrag;
  142. OnSelectionRangeBeginDrag = InArgs._OnSelectionRangeBeginDrag;
  143. OnSelectionRangeEndDrag = InArgs._OnSelectionRangeEndDrag;
  144.  
  145. OnReceivedFocus = InArgs._OnReceivedFocus;
  146.  
  147. FTimeSliderArgs TimeSliderArgs;
  148. {
  149. TimeSliderArgs.ViewRange = InArgs._ViewRange;
  150. TimeSliderArgs.ClampRange = InArgs._ClampRange;
  151. TimeSliderArgs.PlaybackRange = InArgs._PlaybackRange;
  152. TimeSliderArgs.SelectionRange = InArgs._SelectionRange;
  153. TimeSliderArgs.OnPlaybackRangeChanged = InArgs._OnPlaybackRangeChanged;
  154. TimeSliderArgs.OnPlaybackRangeBeginDrag = OnPlaybackRangeBeginDrag;
  155. TimeSliderArgs.OnPlaybackRangeEndDrag = OnPlaybackRangeEndDrag;
  156. TimeSliderArgs.OnSelectionRangeChanged = InArgs._OnSelectionRangeChanged;
  157. TimeSliderArgs.OnSelectionRangeBeginDrag = OnSelectionRangeBeginDrag;
  158. TimeSliderArgs.OnSelectionRangeEndDrag = OnSelectionRangeEndDrag;
  159. TimeSliderArgs.OnViewRangeChanged = InArgs._OnViewRangeChanged;
  160. TimeSliderArgs.OnClampRangeChanged = InArgs._OnClampRangeChanged;
  161. TimeSliderArgs.OnGetNearestKey = InArgs._OnGetNearestKey;
  162. TimeSliderArgs.IsPlaybackRangeLocked = InArgs._IsPlaybackRangeLocked;
  163. TimeSliderArgs.OnTogglePlaybackRangeLocked = InArgs._OnTogglePlaybackRangeLocked;
  164. TimeSliderArgs.TimeSnapInterval = InArgs._TimeSnapInterval;
  165. TimeSliderArgs.ScrubPosition = InArgs._ScrubPosition;
  166. TimeSliderArgs.OnBeginScrubberMovement = InArgs._OnBeginScrubbing;
  167. TimeSliderArgs.OnEndScrubberMovement = InArgs._OnEndScrubbing;
  168. TimeSliderArgs.OnScrubPositionChanged = InArgs._OnScrubPositionChanged;
  169. TimeSliderArgs.PlaybackStatus = InArgs._PlaybackStatus;
  170. TimeSliderArgs.SubSequenceRange = InArgs._SubSequenceRange;
  171.  
  172. TimeSliderArgs.Settings = Settings;
  173. }
  174.  
  175. TimeSliderController = MakeShareable( new FSequencerTimeSliderController( TimeSliderArgs ) );
  176.  
  177. TSharedRef<FSequencerTimeSliderController> TimeSliderControllerRef = TimeSliderController.ToSharedRef();
  178.  
  179. {
  180. auto ShowFrameNumbersDelegate = FOnGetShowFrames::CreateSP(this, &SSequencer::ShowFrameNumbers);
  181. USequencerSettings* SequencerSettings = Settings;
  182. auto GetZeroPad = [=]() -> uint8 {
  183. if (SequencerSettings)
  184. {
  185. return SequencerSettings->GetZeroPadFrames();
  186. }
  187. return 0;
  188. };
  189.  
  190. NumericTypeInterface = MakeShareable( new FFramesOrTimeInterface(ShowFrameNumbersDelegate, TimeSliderControllerRef, FOnGetZeroPad()) );
  191. ZeroPadNumericTypeInterface = MakeShareable( new FFramesOrTimeInterface(ShowFrameNumbersDelegate, TimeSliderControllerRef, FOnGetZeroPad::CreateLambda(GetZeroPad)) );
  192. }
  193.  
  194. bool bMirrorLabels = false;
  195.  
  196. // Create the top and bottom sliders
  197. TopTimeSlider = SequencerWidgets.CreateTimeSlider( TimeSliderControllerRef, bMirrorLabels );
  198. bMirrorLabels = true;
  199. TSharedRef<ITimeSlider> BottomTimeSlider = SequencerWidgets.CreateTimeSlider( TimeSliderControllerRef, TAttribute<EVisibility>(this, &SSequencer::GetBottomTimeSliderVisibility), bMirrorLabels );
  200.  
  201. // Create bottom time range slider
  202. TSharedRef<ITimeSlider> BottomTimeRange = SequencerWidgets.CreateTimeRange(
  203. FTimeRangeArgs(
  204. EShowRange(EShowRange::WorkingRange | EShowRange::ViewRange),
  205. TimeSliderControllerRef,
  206. TAttribute<EVisibility>(this, &SSequencer::GetTimeRangeVisibility),
  207. TAttribute<bool>(this, &SSequencer::ShowFrameNumbers),
  208. ZeroPadNumericTypeInterface.ToSharedRef()
  209. ),
  210. SequencerWidgets.CreateTimeRangeSlider(TimeSliderControllerRef, TAttribute<float>(this, &SSequencer::OnGetTimeSnapInterval))
  211. );
  212.  
  213. OnGetAddMenuContent = InArgs._OnGetAddMenuContent;
  214. AddMenuExtender = InArgs._AddMenuExtender;
  215. ToolbarExtender = InArgs._ToolbarExtender;
  216.  
  217. ColumnFillCoefficients[0] = 0.3f;
  218. ColumnFillCoefficients[1] = 0.7f;
  219.  
  220. TAttribute<float> FillCoefficient_0, FillCoefficient_1;
  221. {
  222. FillCoefficient_0.Bind(TAttribute<float>::FGetter::CreateSP(this, &SSequencer::GetColumnFillCoefficient, 0));
  223. FillCoefficient_1.Bind(TAttribute<float>::FGetter::CreateSP(this, &SSequencer::GetColumnFillCoefficient, 1));
  224. }
  225.  
  226. TSharedRef<SScrollBar> ScrollBar = SNew(SScrollBar)
  227. .Thickness(FVector2D(5.0f, 5.0f));
  228.  
  229. SAssignNew(TrackOutliner, SSequencerTrackOutliner);
  230. SAssignNew(TrackArea, SSequencerTrackArea, TimeSliderControllerRef, InSequencer);
  231. SAssignNew(TreeView, SSequencerTreeView, InSequencer->GetNodeTree(), TrackArea.ToSharedRef())
  232. .ExternalScrollbar(ScrollBar)
  233. .Clipping(EWidgetClipping::ClipToBounds)
  234. .OnGetContextMenuContent(FOnGetContextMenuContent::CreateSP(this, &SSequencer::GetContextMenuContent));
  235.  
  236. SAssignNew(CurveEditor, SSequencerCurveEditor, InSequencer, TimeSliderControllerRef)
  237. .Visibility(this, &SSequencer::GetCurveEditorVisibility)
  238. .OnViewRangeChanged(InArgs._OnViewRangeChanged)
  239. .ViewRange(InArgs._ViewRange);
  240.  
  241. CurveEditor->SetAllowAutoFrame(SequencerPtr.Pin()->GetShowCurveEditor());
  242. TrackArea->SetTreeView(TreeView);
  243.  
  244. const int32 Column0 = 0, Column1 = 1;
  245. const int32 Row0 = 0, Row1 = 1, Row2 = 2, Row3 = 3, Row4 = 4;
  246.  
  247. const float CommonPadding = 3.f;
  248. const FMargin ResizeBarPadding(4.f, 0, 0, 0);
  249.  
  250. ChildSlot
  251. [
  252. SNew(SVerticalBox)
  253.  
  254. + SVerticalBox::Slot()
  255. [
  256. SNew(SSplitter)
  257. .Orientation(Orient_Horizontal)
  258.  
  259. + SSplitter::Slot()
  260. .Value(0.1f)
  261. [
  262. SNew(SBorder)
  263. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  264. .Visibility(this, &SSequencer::HandleLabelBrowserVisibility)
  265. [
  266. // track label browser
  267. SAssignNew(LabelBrowser, SSequencerLabelBrowser, InSequencer)
  268. .OnSelectionChanged(this, &SSequencer::HandleLabelBrowserSelectionChanged)
  269. ]
  270. ]
  271.  
  272. + SSplitter::Slot()
  273. .Value(0.9f)
  274. [
  275. SNew(SOverlay)
  276.  
  277. + SOverlay::Slot()
  278. [
  279. // track area grid panel
  280. SNew( SGridPanel )
  281. .FillRow( 2, 1.f )
  282. .FillColumn( 0, FillCoefficient_0 )
  283. .FillColumn( 1, FillCoefficient_1 )
  284.  
  285. // Toolbar
  286. + SGridPanel::Slot( Column0, Row0, SGridPanel::Layer(10) )
  287. .ColumnSpan(2)
  288. [
  289. SNew(SBorder)
  290. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  291. .Padding(FMargin(CommonPadding, 0.f))
  292. [
  293. SNew(SHorizontalBox)
  294.  
  295. +SHorizontalBox::Slot()
  296. .AutoWidth()
  297. [
  298. MakeToolBar()
  299. ]
  300.  
  301. +SHorizontalBox::Slot()
  302. .AutoWidth()
  303. [
  304. SNew(SSequencerCurveEditorToolBar, InSequencer, CurveEditor->GetCommands())
  305. .Visibility(this, &SSequencer::GetCurveEditorToolBarVisibility)
  306. ]
  307.  
  308. + SHorizontalBox::Slot()
  309. .HAlign(HAlign_Right)
  310. .VAlign(VAlign_Center)
  311. [
  312. SAssignNew(BreadcrumbTrail, SBreadcrumbTrail<FSequencerBreadcrumb>)
  313. .Visibility(this, &SSequencer::GetBreadcrumbTrailVisibility)
  314. .OnCrumbClicked(this, &SSequencer::OnCrumbClicked)
  315. .ButtonStyle(FEditorStyle::Get(), "FlatButton")
  316. .DelimiterImage(FEditorStyle::GetBrush("Sequencer.BreadcrumbIcon"))
  317. .TextStyle(FEditorStyle::Get(), "Sequencer.BreadcrumbText")
  318. ]
  319. ]
  320. ]
  321.  
  322. + SGridPanel::Slot( Column0, Row1 )
  323. [
  324. SNew(SBorder)
  325. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  326. [
  327. SNew(SSpacer)
  328. ]
  329. ]
  330.  
  331. // outliner search box
  332. + SGridPanel::Slot( Column0, Row1, SGridPanel::Layer(10) )
  333. [
  334. SNew(SBorder)
  335. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  336. .Padding(FMargin(CommonPadding*2, CommonPadding))
  337. [
  338. SNew(SHorizontalBox)
  339.  
  340. + SHorizontalBox::Slot()
  341. .AutoWidth()
  342. .VAlign(VAlign_Center)
  343. .Padding(FMargin(0.f, 0.f, CommonPadding, 0.f))
  344. [
  345. MakeAddButton()
  346. ]
  347.  
  348. + SHorizontalBox::Slot()
  349. .VAlign(VAlign_Center)
  350. [
  351. SAssignNew(SearchBox, SSearchBox)
  352. .HintText(LOCTEXT("FilterNodesHint", "Filter"))
  353. .OnTextChanged( this, &SSequencer::OnOutlinerSearchChanged )
  354. ]
  355. ]
  356. ]
  357.  
  358. // main sequencer area
  359. + SGridPanel::Slot( Column0, Row2, SGridPanel::Layer(10) )
  360. .ColumnSpan(2)
  361. [
  362. SNew(SHorizontalBox)
  363.  
  364. + SHorizontalBox::Slot()
  365. [
  366. SNew( SOverlay )
  367.  
  368. + SOverlay::Slot()
  369. [
  370. SNew(SScrollBorder, TreeView.ToSharedRef())
  371. [
  372. SNew(SHorizontalBox)
  373.  
  374. // outliner tree
  375. + SHorizontalBox::Slot()
  376. .FillWidth( FillCoefficient_0 )
  377. [
  378. SNew(SBox)
  379. [
  380. TreeView.ToSharedRef()
  381. ]
  382. ]
  383.  
  384. // track area
  385. + SHorizontalBox::Slot()
  386. .FillWidth( FillCoefficient_1 )
  387. [
  388. SNew(SBox)
  389. .Padding(ResizeBarPadding)
  390. .Visibility(this, &SSequencer::GetTrackAreaVisibility )
  391. .Clipping(EWidgetClipping::ClipToBounds)
  392. [
  393. TrackArea.ToSharedRef()
  394. ]
  395. ]
  396. ]
  397. ]
  398.  
  399. + SOverlay::Slot()
  400. .HAlign( HAlign_Right )
  401. [
  402. ScrollBar
  403. ]
  404. ]
  405.  
  406. + SHorizontalBox::Slot()
  407. .FillWidth( TAttribute<float>( this, &SSequencer::GetOutlinerSpacerFill ) )
  408. [
  409. SNew(SSpacer)
  410. ]
  411. ]
  412.  
  413. // playback buttons
  414. + SGridPanel::Slot( Column0, Row4, SGridPanel::Layer(10) )
  415. [
  416. SNew(SBorder)
  417. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  418. //.BorderBackgroundColor(FLinearColor(.50f, .50f, .50f, 1.0f))
  419. .HAlign(HAlign_Center)
  420. [
  421. SequencerPtr.Pin()->MakeTransportControls(true)
  422. ]
  423. ]
  424.  
  425. // Second column
  426.  
  427. + SGridPanel::Slot( Column1, Row1 )
  428. .Padding(ResizeBarPadding)
  429. .RowSpan(3)
  430. [
  431. SNew(SBorder)
  432. .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
  433. [
  434. SNew(SSpacer)
  435. ]
  436. ]
  437.  
  438. + SGridPanel::Slot( Column1, Row1, SGridPanel::Layer(10) )
  439. .Padding(ResizeBarPadding)
  440. [
  441. SNew( SBorder )
  442. .BorderImage( FEditorStyle::GetBrush("ToolPanel.GroupBorder") )
  443. .BorderBackgroundColor( FLinearColor(.50f, .50f, .50f, 1.0f ) )
  444. .Padding(0)
  445. .Clipping(EWidgetClipping::ClipToBounds)
  446. [
  447. TopTimeSlider.ToSharedRef()
  448. ]
  449. ]
  450.  
  451. // Overlay that draws the tick lines
  452. + SGridPanel::Slot( Column1, Row2, SGridPanel::Layer(10) )
  453. .Padding(ResizeBarPadding)
  454. [
  455. SNew( SSequencerSectionOverlay, TimeSliderControllerRef )
  456. .Visibility( EVisibility::HitTestInvisible )
  457. .DisplayScrubPosition( false )
  458. .DisplayTickLines( true )
  459. .Clipping(EWidgetClipping::ClipToBounds)
  460. ]
  461.  
  462. // Curve editor
  463. + SGridPanel::Slot( Column1, Row2, SGridPanel::Layer(20) )
  464. .Padding(ResizeBarPadding)
  465. [
  466. CurveEditor.ToSharedRef()
  467. ]
  468.  
  469. // Overlay that draws the scrub position
  470. + SGridPanel::Slot( Column1, Row2, SGridPanel::Layer(30) )
  471. .Padding(ResizeBarPadding)
  472. [
  473. SNew( SSequencerSectionOverlay, TimeSliderControllerRef )
  474. .Visibility( EVisibility::HitTestInvisible )
  475. .DisplayScrubPosition( true )
  476. .DisplayTickLines( false )
  477. .PaintPlaybackRangeArgs(this, &SSequencer::GetSectionPlaybackRangeArgs)
  478. .Clipping(EWidgetClipping::ClipToBounds)
  479. ]
  480.  
  481. // Goto box
  482. + SGridPanel::Slot(Column1, Row2, SGridPanel::Layer(40))
  483. .Padding(ResizeBarPadding)
  484. .HAlign(HAlign_Left)
  485. .VAlign(VAlign_Top)
  486. [
  487. SAssignNew(GotoBox, SSequencerGotoBox, SequencerPtr.Pin().ToSharedRef(), *Settings, NumericTypeInterface.ToSharedRef())
  488. ]
  489.  
  490. // Transform box
  491. + SGridPanel::Slot(Column1, Row2, SGridPanel::Layer(50))
  492. .Padding(ResizeBarPadding)
  493. .HAlign(HAlign_Left)
  494. .VAlign(VAlign_Top)
  495. [
  496. SAssignNew(TransformBox, SSequencerTransformBox, SequencerPtr.Pin().ToSharedRef(), *Settings, NumericTypeInterface.ToSharedRef())
  497. ]
  498.  
  499. // debug vis
  500. + SGridPanel::Slot( Column1, Row3, SGridPanel::Layer(10) )
  501. .Padding(ResizeBarPadding)
  502. [
  503. SNew(SSequencerDebugVisualizer, InSequencer)
  504. .ViewRange(FAnimatedRange::WrapAttribute(InArgs._ViewRange))
  505. .Visibility(this, &SSequencer::GetDebugVisualizerVisibility)
  506. ]
  507.  
  508. // play range sliders
  509. + SGridPanel::Slot( Column1, Row4, SGridPanel::Layer(10) )
  510. .Padding(ResizeBarPadding)
  511. [
  512. SNew( SBorder )
  513. .BorderImage( FEditorStyle::GetBrush("ToolPanel.GroupBorder") )
  514. .BorderBackgroundColor( FLinearColor(.50f, .50f, .50f, 1.0f ) )
  515. .Clipping(EWidgetClipping::ClipToBounds)
  516. .Padding(0)
  517. [
  518. SNew( SOverlay )
  519.  
  520. + SOverlay::Slot()
  521. [
  522. BottomTimeSlider
  523. ]
  524.  
  525. + SOverlay::Slot()
  526. [
  527. BottomTimeRange
  528. ]
  529. ]
  530. ]
  531. ]
  532.  
  533. + SOverlay::Slot()
  534. [
  535. // track area virtual splitter overlay
  536. SNew(SSequencerSplitterOverlay)
  537. .Style(FEditorStyle::Get(), "Sequencer.AnimationOutliner.Splitter")
  538. .Visibility(EVisibility::SelfHitTestInvisible)
  539.  
  540. + SSplitter::Slot()
  541. .Value(FillCoefficient_0)
  542. .OnSlotResized(SSplitter::FOnSlotResized::CreateSP(this, &SSequencer::OnColumnFillCoefficientChanged, 0))
  543. [
  544. SNew(SSpacer)
  545. ]
  546.  
  547. + SSplitter::Slot()
  548. .Value(FillCoefficient_1)
  549. .OnSlotResized(SSplitter::FOnSlotResized::CreateSP(this, &SSequencer::OnColumnFillCoefficientChanged, 1))
  550. [
  551. SNew(SSpacer)
  552. ]
  553. ]
  554. ]
  555. ]
  556. ];
  557.  
  558. InSequencer->GetSelection().GetOnKeySelectionChanged().AddSP(this, &SSequencer::HandleKeySelectionChanged);
  559. InSequencer->GetSelection().GetOnSectionSelectionChanged().AddSP(this, &SSequencer::HandleSectionSelectionChanged);
  560. InSequencer->GetSelection().GetOnOutlinerNodeSelectionChanged().AddSP(this, &SSequencer::HandleOutlinerNodeSelectionChanged);
  561.  
  562. ResetBreadcrumbs();
  563. }
  564. PRAGMA_ENABLE_OPTIMIZATION
  565.  
  566. void SSequencer::BindCommands(TSharedRef<FUICommandList> SequencerCommandBindings)
  567. {
  568. auto CanPasteFromHistory = [this]{
  569. if (!HasFocusedDescendants() && !HasKeyboardFocus())
  570. {
  571. return false;
  572. }
  573.  
  574. return SequencerPtr.Pin()->GetClipboardStack().Num() != 0;
  575. };
  576.  
  577. SequencerCommandBindings->MapAction(
  578. FGenericCommands::Get().Paste,
  579. FExecuteAction::CreateSP(this, &SSequencer::OnPaste),
  580. FCanExecuteAction::CreateSP(this, &SSequencer::CanPaste)
  581. );
  582.  
  583. SequencerCommandBindings->MapAction(
  584. FSequencerCommands::Get().PasteFromHistory,
  585. FExecuteAction::CreateSP(this, &SSequencer::PasteFromHistory),
  586. FCanExecuteAction::CreateLambda(CanPasteFromHistory)
  587. );
  588.  
  589. SequencerCommandBindings->MapAction(
  590. FSequencerCommands::Get().ToggleShowGotoBox,
  591. FExecuteAction::CreateLambda([this]{ GotoBox->ToggleVisibility(); })
  592. );
  593.  
  594. SequencerCommandBindings->MapAction(
  595. FSequencerCommands::Get().ToggleShowTransformBox,
  596. FExecuteAction::CreateLambda([this]{ TransformBox->ToggleVisibility(); })
  597. );
  598. }
  599.  
  600. const ISequencerEditTool* SSequencer::GetEditTool() const
  601. {
  602. return TrackArea->GetEditTool();
  603. }
  604.  
  605.  
  606. void SSequencer::NotifyPostChange(const FPropertyChangedEvent& PropertyChangedEvent, FEditPropertyChain* PropertyThatChanged)
  607. {
  608. // @todo sequencer: is this still needed?
  609. }
  610.  
  611.  
  612. /* SSequencer implementation
  613. *****************************************************************************/
  614.  
  615. TSharedRef<INumericTypeInterface<float>> SSequencer::GetNumericTypeInterface()
  616. {
  617. return NumericTypeInterface.ToSharedRef();
  618. }
  619.  
  620. TSharedRef<INumericTypeInterface<float>> SSequencer::GetZeroPadNumericTypeInterface()
  621. {
  622. return ZeroPadNumericTypeInterface.ToSharedRef();
  623. }
  624.  
  625.  
  626. /* SSequencer callbacks
  627. *****************************************************************************/
  628.  
  629. void SSequencer::HandleKeySelectionChanged()
  630. {
  631. }
  632.  
  633.  
  634. void SSequencer::HandleLabelBrowserSelectionChanged(FString NewLabel, ESelectInfo::Type SelectInfo)
  635. {
  636. if (SelectInfo == ESelectInfo::Direct)
  637. {
  638. return;
  639. }
  640.  
  641. if (NewLabel.IsEmpty())
  642. {
  643. SearchBox->SetText(FText::GetEmpty());
  644. }
  645. else
  646. {
  647. SearchBox->SetText(FText::FromString(NewLabel));
  648. }
  649. }
  650.  
  651.  
  652. EVisibility SSequencer::HandleLabelBrowserVisibility() const
  653. {
  654. if (Settings->GetLabelBrowserVisible())
  655. {
  656. return EVisibility::Visible;
  657. }
  658.  
  659. return EVisibility::Collapsed;
  660. }
  661.  
  662.  
  663. void SSequencer::HandleSectionSelectionChanged()
  664. {
  665. }
  666.  
  667.  
  668. void SSequencer::HandleOutlinerNodeSelectionChanged()
  669. {
  670. const TSet<TSharedRef<FSequencerDisplayNode>>& OutlinerSelection = SequencerPtr.Pin()->GetSelection().GetSelectedOutlinerNodes();
  671.  
  672. if ( OutlinerSelection.Num() == 1 )
  673. {
  674. for ( auto& Node : OutlinerSelection )
  675. {
  676. TreeView->RequestScrollIntoView( Node );
  677. break;
  678. }
  679. }
  680. }
  681.  
  682.  
  683. TSharedRef<SWidget> SSequencer::MakeAddButton()
  684. {
  685. if (SequencerPtr.Pin()->IsReadOnly())
  686. {
  687. return SNullWidget::NullWidget;
  688. }
  689.  
  690. return SNew(SComboButton)
  691. .OnGetMenuContent(this, &SSequencer::MakeAddMenu)
  692. .ButtonStyle(FEditorStyle::Get(), "FlatButton.Success")
  693. .ContentPadding(FMargin(2.0f, 1.0f))
  694. .HasDownArrow(false)
  695. .ButtonContent()
  696. [
  697. SNew(SHorizontalBox)
  698.  
  699. + SHorizontalBox::Slot()
  700. .VAlign(VAlign_Center)
  701. .AutoWidth()
  702. [
  703. SNew(STextBlock)
  704. .TextStyle(FEditorStyle::Get(), "NormalText.Important")
  705. .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.10"))
  706. .Text(FEditorFontGlyphs::Plus)
  707. ]
  708.  
  709. + SHorizontalBox::Slot()
  710. .AutoWidth()
  711. .Padding(4, 0, 0, 0)
  712. [
  713. SNew(STextBlock)
  714. .TextStyle(FEditorStyle::Get(), "NormalText.Important")
  715. .Text(LOCTEXT("Track", "Track"))
  716. ]
  717.  
  718. + SHorizontalBox::Slot()
  719. .VAlign(VAlign_Center)
  720. .AutoWidth()
  721. .Padding(4, 0, 0, 0)
  722. [
  723. SNew(STextBlock)
  724. .TextStyle(FEditorStyle::Get(), "NormalText.Important")
  725. .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.10"))
  726. .Text(FEditorFontGlyphs::Caret_Down)
  727. ]
  728. ];
  729. }
  730.  
  731. TSharedRef<SWidget> SSequencer::MakeToolBar()
  732. {
  733. ISequencerModule& SequencerModule = FModuleManager::GetModuleChecked<ISequencerModule>("Sequencer");
  734. TSharedPtr<FExtender> Extender = SequencerModule.GetToolBarExtensibilityManager()->GetAllExtenders();
  735. if (ToolbarExtender.IsValid())
  736. {
  737. Extender = FExtender::Combine({ Extender, ToolbarExtender });
  738. }
  739.  
  740. FToolBarBuilder ToolBarBuilder( SequencerPtr.Pin()->GetCommandBindings(), FMultiBoxCustomization::None, Extender, Orient_Horizontal, true);
  741.  
  742. const bool bIsReadOnly = SequencerPtr.Pin()->IsReadOnly();
  743.  
  744. ToolBarBuilder.BeginSection("Base Commands");
  745. {
  746. // General
  747. if (SequencerPtr.Pin()->IsLevelEditorSequencer())
  748. {
  749. ToolBarBuilder.AddToolBarButton(
  750. FUIAction(FExecuteAction::CreateSP(this, &SSequencer::OnSaveMovieSceneClicked)),
  751. NAME_None,
  752. LOCTEXT("SaveDirtyPackages", "Save"),
  753. LOCTEXT("SaveDirtyPackagesTooltip", "Saves the current sequence"),
  754. FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.Save")
  755. );
  756.  
  757. ToolBarBuilder.AddToolBarButton(
  758. FUIAction(FExecuteAction::CreateSP(this, &SSequencer::OnSaveMovieSceneAsClicked)),
  759. NAME_None,
  760. LOCTEXT("SaveAs", "Save As"),
  761. LOCTEXT("SaveAsTooltip", "Saves the current sequence under a different name"),
  762. FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.SaveAs")
  763. );
  764.  
  765. //ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().DiscardChanges );
  766. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().FindInContentBrowser );
  767. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().CreateCamera );
  768. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().RenderMovie );
  769. ToolBarBuilder.AddSeparator("Level Sequence Separator");
  770. }
  771.  
  772. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().RestoreAnimatedState );
  773.  
  774. ToolBarBuilder.AddComboButton(
  775. FUIAction(),
  776. FOnGetContent::CreateSP(this, &SSequencer::MakeGeneralMenu),
  777. LOCTEXT("GeneralOptions", "General Options"),
  778. LOCTEXT("GeneralOptionsToolTip", "General Options"),
  779. FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.GeneralOptions")
  780. );
  781.  
  782. if (!bIsReadOnly)
  783. {
  784. ToolBarBuilder.AddComboButton(
  785. FUIAction(),
  786. FOnGetContent::CreateSP(this, &SSequencer::MakePlaybackMenu),
  787. LOCTEXT("PlaybackOptions", "Playback Options"),
  788. LOCTEXT("PlaybackOptionsToolTip", "Playback Options"),
  789. FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.PlaybackOptions")
  790. );
  791.  
  792. ToolBarBuilder.AddComboButton(
  793. FUIAction(),
  794. FOnGetContent::CreateSP(this, &SSequencer::MakeSelectEditMenu),
  795. LOCTEXT("SelectEditOptions", "Select/Edit Options"),
  796. LOCTEXT("SelectEditOptionsToolTip", "Select/Edit Options"),
  797. FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.SelectEditOptions")
  798. );
  799.  
  800. ToolBarBuilder.AddSeparator();
  801.  
  802. if( SequencerPtr.Pin()->IsLevelEditorSequencer() )
  803. {
  804. TAttribute<FSlateIcon> KeyAllIcon;
  805. KeyAllIcon.Bind(TAttribute<FSlateIcon>::FGetter::CreateLambda([&]{
  806. static FSlateIcon KeyAllEnabledIcon(FEditorStyle::GetStyleSetName(), "Sequencer.KeyAllEnabled");
  807. static FSlateIcon KeyAllDisabledIcon(FEditorStyle::GetStyleSetName(), "Sequencer.KeyAllDisabled");
  808.  
  809. return SequencerPtr.Pin()->GetKeyAllEnabled() ? KeyAllEnabledIcon : KeyAllDisabledIcon;
  810. }));
  811.  
  812. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().ToggleKeyAllEnabled, NAME_None, TAttribute<FText>(), TAttribute<FText>(), KeyAllIcon );
  813. }
  814.  
  815. if (IVREditorModule::Get().IsVREditorModeActive())
  816. {
  817. TAttribute<FSlateIcon> AutoChangeModeIcon;
  818. AutoChangeModeIcon.Bind(TAttribute<FSlateIcon>::FGetter::CreateLambda( [&] {
  819. switch ( SequencerPtr.Pin()->GetAutoChangeMode() )
  820. {
  821. case EAutoChangeMode::AutoKey:
  822. return FSequencerCommands::Get().SetAutoKey->GetIcon();
  823. case EAutoChangeMode::AutoTrack:
  824. return FSequencerCommands::Get().SetAutoTrack->GetIcon();
  825. case EAutoChangeMode::All:
  826. return FSequencerCommands::Get().SetAutoChangeAll->GetIcon();
  827. default: // EAutoChangeMode::None
  828. return FSequencerCommands::Get().SetAutoChangeNone->GetIcon();
  829. }
  830. } ) );
  831.  
  832. TAttribute<FText> AutoChangeModeToolTip;
  833. AutoChangeModeToolTip.Bind( TAttribute<FText>::FGetter::CreateLambda( [&] {
  834. switch ( SequencerPtr.Pin()->GetAutoChangeMode() )
  835. {
  836. case EAutoChangeMode::AutoKey:
  837. return FSequencerCommands::Get().SetAutoKey->GetDescription();
  838. case EAutoChangeMode::AutoTrack:
  839. return FSequencerCommands::Get().SetAutoTrack->GetDescription();
  840. case EAutoChangeMode::All:
  841. return FSequencerCommands::Get().SetAutoChangeAll->GetDescription();
  842. default: // EAutoChangeMode::None
  843. return FSequencerCommands::Get().SetAutoChangeNone->GetDescription();
  844. }
  845. } ) );
  846.  
  847. ToolBarBuilder.AddComboButton(
  848. FUIAction(),
  849. FOnGetContent::CreateSP(this, &SSequencer::MakeAutoChangeMenu),
  850. LOCTEXT("AutoChangeMode", "Auto-Change Mode"),
  851. AutoChangeModeToolTip,
  852. AutoChangeModeIcon);
  853. }
  854. else
  855. {
  856. TAttribute<FSlateIcon> AutoKeyIcon;
  857. AutoKeyIcon.Bind(TAttribute<FSlateIcon>::FGetter::CreateLambda([&]{
  858. static FSlateIcon AutoKeyEnabledIcon(FEditorStyle::GetStyleSetName(), "Sequencer.SetAutoKey");
  859. static FSlateIcon AutoKeyDisabledIcon(FEditorStyle::GetStyleSetName(), "Sequencer.SetAutoChangeNone");
  860.  
  861. return SequencerPtr.Pin()->GetAutoChangeMode() == EAutoChangeMode::None ? AutoKeyDisabledIcon : AutoKeyEnabledIcon;
  862. }));
  863.  
  864. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().ToggleAutoKeyEnabled, NAME_None, TAttribute<FText>(), TAttribute<FText>(), AutoKeyIcon );
  865. }
  866.  
  867. if( SequencerPtr.Pin()->IsLevelEditorSequencer() )
  868. {
  869. TAttribute<FSlateIcon> AllowEditsModeIcon;
  870. AllowEditsModeIcon.Bind(TAttribute<FSlateIcon>::FGetter::CreateLambda( [&] {
  871. switch ( SequencerPtr.Pin()->GetAllowEditsMode() )
  872. {
  873. case EAllowEditsMode::AllEdits:
  874. return FSequencerCommands::Get().AllowAllEdits->GetIcon();
  875. case EAllowEditsMode::AllowSequencerEditsOnly:
  876. return FSequencerCommands::Get().AllowSequencerEditsOnly->GetIcon();
  877. default: // EAllowEditsMode::AllowLevelEditsOnly
  878. return FSequencerCommands::Get().AllowLevelEditsOnly->GetIcon();
  879. }
  880. } ) );
  881.  
  882. TAttribute<FText> AllowEditsModeToolTip;
  883. AllowEditsModeToolTip.Bind( TAttribute<FText>::FGetter::CreateLambda( [&] {
  884. switch ( SequencerPtr.Pin()->GetAllowEditsMode() )
  885. {
  886. case EAllowEditsMode::AllEdits:
  887. return FSequencerCommands::Get().AllowAllEdits->GetDescription();
  888. case EAllowEditsMode::AllowSequencerEditsOnly:
  889. return FSequencerCommands::Get().AllowSequencerEditsOnly->GetDescription();
  890. default: // EAllowEditsMode::AllowLevelEditsOnly
  891. return FSequencerCommands::Get().AllowLevelEditsOnly->GetDescription();
  892. }
  893. } ) );
  894.  
  895. ToolBarBuilder.AddComboButton(
  896. FUIAction(),
  897. FOnGetContent::CreateSP(this, &SSequencer::MakeAllowEditsMenu),
  898. LOCTEXT("AllowMode", "Allow Edits"),
  899. AllowEditsModeToolTip,
  900. AllowEditsModeIcon);
  901. }
  902. }
  903. }
  904. ToolBarBuilder.EndSection();
  905.  
  906.  
  907. ToolBarBuilder.BeginSection("Snapping");
  908. {
  909. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().ToggleIsSnapEnabled, NAME_None, TAttribute<FText>( FText::GetEmpty() ) );
  910.  
  911. ToolBarBuilder.AddComboButton(
  912. FUIAction(),
  913. FOnGetContent::CreateSP( this, &SSequencer::MakeSnapMenu ),
  914. LOCTEXT( "SnapOptions", "Options" ),
  915. LOCTEXT( "SnapOptionsToolTip", "Snapping Options" ),
  916. TAttribute<FSlateIcon>(),
  917. true );
  918.  
  919. ToolBarBuilder.AddSeparator();
  920. ToolBarBuilder.AddWidget(
  921. SNew( SImage )
  922. .Image(FEditorStyle::GetBrush("Sequencer.Time.Small")) );
  923.  
  924. ToolBarBuilder.AddWidget(
  925. SNew( SBox )
  926. .VAlign( VAlign_Center )
  927. [
  928. SNew( SNumericDropDown<float> )
  929. .DropDownValues( SequencerSnapValues::GetTimeSnapValues() )
  930. .bShowNamedValue(true)
  931. .ToolTipText( LOCTEXT( "TimeSnappingIntervalToolTip", "Time snapping interval" ) )
  932. .Value( this, &SSequencer::OnGetTimeSnapInterval )
  933. .OnValueChanged( this, &SSequencer::OnTimeSnapIntervalChanged )
  934. ]);
  935. }
  936. ToolBarBuilder.EndSection();
  937.  
  938. if (!bIsReadOnly)
  939. {
  940. // Curve editor doesn't have any notion of read-only at the moment
  941. ToolBarBuilder.BeginSection("Curve Editor");
  942. {
  943. ToolBarBuilder.AddToolBarButton( FSequencerCommands::Get().ToggleShowCurveEditor );
  944. }
  945. ToolBarBuilder.EndSection();
  946. }
  947.  
  948. return ToolBarBuilder.MakeWidget();
  949. }
  950.  
  951.  
  952. void SSequencer::GetContextMenuContent(FMenuBuilder& MenuBuilder)
  953. {
  954. // let toolkits populate the menu
  955. MenuBuilder.BeginSection("MainMenu");
  956. OnGetAddMenuContent.ExecuteIfBound(MenuBuilder, SequencerPtr.Pin().ToSharedRef());
  957. MenuBuilder.EndSection();
  958.  
  959. // let track editors & object bindings populate the menu
  960. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  961.  
  962. // Always create the section so that we afford extension
  963. MenuBuilder.BeginSection("ObjectBindings");
  964. if (Sequencer.IsValid())
  965. {
  966. Sequencer->BuildAddObjectBindingsMenu(MenuBuilder);
  967. }
  968. MenuBuilder.EndSection();
  969.  
  970. // Always create the section so that we afford extension
  971. MenuBuilder.BeginSection("AddTracks");
  972. if (Sequencer.IsValid())
  973. {
  974. Sequencer->BuildAddTrackMenu(MenuBuilder);
  975. }
  976. MenuBuilder.EndSection();
  977. }
  978.  
  979.  
  980. TSharedRef<SWidget> SSequencer::MakeAddMenu()
  981. {
  982. FMenuBuilder MenuBuilder(true, nullptr, AddMenuExtender);
  983. {
  984. GetContextMenuContent(MenuBuilder);
  985. }
  986.  
  987. return MenuBuilder.MakeWidget();
  988. }
  989.  
  990. TSharedRef<SWidget> SSequencer::MakeGeneralMenu()
  991. {
  992. FMenuBuilder MenuBuilder( true, SequencerPtr.Pin()->GetCommandBindings() );
  993. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  994.  
  995. // view options
  996. MenuBuilder.BeginSection( "ViewOptions", LOCTEXT( "ViewMenuHeader", "View" ) );
  997. {
  998. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleLabelBrowser );
  999. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleCombinedKeyframes );
  1000. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleChannelColors );
  1001. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleShowPreAndPostRoll );
  1002.  
  1003. if (Sequencer->IsLevelEditorSequencer())
  1004. {
  1005. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().FindInContentBrowser );
  1006. }
  1007.  
  1008. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleExpandCollapseNodes );
  1009. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleExpandCollapseNodesAndDescendants );
  1010. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ExpandAllNodesAndDescendants );
  1011. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().CollapseAllNodesAndDescendants );
  1012. }
  1013. MenuBuilder.EndSection();
  1014.  
  1015. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().ToggleShowGotoBox);
  1016.  
  1017. MenuBuilder.AddMenuSeparator();
  1018.  
  1019. if (SequencerPtr.Pin()->IsLevelEditorSequencer())
  1020. {
  1021. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().FixActorReferences);
  1022. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().RebindPossessableReferences);
  1023. }
  1024. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().FixFrameTiming);
  1025.  
  1026. if ( SequencerPtr.Pin()->IsLevelEditorSequencer() )
  1027. {
  1028. MenuBuilder.AddMenuSeparator();
  1029.  
  1030. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ImportFBX );
  1031. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ExportFBX );
  1032. }
  1033.  
  1034. return MenuBuilder.MakeWidget();
  1035. }
  1036.  
  1037. TSharedRef<SWidget> SSequencer::MakePlaybackMenu()
  1038. {
  1039. FMenuBuilder MenuBuilder( true, SequencerPtr.Pin()->GetCommandBindings() );
  1040.  
  1041. // playback range options
  1042. MenuBuilder.BeginSection("PlaybackThisSequence", LOCTEXT("PlaybackThisSequenceHeader", "Playback - This Sequence"));
  1043. {
  1044. // Menu entry for the start position
  1045. auto OnStartChanged = [=](float NewValue){
  1046. float Upper = SequencerPtr.Pin()->GetPlaybackRange().GetUpperBoundValue();
  1047. SequencerPtr.Pin()->SetPlaybackRange(TRange<float>(FMath::Min(NewValue, Upper), Upper));
  1048. };
  1049.  
  1050. MenuBuilder.AddWidget(
  1051. SNew(SHorizontalBox)
  1052. + SHorizontalBox::Slot()
  1053. [
  1054. SNew(SSpacer)
  1055. ]
  1056. + SHorizontalBox::Slot()
  1057. .AutoWidth()
  1058. [
  1059. SNew(SSpinBox<float>)
  1060. .TypeInterface(NumericTypeInterface)
  1061. .IsEnabled_Lambda([=]() {
  1062. return !SequencerPtr.Pin()->IsPlaybackRangeLocked();
  1063. })
  1064. .Style(&FEditorStyle::GetWidgetStyle<FSpinBoxStyle>("Sequencer.HyperlinkSpinBox"))
  1065. .OnValueCommitted_Lambda([=](float Value, ETextCommit::Type){ OnStartChanged(Value); })
  1066. .OnValueChanged_Lambda(OnStartChanged)
  1067. .OnBeginSliderMovement(OnPlaybackRangeBeginDrag)
  1068. .OnEndSliderMovement_Lambda([=](float Value){ OnStartChanged(Value); OnPlaybackRangeEndDrag.ExecuteIfBound(); })
  1069. .MinValue_Lambda([=]() -> float {
  1070. return SequencerPtr.Pin()->GetClampRange().GetLowerBoundValue();
  1071. })
  1072. .MaxValue_Lambda([=]() -> float {
  1073. return SequencerPtr.Pin()->GetPlaybackRange().GetUpperBoundValue();
  1074. })
  1075. .Value_Lambda([=]() -> float {
  1076. return SequencerPtr.Pin()->GetPlaybackRange().GetLowerBoundValue();
  1077. })
  1078. ],
  1079. LOCTEXT("PlaybackStartLabel", "Start"));
  1080.  
  1081. // Menu entry for the end position
  1082. auto OnEndChanged = [=](float NewValue){
  1083. float Lower = SequencerPtr.Pin()->GetPlaybackRange().GetLowerBoundValue();
  1084. SequencerPtr.Pin()->SetPlaybackRange(TRange<float>(Lower, FMath::Max(NewValue, Lower)));
  1085. };
  1086.  
  1087. MenuBuilder.AddWidget(
  1088. SNew(SHorizontalBox)
  1089. + SHorizontalBox::Slot()
  1090. [
  1091. SNew(SSpacer)
  1092. ]
  1093. + SHorizontalBox::Slot()
  1094. .AutoWidth()
  1095. [
  1096. SNew(SSpinBox<float>)
  1097. .TypeInterface(NumericTypeInterface)
  1098. .IsEnabled_Lambda([=]() {
  1099. return !SequencerPtr.Pin()->IsPlaybackRangeLocked();
  1100. })
  1101. .Style(&FEditorStyle::GetWidgetStyle<FSpinBoxStyle>("Sequencer.HyperlinkSpinBox"))
  1102. .OnValueCommitted_Lambda([=](float Value, ETextCommit::Type){ OnEndChanged(Value); })
  1103. .OnValueChanged_Lambda(OnEndChanged)
  1104. .OnBeginSliderMovement(OnPlaybackRangeBeginDrag)
  1105. .OnEndSliderMovement_Lambda([=](float Value){ OnEndChanged(Value); OnPlaybackRangeEndDrag.ExecuteIfBound(); })
  1106. .MinValue_Lambda([=]() -> float {
  1107. return SequencerPtr.Pin()->GetPlaybackRange().GetLowerBoundValue();
  1108. })
  1109. .MaxValue_Lambda([=]() -> float {
  1110. return SequencerPtr.Pin()->GetClampRange().GetUpperBoundValue();
  1111. })
  1112. .Value_Lambda([=]() -> float {
  1113. return SequencerPtr.Pin()->GetPlaybackRange().GetUpperBoundValue();
  1114. })
  1115. ],
  1116. LOCTEXT("PlaybackStartEnd", "End"));
  1117.  
  1118. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().TogglePlaybackRangeLocked );
  1119. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleForceFixedFrameIntervalPlayback );
  1120.  
  1121. if (SequencerPtr.Pin()->IsLevelEditorSequencer())
  1122. {
  1123. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleRerunConstructionScripts );
  1124. }
  1125. }
  1126. MenuBuilder.EndSection();
  1127.  
  1128. MenuBuilder.BeginSection( "PlaybackAllSequences", LOCTEXT( "PlaybackRangeAllSequencesHeader", "Playback Range - All Sequences" ) );
  1129. {
  1130. if (SequencerPtr.Pin()->IsLevelEditorSequencer())
  1131. {
  1132. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleEvaluateSubSequencesInIsolation );
  1133. }
  1134.  
  1135. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleKeepCursorInPlaybackRangeWhileScrubbing );
  1136. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleKeepCursorInPlaybackRange );
  1137. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleKeepPlaybackRangeInSectionBounds );
  1138. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleLinkCurveEditorTimeRange );
  1139.  
  1140. // Menu entry for zero padding
  1141. auto OnZeroPadChanged = [=](uint8 NewValue){
  1142. Settings->SetZeroPadFrames(NewValue);
  1143. };
  1144.  
  1145. MenuBuilder.AddWidget(
  1146. SNew(SHorizontalBox)
  1147. + SHorizontalBox::Slot()
  1148. [
  1149. SNew(SSpacer)
  1150. ]
  1151. + SHorizontalBox::Slot()
  1152. .AutoWidth()
  1153. [
  1154. SNew(SSpinBox<uint8>)
  1155. .Style(&FEditorStyle::GetWidgetStyle<FSpinBoxStyle>("Sequencer.HyperlinkSpinBox"))
  1156. .OnValueCommitted_Lambda([=](uint8 Value, ETextCommit::Type){ OnZeroPadChanged(Value); })
  1157. .OnValueChanged_Lambda(OnZeroPadChanged)
  1158. .MinValue(0)
  1159. .MaxValue(8)
  1160. .Value_Lambda([=]() -> uint8 {
  1161. return Settings->GetZeroPadFrames();
  1162. })
  1163. ],
  1164. LOCTEXT("ZeroPaddingText", "Zero Pad Frame Numbers"));
  1165. }
  1166. MenuBuilder.EndSection();
  1167.  
  1168. return MenuBuilder.MakeWidget();
  1169. }
  1170.  
  1171. TSharedRef<SWidget> SSequencer::MakeSelectEditMenu()
  1172. {
  1173. FMenuBuilder MenuBuilder( true, SequencerPtr.Pin()->GetCommandBindings() );
  1174. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1175.  
  1176. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().ToggleShowTransformBox);
  1177.  
  1178. // selection range options
  1179. MenuBuilder.BeginSection("SelectionRange", LOCTEXT("SelectionRangeHeader", "Selection Range"));
  1180. {
  1181. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetSelectionRangeStart);
  1182. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetSelectionRangeEnd);
  1183. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().ResetSelectionRange);
  1184. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SelectKeysInSelectionRange);
  1185. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SelectSectionsInSelectionRange);
  1186. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SelectAllInSelectionRange);
  1187. }
  1188. MenuBuilder.EndSection();
  1189.  
  1190. return MenuBuilder.MakeWidget();
  1191. }
  1192.  
  1193.  
  1194. TSharedRef<SWidget> SSequencer::MakeSnapMenu()
  1195. {
  1196. FMenuBuilder MenuBuilder( false, SequencerPtr.Pin()->GetCommandBindings() );
  1197.  
  1198. MenuBuilder.BeginSection("FramesRanges", LOCTEXT("SnappingMenuFrameRangesHeader", "Frame Ranges") );
  1199. {
  1200. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleAutoScroll );
  1201. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleShowFrameNumbers );
  1202. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleShowRangeSlider );
  1203. }
  1204. MenuBuilder.EndSection();
  1205.  
  1206. MenuBuilder.BeginSection( "KeySnapping", LOCTEXT( "SnappingMenuKeyHeader", "Key Snapping" ) );
  1207. {
  1208. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapKeyTimesToInterval );
  1209. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapKeyTimesToKeys );
  1210. }
  1211. MenuBuilder.EndSection();
  1212.  
  1213. MenuBuilder.BeginSection( "SectionSnapping", LOCTEXT( "SnappingMenuSectionHeader", "Section Snapping" ) );
  1214. {
  1215. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapSectionTimesToInterval );
  1216. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapSectionTimesToSections );
  1217. }
  1218. MenuBuilder.EndSection();
  1219.  
  1220. MenuBuilder.BeginSection( "PlayTimeSnapping", LOCTEXT( "SnappingMenuPlayTimeHeader", "Play Time Snapping" ) );
  1221. {
  1222. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapPlayTimeToInterval );
  1223. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapPlayTimeToKeys );
  1224. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapPlayTimeToPressedKey );
  1225. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapPlayTimeToDraggedKey );
  1226. }
  1227. MenuBuilder.EndSection();
  1228.  
  1229. MenuBuilder.BeginSection( "CurveSnapping", LOCTEXT( "SnappingMenuCurveHeader", "Curve Snapping" ) );
  1230. {
  1231. MenuBuilder.AddMenuEntry( FSequencerCommands::Get().ToggleSnapCurveValueToInterval );
  1232. }
  1233. MenuBuilder.EndSection();
  1234.  
  1235. return MenuBuilder.MakeWidget();
  1236. }
  1237.  
  1238.  
  1239. TSharedRef<SWidget> SSequencer::MakeAutoChangeMenu()
  1240. {
  1241. FMenuBuilder MenuBuilder(false, SequencerPtr.Pin()->GetCommandBindings());
  1242.  
  1243. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetAutoKey);
  1244.  
  1245. if (SequencerPtr.Pin()->IsLevelEditorSequencer())
  1246. {
  1247. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetAutoTrack);
  1248. }
  1249.  
  1250. if (IVREditorModule::Get().IsVREditorModeActive())
  1251. {
  1252. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetAutoChangeAll);
  1253. }
  1254.  
  1255. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().SetAutoChangeNone);
  1256.  
  1257. return MenuBuilder.MakeWidget();
  1258.  
  1259. }
  1260.  
  1261. TSharedRef<SWidget> SSequencer::MakeAllowEditsMenu()
  1262. {
  1263. FMenuBuilder MenuBuilder(false, SequencerPtr.Pin()->GetCommandBindings());
  1264.  
  1265. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().AllowAllEdits);
  1266. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().AllowSequencerEditsOnly);
  1267. MenuBuilder.AddMenuEntry(FSequencerCommands::Get().AllowLevelEditsOnly);
  1268.  
  1269. return MenuBuilder.MakeWidget();
  1270.  
  1271. }
  1272.  
  1273. TSharedRef<SWidget> SSequencer::MakeTimeRange(const TSharedRef<SWidget>& InnerContent, bool bShowWorkingRange, bool bShowViewRange, bool bShowPlaybackRange)
  1274. {
  1275. ISequencerWidgetsModule& SequencerWidgets = FModuleManager::Get().LoadModuleChecked<ISequencerWidgetsModule>( "SequencerWidgets" );
  1276.  
  1277. EShowRange ShowRange = EShowRange::None;
  1278. if (bShowWorkingRange)
  1279. {
  1280. ShowRange |= EShowRange::WorkingRange;
  1281. }
  1282. if (bShowViewRange)
  1283. {
  1284. ShowRange |= EShowRange::ViewRange;
  1285. }
  1286. if (bShowPlaybackRange)
  1287. {
  1288. ShowRange |= EShowRange::PlaybackRange;
  1289. }
  1290.  
  1291. FTimeRangeArgs Args(
  1292. ShowRange,
  1293. TimeSliderController.ToSharedRef(),
  1294. EVisibility::Visible,
  1295. TAttribute<bool>(this, &SSequencer::ShowFrameNumbers),
  1296. GetZeroPadNumericTypeInterface()
  1297. );
  1298. return SequencerWidgets.CreateTimeRange(Args, InnerContent);
  1299. }
  1300.  
  1301. TSharedPtr<ITimeSlider> SSequencer::GetTopTimeSliderWidget() const
  1302. {
  1303. return TopTimeSlider;
  1304. }
  1305.  
  1306. SSequencer::~SSequencer()
  1307. {
  1308. USelection::SelectionChangedEvent.RemoveAll(this);
  1309. }
  1310.  
  1311.  
  1312. void SSequencer::RegisterActiveTimerForPlayback()
  1313. {
  1314. if (!bIsActiveTimerRegistered)
  1315. {
  1316. bIsActiveTimerRegistered = true;
  1317. RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SSequencer::EnsureSlateTickDuringPlayback));
  1318. }
  1319. }
  1320.  
  1321.  
  1322. EActiveTimerReturnType SSequencer::EnsureSlateTickDuringPlayback(double InCurrentTime, float InDeltaTime)
  1323. {
  1324. if (SequencerPtr.IsValid())
  1325. {
  1326. auto PlaybackStatus = SequencerPtr.Pin()->GetPlaybackStatus();
  1327. if (PlaybackStatus == EMovieScenePlayerStatus::Playing || PlaybackStatus == EMovieScenePlayerStatus::Recording || PlaybackStatus == EMovieScenePlayerStatus::Scrubbing)
  1328. {
  1329. return EActiveTimerReturnType::Continue;
  1330. }
  1331. }
  1332.  
  1333. bIsActiveTimerRegistered = false;
  1334. return EActiveTimerReturnType::Stop;
  1335. }
  1336.  
  1337.  
  1338. void RestoreSelectionState(const TArray<TSharedRef<FSequencerDisplayNode>>& DisplayNodes, TSet<FString>& SelectedPathNames, FSequencerSelection& SequencerSelection)
  1339. {
  1340. for (TSharedRef<FSequencerDisplayNode> DisplayNode : DisplayNodes)
  1341. {
  1342. if (SelectedPathNames.Contains(DisplayNode->GetPathName()))
  1343. {
  1344. SequencerSelection.AddToSelection(DisplayNode);
  1345. }
  1346.  
  1347. RestoreSelectionState(DisplayNode->GetChildNodes(), SelectedPathNames, SequencerSelection);
  1348. }
  1349. }
  1350.  
  1351. void RestoreSectionSelection(const TSet<TWeakObjectPtr<UMovieSceneSection> >& SelectedSections, FSequencerSelection& Selection)
  1352. {
  1353. for (auto Section : SelectedSections)
  1354. {
  1355. if (Section.IsValid())
  1356. {
  1357. Selection.AddToSelection(Section.Get());
  1358. }
  1359. }
  1360. }
  1361.  
  1362. /** Attempt to restore key selection from the specified set of selected keys. Only works for key areas that have the same key handles as their expired counterparts (this is generally the case) */
  1363. void RestoreKeySelection(const TSet<FSequencerSelectedKey>& OldKeys, FSequencerSelection& Selection, FSequencerNodeTree& Tree)
  1364. {
  1365. // Store a map of previous section/key area pairs to their current pairs
  1366. TMap<FSequencerSelectedKey, FSequencerSelectedKey> OldToNew;
  1367.  
  1368. for (FSequencerSelectedKey OldKeyTemplate : OldKeys)
  1369. {
  1370. // Cache of this key's handle for assignment to the new handle
  1371. TOptional<FKeyHandle> OldKeyHandle = OldKeyTemplate.KeyHandle;
  1372. // Reset the key handle so we can reuse cached section/key area pairs
  1373. OldKeyTemplate.KeyHandle.Reset();
  1374.  
  1375. FSequencerSelectedKey NewKeyTemplate = OldToNew.FindRef(OldKeyTemplate);
  1376. if (!NewKeyTemplate.Section)
  1377. {
  1378. // Not cached yet, so we'll need to search for it
  1379. for (const TSharedRef<FSequencerDisplayNode>& RootNode : Tree.GetRootNodes())
  1380. {
  1381. auto FindKeyArea =
  1382. [&](FSequencerDisplayNode& InNode)
  1383. {
  1384. FSequencerSectionKeyAreaNode* KeyAreaNode = nullptr;
  1385.  
  1386. if (InNode.GetType() == ESequencerNode::KeyArea)
  1387. {
  1388. KeyAreaNode = static_cast<FSequencerSectionKeyAreaNode*>(&InNode);
  1389. }
  1390. else if (InNode.GetType() == ESequencerNode::Track)
  1391. {
  1392. KeyAreaNode = static_cast<FSequencerTrackNode&>(InNode).GetTopLevelKeyNode().Get();
  1393. }
  1394.  
  1395. if (KeyAreaNode)
  1396. {
  1397. for (const TSharedRef<IKeyArea>& KeyArea : KeyAreaNode->GetAllKeyAreas())
  1398. {
  1399. if (KeyArea->GetOwningSection() == OldKeyTemplate.Section)
  1400. {
  1401. NewKeyTemplate.Section = OldKeyTemplate.Section;
  1402. NewKeyTemplate.KeyArea = KeyArea;
  1403. OldToNew.Add(OldKeyTemplate, NewKeyTemplate);
  1404. // stop iterating
  1405. return false;
  1406. }
  1407. }
  1408. }
  1409. return true;
  1410. };
  1411.  
  1412. // If the traversal returned false, we've found what we're looking for - no need to look at any more nodes
  1413. if (!RootNode->Traverse_ParentFirst(FindKeyArea))
  1414. {
  1415. break;
  1416. }
  1417. }
  1418. }
  1419.  
  1420. // If we've got a curretn section/key area pair, we can add this key to the selection
  1421. if (NewKeyTemplate.Section)
  1422. {
  1423. NewKeyTemplate.KeyHandle = OldKeyHandle;
  1424. Selection.AddToSelection(NewKeyTemplate);
  1425. }
  1426. }
  1427. }
  1428.  
  1429. void SSequencer::UpdateLayoutTree()
  1430. {
  1431. TrackArea->Empty();
  1432.  
  1433. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1434. if ( Sequencer.IsValid() )
  1435. {
  1436. // Cache the selected path names so selection can be restored after the update.
  1437. TSet<FString> SelectedPathNames;
  1438. // Cache selected keys
  1439. TSet<FSequencerSelectedKey> SelectedKeys = Sequencer->GetSelection().GetSelectedKeys();
  1440. TSet<TWeakObjectPtr<UMovieSceneSection> > SelectedSections = Sequencer->GetSelection().GetSelectedSections();
  1441.  
  1442. for (TSharedRef<const FSequencerDisplayNode> SelectedDisplayNode : Sequencer->GetSelection().GetSelectedOutlinerNodes().Array())
  1443. {
  1444. FString PathName = SelectedDisplayNode->GetPathName();
  1445. if ( FName(*PathName).IsNone() == false )
  1446. {
  1447. SelectedPathNames.Add(PathName);
  1448. }
  1449. }
  1450.  
  1451. // Suspend broadcasting selection changes because we don't want unnecessary rebuilds.
  1452. Sequencer->GetSelection().SuspendBroadcast();
  1453. Sequencer->GetSelection().Empty();
  1454.  
  1455. // Update the node tree
  1456. Sequencer->GetNodeTree()->Update();
  1457.  
  1458. // Restore the selection state.
  1459. RestoreSelectionState(Sequencer->GetNodeTree()->GetRootNodes(), SelectedPathNames, SequencerPtr.Pin()->GetSelection()); // Update to actor selection.
  1460.  
  1461. // This must come after the selection state has been restored so that the tree and curve editor are populated with the correctly selected nodes
  1462. TreeView->Refresh();
  1463. CurveEditor->SetSequencerNodeTree(Sequencer->GetNodeTree());
  1464.  
  1465. RestoreKeySelection(SelectedKeys, Sequencer->GetSelection(), *Sequencer->GetNodeTree());
  1466. RestoreSectionSelection(SelectedSections, Sequencer->GetSelection());
  1467.  
  1468. // Continue broadcasting selection changes
  1469. Sequencer->GetSelection().ResumeBroadcast();
  1470. }
  1471. }
  1472.  
  1473.  
  1474. void SSequencer::UpdateBreadcrumbs()
  1475. {
  1476. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1477. if (!Sequencer.IsValid())
  1478. {
  1479. return;
  1480. }
  1481.  
  1482. FMovieSceneSequenceID FocusedID = Sequencer->GetFocusedTemplateID();
  1483. if (BreadcrumbTrail->PeekCrumb().BreadcrumbType == FSequencerBreadcrumb::ShotType)
  1484. {
  1485. BreadcrumbTrail->PopCrumb();
  1486. }
  1487.  
  1488. if( BreadcrumbTrail->PeekCrumb().BreadcrumbType == FSequencerBreadcrumb::MovieSceneType && BreadcrumbTrail->PeekCrumb().SequenceID != FocusedID )
  1489. {
  1490. FText CrumbName = Sequencer->GetFocusedMovieSceneSequence()->GetDisplayName();
  1491. // The current breadcrumb is not a moviescene so we need to make a new breadcrumb in order return to the parent moviescene later
  1492. BreadcrumbTrail->PushCrumb( CrumbName, FSequencerBreadcrumb( FocusedID ) );
  1493. }
  1494. }
  1495.  
  1496.  
  1497. void SSequencer::ResetBreadcrumbs()
  1498. {
  1499. BreadcrumbTrail->ClearCrumbs();
  1500. BreadcrumbTrail->PushCrumb(TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateSP(this, &SSequencer::GetRootAnimationName)), FSequencerBreadcrumb(MovieSceneSequenceID::Root));
  1501. }
  1502.  
  1503. void SSequencer::PopBreadcrumb()
  1504. {
  1505. BreadcrumbTrail->PopCrumb();
  1506. }
  1507.  
  1508. void SSequencer::OnOutlinerSearchChanged( const FText& Filter )
  1509. {
  1510. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1511. if ( Sequencer.IsValid())
  1512. {
  1513. const FString FilterString = Filter.ToString();
  1514.  
  1515. Sequencer->GetNodeTree()->FilterNodes( FilterString );
  1516. TreeView->Refresh();
  1517.  
  1518. if ( FilterString.StartsWith( TEXT( "label:" ) ) )
  1519. {
  1520. LabelBrowser->SetSelectedLabel(FilterString);
  1521. }
  1522. else
  1523. {
  1524. LabelBrowser->SetSelectedLabel( FString() );
  1525. }
  1526. }
  1527. }
  1528.  
  1529.  
  1530. float SSequencer::OnGetTimeSnapInterval() const
  1531. {
  1532. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1533. if ( Sequencer.IsValid() )
  1534. {
  1535. return Sequencer->GetFixedFrameInterval();
  1536. }
  1537.  
  1538. return 1.f;
  1539. }
  1540.  
  1541.  
  1542. void SSequencer::OnDragEnter( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
  1543. {
  1544. // @todo sequencer: Add drop validity cue
  1545. }
  1546.  
  1547.  
  1548. void SSequencer::OnDragLeave( const FDragDropEvent& DragDropEvent )
  1549. {
  1550. // @todo sequencer: Clear drop validity cue
  1551. }
  1552.  
  1553.  
  1554. FReply SSequencer::OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
  1555. {
  1556. bool bIsDragSupported = false;
  1557.  
  1558. TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
  1559. if (Operation.IsValid() && (
  1560. Operation->IsOfType<FAssetDragDropOp>() ||
  1561. Operation->IsOfType<FClassDragDropOp>() ||
  1562. Operation->IsOfType<FUnloadedClassDragDropOp>() ||
  1563. Operation->IsOfType<FActorDragDropGraphEdOp>() ) )
  1564. {
  1565. bIsDragSupported = true;
  1566. }
  1567.  
  1568. return bIsDragSupported ? FReply::Handled() : FReply::Unhandled();
  1569. }
  1570.  
  1571.  
  1572. FReply SSequencer::OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
  1573. {
  1574. bool bWasDropHandled = false;
  1575.  
  1576. // @todo sequencer: Get rid of hard-code assumptions about dealing with ACTORS at this level?
  1577.  
  1578. // @todo sequencer: We may not want any actor-specific code here actually. We need systems to be able to
  1579. // register with sequencer to support dropping assets/classes/actors, or OTHER types!
  1580.  
  1581. // @todo sequencer: Handle drag and drop from other FDragDropOperations, including unloaded classes/asset and external drags!
  1582.  
  1583. // @todo sequencer: Consider allowing drops into the level viewport to add to the MovieScene as well.
  1584. // - Basically, when Sequencer is open it would take over drops into the level and auto-add puppets for these instead of regular actors
  1585. // - This would let people drag smoothly and precisely into the view to drop assets/classes into the scene
  1586.  
  1587. TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
  1588.  
  1589. if (Operation.IsValid() )
  1590. {
  1591. if ( Operation->IsOfType<FAssetDragDropOp>() )
  1592. {
  1593. const auto& DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>( Operation );
  1594.  
  1595. OnAssetsDropped( *DragDropOp );
  1596. bWasDropHandled = true;
  1597. }
  1598. else if( Operation->IsOfType<FClassDragDropOp>() )
  1599. {
  1600. const auto& DragDropOp = StaticCastSharedPtr<FClassDragDropOp>( Operation );
  1601.  
  1602. OnClassesDropped( *DragDropOp );
  1603. bWasDropHandled = true;
  1604. }
  1605. else if( Operation->IsOfType<FUnloadedClassDragDropOp>() )
  1606. {
  1607. const auto& DragDropOp = StaticCastSharedPtr<FUnloadedClassDragDropOp>( Operation );
  1608.  
  1609. OnUnloadedClassesDropped( *DragDropOp );
  1610. bWasDropHandled = true;
  1611. }
  1612. else if( Operation->IsOfType<FActorDragDropGraphEdOp>() )
  1613. {
  1614. const auto& DragDropOp = StaticCastSharedPtr<FActorDragDropGraphEdOp>( Operation );
  1615.  
  1616. OnActorsDropped( *DragDropOp );
  1617. bWasDropHandled = true;
  1618. }
  1619. }
  1620.  
  1621. return bWasDropHandled ? FReply::Handled() : FReply::Unhandled();
  1622. }
  1623.  
  1624.  
  1625. FReply SSequencer::OnKeyDown( const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent )
  1626. {
  1627. // A toolkit tab is active, so direct all command processing to it
  1628. if( SequencerPtr.Pin()->GetCommandBindings()->ProcessCommandBindings( InKeyEvent ) )
  1629. {
  1630. return FReply::Handled();
  1631. }
  1632.  
  1633. return FReply::Unhandled();
  1634. }
  1635.  
  1636. void SSequencer::OnFocusChanging( const FWeakWidgetPath& PreviousFocusPath, const FWidgetPath& NewWidgetPath, const FFocusEvent& InFocusEvent )
  1637. {
  1638. if (NewWidgetPath.ContainsWidget(AsShared()))
  1639. {
  1640. OnReceivedFocus.ExecuteIfBound();
  1641. }
  1642. }
  1643.  
  1644. void SSequencer::OnAssetsDropped( const FAssetDragDropOp& DragDropOp )
  1645. {
  1646. FSequencer& SequencerRef = *SequencerPtr.Pin();
  1647.  
  1648. bool bObjectAdded = false;
  1649. TArray< UObject* > DroppedObjects;
  1650. bool bAllAssetsWereLoaded = true;
  1651.  
  1652. for (const FAssetData& AssetData : DragDropOp.GetAssets())
  1653. {
  1654. UObject* Object = AssetData.GetAsset();
  1655.  
  1656. if ( Object != nullptr )
  1657. {
  1658. DroppedObjects.Add( Object );
  1659. }
  1660. else
  1661. {
  1662. bAllAssetsWereLoaded = false;
  1663. }
  1664. }
  1665.  
  1666. const TSet< TSharedRef<FSequencerDisplayNode> >& SelectedNodes = SequencerPtr.Pin()->GetSelection().GetSelectedOutlinerNodes();
  1667. FGuid TargetObjectGuid;
  1668. // if exactly one object node is selected, we have a target object guid
  1669. TSharedPtr<const FSequencerDisplayNode> DisplayNode;
  1670. if (SelectedNodes.Num() == 1)
  1671. {
  1672. for (TSharedRef<const FSequencerDisplayNode> SelectedNode : SelectedNodes )
  1673. {
  1674. DisplayNode = SelectedNode;
  1675. }
  1676. if (DisplayNode.IsValid() && DisplayNode->GetType() == ESequencerNode::Object)
  1677. {
  1678. TSharedPtr<const FSequencerObjectBindingNode> ObjectBindingNode = StaticCastSharedPtr<const FSequencerObjectBindingNode>(DisplayNode);
  1679. TargetObjectGuid = ObjectBindingNode->GetObjectBinding();
  1680. }
  1681. }
  1682.  
  1683. for( auto CurObjectIter = DroppedObjects.CreateConstIterator(); CurObjectIter; ++CurObjectIter )
  1684. {
  1685. UObject* CurObject = *CurObjectIter;
  1686.  
  1687. if (!SequencerRef.OnHandleAssetDropped(CurObject, TargetObjectGuid))
  1688. {
  1689. SequencerRef.MakeNewSpawnable( *CurObject );
  1690. }
  1691. bObjectAdded = true;
  1692. }
  1693.  
  1694. if( bObjectAdded )
  1695. {
  1696. // Update the sequencers view of the movie scene data when any object is added
  1697. SequencerRef.NotifyMovieSceneDataChanged( EMovieSceneDataChangeType::MovieSceneStructureItemAdded );
  1698.  
  1699. // Update the tree and synchronize selection
  1700. UpdateLayoutTree();
  1701.  
  1702. SequencerRef.SynchronizeSequencerSelectionWithExternalSelection();
  1703. }
  1704. }
  1705.  
  1706.  
  1707. void SSequencer::OnClassesDropped( const FClassDragDropOp& DragDropOp )
  1708. {
  1709. FSequencer& SequencerRef = *SequencerPtr.Pin();
  1710.  
  1711. for( auto ClassIter = DragDropOp.ClassesToDrop.CreateConstIterator(); ClassIter; ++ClassIter )
  1712. {
  1713. UClass* Class = ( *ClassIter ).Get();
  1714. if( Class != nullptr )
  1715. {
  1716. UObject* Object = Class->GetDefaultObject();
  1717.  
  1718. FGuid NewGuid = SequencerRef.MakeNewSpawnable( *Object );
  1719. }
  1720. }
  1721. }
  1722.  
  1723.  
  1724. void SSequencer::OnUnloadedClassesDropped( const FUnloadedClassDragDropOp& DragDropOp )
  1725. {
  1726. FSequencer& SequencerRef = *SequencerPtr.Pin();
  1727. for( auto ClassDataIter = DragDropOp.AssetsToDrop->CreateConstIterator(); ClassDataIter; ++ClassDataIter )
  1728. {
  1729. auto& ClassData = *ClassDataIter;
  1730.  
  1731. // Check to see if the asset can be found, otherwise load it.
  1732. UObject* Object = FindObject<UObject>( nullptr, *ClassData.AssetName );
  1733. if( Object == nullptr )
  1734. {
  1735. Object = FindObject<UObject>(nullptr, *FString::Printf(TEXT("%s.%s"), *ClassData.GeneratedPackageName, *ClassData.AssetName));
  1736. }
  1737.  
  1738. if( Object == nullptr )
  1739. {
  1740. // Load the package.
  1741. GWarn->BeginSlowTask( LOCTEXT("OnDrop_FullyLoadPackage", "Fully Loading Package For Drop"), true, false );
  1742. UPackage* Package = LoadPackage(nullptr, *ClassData.GeneratedPackageName, LOAD_NoRedirects );
  1743. if( Package != nullptr )
  1744. {
  1745. Package->FullyLoad();
  1746. }
  1747. GWarn->EndSlowTask();
  1748.  
  1749. Object = FindObject<UObject>(Package, *ClassData.AssetName);
  1750. }
  1751.  
  1752. if( Object != nullptr )
  1753. {
  1754. // Check to see if the dropped asset was a blueprint
  1755. if(Object->IsA(UBlueprint::StaticClass()))
  1756. {
  1757. // Get the default object from the generated class.
  1758. Object = Cast<UBlueprint>(Object)->GeneratedClass->GetDefaultObject();
  1759. }
  1760. }
  1761.  
  1762. if( Object != nullptr )
  1763. {
  1764. FGuid NewGuid = SequencerRef.MakeNewSpawnable( *Object );
  1765. }
  1766. }
  1767. }
  1768.  
  1769.  
  1770. void SSequencer::OnActorsDropped( FActorDragDropGraphEdOp& DragDropOp )
  1771. {
  1772. SequencerPtr.Pin()->OnActorsDropped( DragDropOp.Actors );
  1773. }
  1774.  
  1775.  
  1776. void SSequencer::OnCrumbClicked(const FSequencerBreadcrumb& Item)
  1777. {
  1778. if (Item.BreadcrumbType != FSequencerBreadcrumb::ShotType)
  1779. {
  1780. if( SequencerPtr.Pin()->GetFocusedTemplateID() == Item.SequenceID )
  1781. {
  1782. // then do zooming
  1783. }
  1784. else
  1785. {
  1786. if (SequencerPtr.Pin()->GetShowCurveEditor())
  1787. {
  1788. SequencerPtr.Pin()->SetShowCurveEditor(false);
  1789. }
  1790.  
  1791. SequencerPtr.Pin()->PopToSequenceInstance( Item.SequenceID );
  1792. }
  1793. }
  1794. }
  1795.  
  1796.  
  1797. FText SSequencer::GetRootAnimationName() const
  1798. {
  1799. return SequencerPtr.Pin()->GetRootMovieSceneSequence()->GetDisplayName();
  1800. }
  1801.  
  1802.  
  1803. TSharedPtr<SSequencerTreeView> SSequencer::GetTreeView() const
  1804. {
  1805. return TreeView;
  1806. }
  1807.  
  1808.  
  1809. TArray<FSectionHandle> SSequencer::GetSectionHandles(const TSet<TWeakObjectPtr<UMovieSceneSection>>& DesiredSections) const
  1810. {
  1811. TArray<FSectionHandle> SectionHandles;
  1812.  
  1813. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1814. if (Sequencer.IsValid())
  1815. {
  1816. // @todo sequencer: this is potentially slow as it traverses the entire tree - there's scope for optimization here
  1817. for (auto& Node : Sequencer->GetNodeTree()->GetRootNodes())
  1818. {
  1819. Node->Traverse_ParentFirst([&](FSequencerDisplayNode& InNode) {
  1820. if (InNode.GetType() == ESequencerNode::Track)
  1821. {
  1822. FSequencerTrackNode& TrackNode = static_cast<FSequencerTrackNode&>(InNode);
  1823.  
  1824. const auto& AllSections = TrackNode.GetSections();
  1825. for (int32 Index = 0; Index < AllSections.Num(); ++Index)
  1826. {
  1827. if (DesiredSections.Contains(TWeakObjectPtr<UMovieSceneSection>(AllSections[Index]->GetSectionObject())))
  1828. {
  1829. SectionHandles.Emplace(StaticCastSharedRef<FSequencerTrackNode>(TrackNode.AsShared()), Index);
  1830. }
  1831. }
  1832. }
  1833. return true;
  1834. });
  1835. }
  1836. }
  1837.  
  1838. return SectionHandles;
  1839. }
  1840.  
  1841.  
  1842. void SSequencer::OnSaveMovieSceneClicked()
  1843. {
  1844. SequencerPtr.Pin()->SaveCurrentMovieScene();
  1845. }
  1846.  
  1847.  
  1848. void SSequencer::OnSaveMovieSceneAsClicked()
  1849. {
  1850. SequencerPtr.Pin()->SaveCurrentMovieSceneAs();
  1851. }
  1852.  
  1853.  
  1854. void SSequencer::StepToNextKey()
  1855. {
  1856. StepToKey(true, false);
  1857. }
  1858.  
  1859.  
  1860. void SSequencer::StepToPreviousKey()
  1861. {
  1862. StepToKey(false, false);
  1863. }
  1864.  
  1865.  
  1866. void SSequencer::StepToNextCameraKey()
  1867. {
  1868. StepToKey(true, true);
  1869. }
  1870.  
  1871.  
  1872. void SSequencer::StepToPreviousCameraKey()
  1873. {
  1874. StepToKey(false, true);
  1875. }
  1876.  
  1877.  
  1878. void SSequencer::StepToKey(bool bStepToNextKey, bool bCameraOnly)
  1879. {
  1880. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  1881. if ( Sequencer.IsValid() )
  1882. {
  1883. TSet< TSharedRef<FSequencerDisplayNode> > Nodes;
  1884.  
  1885. if ( bCameraOnly )
  1886. {
  1887. TSet<TSharedRef<FSequencerDisplayNode>> RootNodes( Sequencer->GetNodeTree()->GetRootNodes() );
  1888.  
  1889. TSet<TWeakObjectPtr<AActor> > LockedActors;
  1890. for ( int32 i = 0; i < GEditor->LevelViewportClients.Num(); ++i )
  1891. {
  1892. FLevelEditorViewportClient* LevelVC = GEditor->LevelViewportClients[i];
  1893. if ( LevelVC && LevelVC->IsPerspective() && LevelVC->GetViewMode() != VMI_Unknown )
  1894. {
  1895. TWeakObjectPtr<AActor> ActorLock = LevelVC->GetActiveActorLock();
  1896. if ( ActorLock.IsValid() )
  1897. {
  1898. LockedActors.Add( ActorLock );
  1899. }
  1900. }
  1901. }
  1902.  
  1903. for ( auto RootNode : RootNodes )
  1904. {
  1905. TSharedRef<FSequencerObjectBindingNode> ObjectBindingNode = StaticCastSharedRef<FSequencerObjectBindingNode>( RootNode );
  1906.  
  1907. for (TWeakObjectPtr<>& Object : Sequencer->FindObjectsInCurrentSequence(ObjectBindingNode->GetObjectBinding()))
  1908. {
  1909. AActor* RuntimeActor = Cast<AActor>( Object.Get() );
  1910. if ( RuntimeActor != nullptr && LockedActors.Contains( RuntimeActor ) )
  1911. {
  1912. Nodes.Add( RootNode );
  1913. }
  1914. }
  1915. }
  1916. }
  1917. else
  1918. {
  1919. const TSet< TSharedRef<FSequencerDisplayNode> >& SelectedNodes = Sequencer->GetSelection().GetSelectedOutlinerNodes();
  1920. Nodes = SelectedNodes;
  1921.  
  1922. if ( Nodes.Num() == 0 )
  1923. {
  1924. TSet<TSharedRef<FSequencerDisplayNode>> RootNodes( Sequencer->GetNodeTree()->GetRootNodes() );
  1925. for ( auto RootNode : RootNodes )
  1926. {
  1927. Nodes.Add( RootNode );
  1928.  
  1929. SequencerHelpers::GetDescendantNodes( RootNode, Nodes );
  1930. }
  1931. }
  1932. }
  1933.  
  1934. if ( Nodes.Num() > 0 )
  1935. {
  1936. float ClosestKeyDistance = MAX_FLT;
  1937. float CurrentTime = Sequencer->GetLocalTime();
  1938. float StepToTime = 0;
  1939. bool StepToKeyFound = false;
  1940.  
  1941. auto It = Nodes.CreateConstIterator();
  1942. bool bExpand = !( *It ).Get().IsExpanded();
  1943.  
  1944. for ( auto Node : Nodes )
  1945. {
  1946. TArray<float> AllTimes;
  1947.  
  1948. TSet<TSharedPtr<IKeyArea>> KeyAreas;
  1949. SequencerHelpers::GetAllKeyAreas( Node, KeyAreas );
  1950. for ( TSharedPtr<IKeyArea> KeyArea : KeyAreas )
  1951. {
  1952. for ( FKeyHandle& KeyHandle : KeyArea->GetUnsortedKeyHandles() )
  1953. {
  1954. float KeyTime = KeyArea->GetKeyTime( KeyHandle );
  1955. AllTimes.Add(KeyTime);
  1956. }
  1957. }
  1958.  
  1959. TSet<TWeakObjectPtr<UMovieSceneSection> > Sections;
  1960. SequencerHelpers::GetAllSections( Node, Sections );
  1961. for ( TWeakObjectPtr<UMovieSceneSection> Section : Sections )
  1962. {
  1963. if (Section.IsValid() && !Section->IsInfinite())
  1964. {
  1965. AllTimes.Add(Section->GetStartTime());
  1966. AllTimes.Add(Section->GetEndTime());
  1967. }
  1968. }
  1969.  
  1970. for (float Time : AllTimes)
  1971. {
  1972. if ( bStepToNextKey )
  1973. {
  1974. if ( Time > CurrentTime && Time - CurrentTime < ClosestKeyDistance )
  1975. {
  1976. StepToTime = Time;
  1977. ClosestKeyDistance = Time - CurrentTime;
  1978. StepToKeyFound = true;
  1979. }
  1980. }
  1981. else
  1982. {
  1983. if ( Time < CurrentTime && CurrentTime - Time < ClosestKeyDistance )
  1984. {
  1985. StepToTime = Time;
  1986. ClosestKeyDistance = CurrentTime - Time;
  1987. StepToKeyFound = true;
  1988. }
  1989. }
  1990. }
  1991. }
  1992.  
  1993. if ( StepToKeyFound )
  1994. {
  1995. Sequencer->SetLocalTime( StepToTime );
  1996. }
  1997. }
  1998. }
  1999. }
  2000.  
  2001.  
  2002. EVisibility SSequencer::GetBreadcrumbTrailVisibility() const
  2003. {
  2004. return SequencerPtr.Pin()->IsLevelEditorSequencer() ? EVisibility::Visible : EVisibility::Collapsed;
  2005. }
  2006.  
  2007.  
  2008. EVisibility SSequencer::GetCurveEditorToolBarVisibility() const
  2009. {
  2010. return SequencerPtr.Pin()->GetShowCurveEditor() ? EVisibility::Visible : EVisibility::Collapsed;
  2011. }
  2012.  
  2013.  
  2014. EVisibility SSequencer::GetBottomTimeSliderVisibility() const
  2015. {
  2016. return Settings->GetShowRangeSlider() ? EVisibility::Hidden : EVisibility::Visible;
  2017. }
  2018.  
  2019.  
  2020. EVisibility SSequencer::GetTimeRangeVisibility() const
  2021. {
  2022. return Settings->GetShowRangeSlider() ? EVisibility::Visible : EVisibility::Hidden;
  2023. }
  2024.  
  2025.  
  2026. bool SSequencer::ShowFrameNumbers() const
  2027. {
  2028. return SequencerPtr.Pin()->CanShowFrameNumbers() && Settings->GetShowFrameNumbers();
  2029. }
  2030.  
  2031.  
  2032. float SSequencer::GetOutlinerSpacerFill() const
  2033. {
  2034. const float Column1Coeff = GetColumnFillCoefficient(1);
  2035. return SequencerPtr.Pin()->GetShowCurveEditor() ? Column1Coeff / (1 - Column1Coeff) : 0.f;
  2036. }
  2037.  
  2038.  
  2039. void SSequencer::OnColumnFillCoefficientChanged(float FillCoefficient, int32 ColumnIndex)
  2040. {
  2041. ColumnFillCoefficients[ColumnIndex] = FillCoefficient;
  2042. }
  2043.  
  2044.  
  2045. EVisibility SSequencer::GetTrackAreaVisibility() const
  2046. {
  2047. return SequencerPtr.Pin()->GetShowCurveEditor() ? EVisibility::Collapsed : EVisibility::Visible;
  2048. }
  2049.  
  2050.  
  2051. EVisibility SSequencer::GetCurveEditorVisibility() const
  2052. {
  2053. return SequencerPtr.Pin()->GetShowCurveEditor() ? EVisibility::Visible : EVisibility::Collapsed;
  2054. }
  2055.  
  2056.  
  2057. void SSequencer::OnCurveEditorVisibilityChanged()
  2058. {
  2059. if (CurveEditor.IsValid())
  2060. {
  2061. if (!Settings->GetLinkCurveEditorTimeRange())
  2062. {
  2063. TRange<float> ClampRange = SequencerPtr.Pin()->GetClampRange();
  2064. if (CachedClampRange.IsEmpty())
  2065. {
  2066. CachedClampRange = ClampRange;
  2067. }
  2068. SequencerPtr.Pin()->SetClampRange(CachedClampRange);
  2069. CachedClampRange = ClampRange;
  2070.  
  2071. TRange<float> ViewRange = SequencerPtr.Pin()->GetViewRange();
  2072. if (CachedViewRange.IsEmpty())
  2073. {
  2074. CachedViewRange = ViewRange;
  2075. }
  2076. SequencerPtr.Pin()->SetViewRange(CachedViewRange);
  2077. CachedViewRange = ViewRange;
  2078. }
  2079.  
  2080. // Only zoom horizontally if the editor is visible
  2081. CurveEditor->SetAllowAutoFrame(SequencerPtr.Pin()->GetShowCurveEditor());
  2082.  
  2083. if (CurveEditor->GetAutoFrame())
  2084. {
  2085. CurveEditor->ZoomToFit();
  2086. }
  2087. }
  2088.  
  2089. TreeView->UpdateTrackArea();
  2090. }
  2091.  
  2092.  
  2093. void SSequencer::OnTimeSnapIntervalChanged(float InInterval)
  2094. {
  2095. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2096. if ( Sequencer.IsValid() )
  2097. {
  2098. UMovieScene* MovieScene = Sequencer->GetFocusedMovieSceneSequence()->GetMovieScene();
  2099. if (!FMath::IsNearlyEqual(MovieScene->GetFixedFrameInterval(), InInterval))
  2100. {
  2101. FScopedTransaction SetFixedFrameIntervalTransaction( NSLOCTEXT( "Sequencer", "SetFixedFrameInterval", "Set scene fixed frame interval" ) );
  2102. MovieScene->Modify();
  2103. MovieScene->SetFixedFrameInterval( InInterval );
  2104.  
  2105. // Update the current time to the new interval
  2106. float NewTime = SequencerHelpers::SnapTimeToInterval(Sequencer->GetLocalTime(), InInterval);
  2107. Sequencer->SetLocalTime(NewTime);
  2108. }
  2109. }
  2110. }
  2111.  
  2112.  
  2113. FPaintPlaybackRangeArgs SSequencer::GetSectionPlaybackRangeArgs() const
  2114. {
  2115. if (GetBottomTimeSliderVisibility() == EVisibility::Visible)
  2116. {
  2117. static FPaintPlaybackRangeArgs Args(FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_L"), FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_R"), 6.f);
  2118. return Args;
  2119. }
  2120. else
  2121. {
  2122. static FPaintPlaybackRangeArgs Args(FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Bottom_L"), FEditorStyle::GetBrush("Sequencer.Timeline.PlayRange_Bottom_R"), 6.f);
  2123. return Args;
  2124. }
  2125. }
  2126.  
  2127.  
  2128. FVirtualTrackArea SSequencer::GetVirtualTrackArea() const
  2129. {
  2130. return FVirtualTrackArea(*SequencerPtr.Pin(), *TreeView.Get(), TrackArea->GetCachedGeometry());
  2131. }
  2132.  
  2133. FPasteContextMenuArgs SSequencer::GeneratePasteArgs(float PasteAtTime, TSharedPtr<FMovieSceneClipboard> Clipboard)
  2134. {
  2135. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2136. if (Settings->GetIsSnapEnabled())
  2137. {
  2138. PasteAtTime = SequencerHelpers::SnapTimeToInterval(PasteAtTime, Sequencer->GetFixedFrameInterval());
  2139. }
  2140.  
  2141. // Open a paste menu at the current mouse position
  2142. FSlateApplication& Application = FSlateApplication::Get();
  2143. FVector2D LocalMousePosition = TrackArea->GetCachedGeometry().AbsoluteToLocal(Application.GetCursorPos());
  2144.  
  2145. FVirtualTrackArea VirtualTrackArea = GetVirtualTrackArea();
  2146.  
  2147. // Paste into the currently selected sections, or hit test the mouse position as a last resort
  2148. TArray<TSharedRef<FSequencerDisplayNode>> PasteIntoNodes;
  2149. {
  2150. TSet<TWeakObjectPtr<UMovieSceneSection>> Sections = Sequencer->GetSelection().GetSelectedSections();
  2151. for (const FSequencerSelectedKey& Key : Sequencer->GetSelection().GetSelectedKeys())
  2152. {
  2153. Sections.Add(Key.Section);
  2154. }
  2155.  
  2156. for (const FSectionHandle& Handle : GetSectionHandles(Sections))
  2157. {
  2158. PasteIntoNodes.Add(Handle.TrackNode.ToSharedRef());
  2159. }
  2160. }
  2161.  
  2162. if (PasteIntoNodes.Num() == 0)
  2163. {
  2164. TSharedPtr<FSequencerDisplayNode> Node = VirtualTrackArea.HitTestNode(LocalMousePosition.Y);
  2165. if (Node.IsValid())
  2166. {
  2167. PasteIntoNodes.Add(Node.ToSharedRef());
  2168. }
  2169. }
  2170.  
  2171. return FPasteContextMenuArgs::PasteInto(MoveTemp(PasteIntoNodes), PasteAtTime, Clipboard);
  2172. }
  2173.  
  2174. void SSequencer::OnPaste()
  2175. {
  2176. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2177. TSet<TSharedRef<FSequencerDisplayNode>> SelectedNodes = Sequencer->GetSelection().GetSelectedOutlinerNodes();
  2178. if (SelectedNodes.Num() == 0)
  2179. {
  2180. if (OpenPasteMenu())
  2181. {
  2182. return;
  2183. }
  2184. }
  2185.  
  2186. PasteTracks();
  2187. }
  2188.  
  2189. bool SSequencer::CanPaste()
  2190. {
  2191. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2192. TSet<TSharedRef<FSequencerDisplayNode>> SelectedNodes = Sequencer->GetSelection().GetSelectedOutlinerNodes();
  2193. if (SelectedNodes.Num() != 0)
  2194. {
  2195. FString TexttoImport;
  2196. FPlatformApplicationMisc::ClipboardPaste(TexttoImport);
  2197.  
  2198. if (Sequencer->CanPaste(TexttoImport))
  2199. {
  2200. TArray<UMovieSceneTrack*> ImportedTrack;
  2201. Sequencer->ImportTracksFromText(TexttoImport, ImportedTrack);
  2202. if (ImportedTrack.Num() == 0)
  2203. {
  2204. return false;
  2205. }
  2206.  
  2207. for (TSharedRef<FSequencerDisplayNode> Node : SelectedNodes)
  2208. {
  2209. if (Node->GetType() == ESequencerNode::Object)
  2210. {
  2211. return true;
  2212. }
  2213. }
  2214. return false;
  2215. }
  2216. }
  2217.  
  2218. return SequencerPtr.Pin()->GetClipboardStack().Num() != 0;
  2219. }
  2220.  
  2221. void SSequencer::PasteTracks()
  2222. {
  2223. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2224.  
  2225. Sequencer->PasteCopiedTracks();
  2226. }
  2227.  
  2228. bool SSequencer::OpenPasteMenu()
  2229. {
  2230. TSharedPtr<FPasteContextMenu> ContextMenu;
  2231.  
  2232. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2233. if (Sequencer->GetClipboardStack().Num() != 0)
  2234. {
  2235. FPasteContextMenuArgs Args = GeneratePasteArgs(Sequencer->GetLocalTime(), Sequencer->GetClipboardStack().Last());
  2236. ContextMenu = FPasteContextMenu::CreateMenu(*Sequencer, Args);
  2237. }
  2238.  
  2239. if (!ContextMenu.IsValid() || !ContextMenu->IsValidPaste())
  2240. {
  2241. return false;
  2242. }
  2243. else if (ContextMenu->AutoPaste())
  2244. {
  2245. return false;
  2246. }
  2247.  
  2248. const bool bShouldCloseWindowAfterMenuSelection = true;
  2249. FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, SequencerPtr.Pin()->GetCommandBindings());
  2250.  
  2251. ContextMenu->PopulateMenu(MenuBuilder);
  2252.  
  2253. FWidgetPath Path;
  2254. FSlateApplication::Get().FindPathToWidget(AsShared(), Path);
  2255.  
  2256. FSlateApplication::Get().PushMenu(
  2257. AsShared(),
  2258. Path,
  2259. MenuBuilder.MakeWidget(),
  2260. FSlateApplication::Get().GetCursorPos(),
  2261. FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)
  2262. );
  2263.  
  2264. return true;
  2265. }
  2266.  
  2267. void SSequencer::PasteFromHistory()
  2268. {
  2269. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2270. if (Sequencer->GetClipboardStack().Num() == 0)
  2271. {
  2272. return;
  2273. }
  2274.  
  2275. FPasteContextMenuArgs Args = GeneratePasteArgs(Sequencer->GetLocalTime());
  2276. TSharedPtr<FPasteFromHistoryContextMenu> ContextMenu = FPasteFromHistoryContextMenu::CreateMenu(*Sequencer, Args);
  2277.  
  2278. if (ContextMenu.IsValid())
  2279. {
  2280. const bool bShouldCloseWindowAfterMenuSelection = true;
  2281. FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, Sequencer->GetCommandBindings());
  2282.  
  2283. ContextMenu->PopulateMenu(MenuBuilder);
  2284.  
  2285. FWidgetPath Path;
  2286. FSlateApplication::Get().FindPathToWidget(AsShared(), Path);
  2287.  
  2288. FSlateApplication::Get().PushMenu(
  2289. AsShared(),
  2290. Path,
  2291. MenuBuilder.MakeWidget(),
  2292. FSlateApplication::Get().GetCursorPos(),
  2293. FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)
  2294. );
  2295. }
  2296. }
  2297.  
  2298. void SSequencer::OnSequenceInstanceActivated( FMovieSceneSequenceIDRef ActiveInstanceID )
  2299. {
  2300. TSharedPtr<FSequencer> Sequencer = SequencerPtr.Pin();
  2301. if ( Sequencer.IsValid() )
  2302. {
  2303. UMovieScene* MovieScene = Sequencer->GetFocusedMovieSceneSequence()->GetMovieScene();
  2304. if ( MovieScene->GetFixedFrameInterval() == 0 )
  2305. {
  2306. MovieScene->Modify();
  2307. MovieScene->SetFixedFrameInterval(Settings->GetTimeSnapInterval());
  2308.  
  2309. // Update the current time to the new interval
  2310. float NewTime = SequencerHelpers::SnapTimeToInterval(Sequencer->GetLocalTime(), Settings->GetTimeSnapInterval());
  2311. Sequencer->SetLocalTime(NewTime);
  2312. }
  2313. }
  2314. }
  2315.  
  2316. EVisibility SSequencer::GetDebugVisualizerVisibility() const
  2317. {
  2318. return Settings->ShouldShowDebugVisualization() ? EVisibility::Visible : EVisibility::Collapsed;
  2319. }
  2320.  
  2321. #undef LOCTEXT_NAMESPACE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement