// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #include "SequencerSelection.h" #include "MovieSceneSection.h" #include "DisplayNodes/SequencerObjectBindingNode.h" #include "DisplayNodes/SequencerTrackNode.h" #include "SequencerCommonHelpers.h" #include "IKeyArea.h" FSequencerSelection::FSequencerSelection() : SuspendBroadcastCount(0) , bOutlinerNodeSelectionChangedBroadcastPending(false) { } const TSet& FSequencerSelection::GetSelectedKeys() const { return SelectedKeys; } const TSet>& FSequencerSelection::GetSelectedSections() const { return SelectedSections; } const TSet>& FSequencerSelection::GetSelectedOutlinerNodes() const { return SelectedOutlinerNodes; } const TSet>& FSequencerSelection::GetNodesWithSelectedKeysOrSections() const { return NodesWithSelectedKeysOrSections; } FSequencerSelection::FOnSelectionChanged& FSequencerSelection::GetOnKeySelectionChanged() { return OnKeySelectionChanged; } FSequencerSelection::FOnSelectionChanged& FSequencerSelection::GetOnSectionSelectionChanged() { return OnSectionSelectionChanged; } FSequencerSelection::FOnSelectionChanged& FSequencerSelection::GetOnOutlinerNodeSelectionChanged() { return OnOutlinerNodeSelectionChanged; } FSequencerSelection::FOnSelectionChanged& FSequencerSelection::GetOnNodesWithSelectedKeysOrSectionsChanged() { return OnNodesWithSelectedKeysOrSectionsChanged; } FSequencerSelection::FOnSelectionChangedObjectGuids& FSequencerSelection::GetOnOutlinerNodeSelectionChangedObjectGuids() { return OnOutlinerNodeSelectionChangedObjectGuids; } TArray FSequencerSelection::GetBoundObjectsGuids() { TArray OutGuids; TSet> SelectedNodes = GetNodesWithSelectedKeysOrSections(); if (SelectedNodes.Num() == 0) { SelectedNodes = GetSelectedOutlinerNodes(); } for (TSharedRef Node : SelectedNodes) { TSharedPtr ObjectNode; if (Node->GetType() == ESequencerNode::Object) { ObjectNode = StaticCastSharedRef(Node); } else { TSharedPtr ParentNode = Node->GetParent(); if (ParentNode.IsValid()) { while (ParentNode->GetParent().IsValid() && ParentNode->GetType() != ESequencerNode::Object) { ParentNode = ParentNode->GetParent(); } ObjectNode = StaticCastSharedPtr(ParentNode); } } if (ObjectNode.IsValid()) { OutGuids.Add(ObjectNode->GetObjectBinding()); } } return OutGuids; } TArray FSequencerSelection::GetSelectedTracks() const { TArray OutTracks; for (const TSharedRef& SelectedNode : SelectedOutlinerNodes) { if (SelectedNode->GetType() == ESequencerNode::Track) { if (UMovieSceneTrack* Track = StaticCastSharedRef(SelectedNode)->GetTrack()) { OutTracks.Add(Track); } } } return OutTracks; } void FSequencerSelection::AddToSelection(FSequencerSelectedKey Key) { SelectedKeys.Add(Key); if ( IsBroadcasting() ) { OnKeySelectionChanged.Broadcast(); OnOutlinerNodeSelectionChangedObjectGuids.Broadcast(); } // Deselect any outliner nodes that aren't within the trunk of this key if (Key.KeyArea.IsValid()) { EmptySelectedOutlinerNodesWithoutSection(Key.KeyArea->GetOwningSection()); } } void FSequencerSelection::AddToSelection(UMovieSceneSection* Section) { SelectedSections.Add(Section); if ( IsBroadcasting() ) { OnSectionSelectionChanged.Broadcast(); OnOutlinerNodeSelectionChangedObjectGuids.Broadcast(); } // Deselect any outliner nodes that aren't within the trunk of this section if (Section) { EmptySelectedOutlinerNodesWithoutSection(Section); } } void FSequencerSelection::AddToSelection(TSharedRef OutlinerNode) { SelectedOutlinerNodes.Add(OutlinerNode); if ( IsBroadcasting() ) { OnOutlinerNodeSelectionChanged.Broadcast(); OnOutlinerNodeSelectionChangedObjectGuids.Broadcast(); } EmptySelectedKeys(); EmptySelectedSections(); EmptyNodesWithSelectedKeysOrSections(); } void FSequencerSelection::AddToSelection(const TArray>& OutlinerNodes) { SelectedOutlinerNodes.Append(OutlinerNodes); if (IsBroadcasting()) { OnOutlinerNodeSelectionChanged.Broadcast(); OnOutlinerNodeSelectionChangedObjectGuids.Broadcast(); } EmptySelectedKeys(); EmptySelectedSections(); EmptyNodesWithSelectedKeysOrSections(); } void FSequencerSelection::AddToNodesWithSelectedKeysOrSections(TSharedRef OutlinerNode) { NodesWithSelectedKeysOrSections.Add(OutlinerNode); if ( IsBroadcasting() ) { OnNodesWithSelectedKeysOrSectionsChanged.Broadcast(); OnOutlinerNodeSelectionChangedObjectGuids.Broadcast(); } } void FSequencerSelection::RemoveFromSelection(FSequencerSelectedKey Key) { SelectedKeys.Remove(Key); if ( IsBroadcasting() ) { OnKeySelectionChanged.Broadcast(); } } void FSequencerSelection::RemoveFromSelection(UMovieSceneSection* Section) { SelectedSections.Remove(Section); if ( IsBroadcasting() ) { OnSectionSelectionChanged.Broadcast(); } } void FSequencerSelection::RemoveFromSelection(TSharedRef OutlinerNode) { SelectedOutlinerNodes.Remove(OutlinerNode); if ( IsBroadcasting() ) { OnOutlinerNodeSelectionChanged.Broadcast(); } } void FSequencerSelection::RemoveFromNodesWithSelectedKeysOrSections(TSharedRef OutlinerNode) { NodesWithSelectedKeysOrSections.Remove(OutlinerNode); if ( IsBroadcasting() ) { OnNodesWithSelectedKeysOrSectionsChanged.Broadcast(); } } bool FSequencerSelection::IsSelected(FSequencerSelectedKey Key) const { return SelectedKeys.Contains(Key); } bool FSequencerSelection::IsSelected(UMovieSceneSection* Section) const { return SelectedSections.Contains(Section); } bool FSequencerSelection::IsSelected(TSharedRef OutlinerNode) const { return SelectedOutlinerNodes.Contains(OutlinerNode); } bool FSequencerSelection::NodeHasSelectedKeysOrSections(TSharedRef OutlinerNode) const { return NodesWithSelectedKeysOrSections.Contains(OutlinerNode); } void FSequencerSelection::Empty() { EmptySelectedKeys(); EmptySelectedSections(); EmptySelectedOutlinerNodes(); EmptyNodesWithSelectedKeysOrSections(); } void FSequencerSelection::EmptySelectedKeys() { if (!SelectedKeys.Num()) { return; } SelectedKeys.Empty(); if ( IsBroadcasting() ) { OnKeySelectionChanged.Broadcast(); } } void FSequencerSelection::EmptySelectedSections() { if (!SelectedSections.Num()) { return; } SelectedSections.Empty(); if ( IsBroadcasting() ) { OnSectionSelectionChanged.Broadcast(); } } void FSequencerSelection::EmptySelectedOutlinerNodes() { if (!SelectedOutlinerNodes.Num()) { return; } SelectedOutlinerNodes.Empty(); if ( IsBroadcasting() ) { OnOutlinerNodeSelectionChanged.Broadcast(); } } void FSequencerSelection::EmptyNodesWithSelectedKeysOrSections() { if (!NodesWithSelectedKeysOrSections.Num()) { return; } NodesWithSelectedKeysOrSections.Empty(); if ( IsBroadcasting() ) { OnNodesWithSelectedKeysOrSectionsChanged.Broadcast(); } } /** Suspend or resume broadcast of selection changing */ void FSequencerSelection::SuspendBroadcast() { SuspendBroadcastCount++; } void FSequencerSelection::ResumeBroadcast() { SuspendBroadcastCount--; checkf(SuspendBroadcastCount >= 0, TEXT("Suspend/Resume broadcast mismatch!")); } bool FSequencerSelection::IsBroadcasting() { return SuspendBroadcastCount == 0; } void FSequencerSelection::EmptySelectedOutlinerNodesWithoutSection(UMovieSceneSection* Section) { TSet> LocalSelectedOutlinerNodes = SelectedOutlinerNodes; SuspendBroadcast(); bool bRemoved = false; for (auto SelectedOutlinerNode : LocalSelectedOutlinerNodes) { TSet > TrunkNodes; TrunkNodes.Add(SelectedOutlinerNode); SequencerHelpers::GetDescendantNodes(SelectedOutlinerNode, TrunkNodes); bool bFoundMatch = false; for (auto TrunkIt = TrunkNodes.CreateConstIterator(); TrunkIt && !bFoundMatch; ++TrunkIt) { TSet> AllSections; SequencerHelpers::GetAllSections(*TrunkIt, AllSections); for (auto SectionIt = AllSections.CreateConstIterator(); SectionIt && !bFoundMatch; ++SectionIt) { if (*SectionIt == Section) { bFoundMatch = true; break; } } } if (!bFoundMatch) { RemoveFromSelection(SelectedOutlinerNode); bRemoved = true; } } ResumeBroadcast(); if (bRemoved) { OnOutlinerNodeSelectionChanged.Broadcast(); } } void FSequencerSelection::RequestOutlinerNodeSelectionChangedBroadcast() { if ( IsBroadcasting() ) { bOutlinerNodeSelectionChangedBroadcastPending = true; } } void FSequencerSelection::Tick() { if ( bOutlinerNodeSelectionChangedBroadcastPending && IsBroadcasting() ) { bOutlinerNodeSelectionChangedBroadcastPending = false; OnOutlinerNodeSelectionChanged.Broadcast(); } }