Files
UnrealEngineUWP/Engine/Source/Editor/Sequencer/Private/SequencerSelection.cpp
Marc Audy f512a6d461 Eliminate whitespace only differences between Release-Engine-Staging and Release-Engine-Test
#fyi Aurel.Cordonnier

[CL 18448630 by Marc Audy in ue5-release-engine-test branch]
2021-12-13 15:59:48 -05:00

444 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SequencerSelection.h"
#include "MovieSceneSection.h"
#include "DisplayNodes/SequencerObjectBindingNode.h"
#include "DisplayNodes/SequencerTrackNode.h"
#include "SequencerCommonHelpers.h"
FSequencerSelection::FSequencerSelection()
: SerialNumber(0)
, SuspendBroadcastCount(0)
, bOutlinerNodeSelectionChangedBroadcastPending(false)
, bEmptySelectedOutlinerNodesWithSectionsPending(false)
{
}
const TSet<FSequencerSelectedKey>& FSequencerSelection::GetSelectedKeys() const
{
return SelectedKeys;
}
const TSet<TWeakObjectPtr<UMovieSceneSection>>& FSequencerSelection::GetSelectedSections() const
{
return SelectedSections;
}
const TSet<TSharedRef<FSequencerDisplayNode>>& FSequencerSelection::GetSelectedOutlinerNodes() const
{
return SelectedOutlinerNodes;
}
const TSet<TSharedRef<FSequencerDisplayNode>>& 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<FGuid> FSequencerSelection::GetBoundObjectsGuids()
{
TArray<FGuid> OutGuids;
TSet<TSharedRef<FSequencerDisplayNode>> SelectedNodes = GetNodesWithSelectedKeysOrSections();
if (SelectedNodes.Num() == 0)
{
SelectedNodes = GetSelectedOutlinerNodes();
}
for (TSharedRef<FSequencerDisplayNode> Node : SelectedNodes)
{
TSharedPtr<FSequencerObjectBindingNode> ObjectNode = Node->FindParentObjectBindingNode();
if (Node->GetType() == ESequencerNode::Object)
{
ObjectNode = StaticCastSharedRef<FSequencerObjectBindingNode>(Node);
}
else
{
ObjectNode = Node->FindParentObjectBindingNode();
}
if (ObjectNode.IsValid())
{
OutGuids.Add(ObjectNode->GetObjectBinding());
}
}
return OutGuids;
}
TArray<UMovieSceneTrack*> FSequencerSelection::GetSelectedTracks() const
{
TArray<UMovieSceneTrack*> OutTracks;
for (const TSharedRef<FSequencerDisplayNode>& SelectedNode : SelectedOutlinerNodes)
{
TSharedPtr<FSequencerDisplayNode> CurrentNode = SelectedNode;
while (CurrentNode.IsValid() && CurrentNode->GetType() != ESequencerNode::Track)
{
CurrentNode = CurrentNode->GetParent();
}
if (CurrentNode.IsValid())
{
UMovieSceneTrack* SelectedTrack = StaticCastSharedPtr<FSequencerTrackNode>(CurrentNode)->GetTrack();
if (SelectedTrack != nullptr)
{
OutTracks.Add(SelectedTrack);
}
}
}
return OutTracks;
}
void FSequencerSelection::AddToSelection(const FSequencerSelectedKey& Key)
{
++SerialNumber;
SelectedKeys.Add(Key);
if ( IsBroadcasting() )
{
OnKeySelectionChanged.Broadcast();
OnOutlinerNodeSelectionChangedObjectGuids.Broadcast();
// Deselect any outliner nodes that aren't within the trunk of this key
TArray<UMovieSceneSection*> Sections;
Sections.Add(Key.Section);
EmptySelectedOutlinerNodesWithoutSections(Sections);
}
else
{
bEmptySelectedOutlinerNodesWithSectionsPending = true;
}
}
void FSequencerSelection::AddToSelection(UMovieSceneSection* Section)
{
++SerialNumber;
SelectedSections.Add(Section);
if ( IsBroadcasting() )
{
OnSectionSelectionChanged.Broadcast();
OnOutlinerNodeSelectionChangedObjectGuids.Broadcast();
// Deselect any outliner nodes that aren't within the trunk of this section
if (Section)
{
TArray<UMovieSceneSection*> Sections;
Sections.Add(Section);
EmptySelectedOutlinerNodesWithoutSections(Sections);
}
}
else
{
bEmptySelectedOutlinerNodesWithSectionsPending = true;
}
}
void FSequencerSelection::AddToSelection(TSharedRef<FSequencerDisplayNode> OutlinerNode)
{
++SerialNumber;
SelectedOutlinerNodes.Add(OutlinerNode);
if ( IsBroadcasting() )
{
OnOutlinerNodeSelectionChanged.Broadcast();
OnOutlinerNodeSelectionChangedObjectGuids.Broadcast();
}
EmptySelectedKeys();
EmptySelectedSections();
EmptyNodesWithSelectedKeysOrSections();
}
void FSequencerSelection::AddToSelection(const TArray<TSharedRef<FSequencerDisplayNode>>& OutlinerNodes)
{
++SerialNumber;
SelectedOutlinerNodes.Append(OutlinerNodes);
if (IsBroadcasting())
{
OnOutlinerNodeSelectionChanged.Broadcast();
OnOutlinerNodeSelectionChangedObjectGuids.Broadcast();
}
EmptySelectedKeys();
EmptySelectedSections();
EmptyNodesWithSelectedKeysOrSections();
}
void FSequencerSelection::AddToNodesWithSelectedKeysOrSections(TSharedRef<FSequencerDisplayNode> OutlinerNode)
{
++SerialNumber;
NodesWithSelectedKeysOrSections.Add(OutlinerNode);
if ( IsBroadcasting() )
{
++SerialNumber;
OnNodesWithSelectedKeysOrSectionsChanged.Broadcast();
OnOutlinerNodeSelectionChangedObjectGuids.Broadcast();
}
}
void FSequencerSelection::RemoveFromSelection(const FSequencerSelectedKey& Key)
{
++SerialNumber;
SelectedKeys.Remove(Key);
if ( IsBroadcasting() )
{
OnKeySelectionChanged.Broadcast();
}
}
void FSequencerSelection::RemoveFromSelection(UMovieSceneSection* Section)
{
++SerialNumber;
SelectedSections.Remove(Section);
if ( IsBroadcasting() )
{
OnSectionSelectionChanged.Broadcast();
}
}
void FSequencerSelection::RemoveFromSelection(TSharedRef<FSequencerDisplayNode> OutlinerNode)
{
++SerialNumber;
SelectedOutlinerNodes.Remove(OutlinerNode);
if ( IsBroadcasting() )
{
OnOutlinerNodeSelectionChanged.Broadcast();
}
}
void FSequencerSelection::RemoveFromNodesWithSelectedKeysOrSections(TSharedRef<FSequencerDisplayNode> OutlinerNode)
{
++SerialNumber;
NodesWithSelectedKeysOrSections.Remove(OutlinerNode);
if ( IsBroadcasting() )
{
OnNodesWithSelectedKeysOrSectionsChanged.Broadcast();
}
}
bool FSequencerSelection::IsSelected(const FSequencerSelectedKey& Key) const
{
return SelectedKeys.Contains(Key);
}
bool FSequencerSelection::IsSelected(UMovieSceneSection* Section) const
{
return SelectedSections.Contains(Section);
}
bool FSequencerSelection::IsSelected(TSharedRef<FSequencerDisplayNode> OutlinerNode) const
{
return SelectedOutlinerNodes.Contains(OutlinerNode);
}
bool FSequencerSelection::NodeHasSelectedKeysOrSections(TSharedRef<FSequencerDisplayNode> OutlinerNode) const
{
return NodesWithSelectedKeysOrSections.Contains(OutlinerNode);
}
void FSequencerSelection::Empty()
{
++SerialNumber;
EmptySelectedKeys();
EmptySelectedSections();
EmptySelectedOutlinerNodes();
EmptyNodesWithSelectedKeysOrSections();
}
void FSequencerSelection::EmptySelectedKeys()
{
if (!SelectedKeys.Num())
{
return;
}
++SerialNumber;
SelectedKeys.Empty();
if ( IsBroadcasting() )
{
OnKeySelectionChanged.Broadcast();
}
}
void FSequencerSelection::EmptySelectedSections()
{
if (!SelectedSections.Num())
{
return;
}
++SerialNumber;
SelectedSections.Empty();
if ( IsBroadcasting() )
{
OnSectionSelectionChanged.Broadcast();
}
}
void FSequencerSelection::EmptySelectedOutlinerNodes()
{
if (!SelectedOutlinerNodes.Num())
{
return;
}
++SerialNumber;
SelectedOutlinerNodes.Empty();
if ( IsBroadcasting() )
{
OnOutlinerNodeSelectionChanged.Broadcast();
}
}
void FSequencerSelection::EmptyNodesWithSelectedKeysOrSections()
{
if (!NodesWithSelectedKeysOrSections.Num())
{
return;
}
++SerialNumber;
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::EmptySelectedOutlinerNodesWithoutSections(const TArray<UMovieSceneSection*>& Sections)
{
TSet<TSharedRef<FSequencerDisplayNode>> LocalSelectedOutlinerNodes = SelectedOutlinerNodes;
SuspendBroadcast();
bool bRemoved = false;
for (auto SelectedOutlinerNode : LocalSelectedOutlinerNodes)
{
TSet<TSharedRef<FSequencerDisplayNode> > TrunkNodes;
TrunkNodes.Add(SelectedOutlinerNode);
SequencerHelpers::GetDescendantNodes(SelectedOutlinerNode, TrunkNodes);
bool bFoundMatch = false;
for (auto TrunkIt = TrunkNodes.CreateConstIterator(); TrunkIt && !bFoundMatch; ++TrunkIt)
{
TSet<TWeakObjectPtr<UMovieSceneSection>> AllSections;
SequencerHelpers::GetAllSections(*TrunkIt, AllSections);
for (auto SectionIt = AllSections.CreateConstIterator(); SectionIt && !bFoundMatch; ++SectionIt)
{
if (Sections.Contains(*SectionIt))
{
bFoundMatch = true;
break;
}
}
}
if (!bFoundMatch)
{
RemoveFromSelection(SelectedOutlinerNode);
bRemoved = true;
}
}
ResumeBroadcast();
if (bRemoved)
{
++SerialNumber;
OnOutlinerNodeSelectionChanged.Broadcast();
}
}
void FSequencerSelection::RequestOutlinerNodeSelectionChangedBroadcast()
{
bOutlinerNodeSelectionChangedBroadcastPending = true;
}
void FSequencerSelection::Tick()
{
if ( bOutlinerNodeSelectionChangedBroadcastPending && IsBroadcasting() )
{
bOutlinerNodeSelectionChangedBroadcastPending = false;
OnOutlinerNodeSelectionChanged.Broadcast();
}
if ( bEmptySelectedOutlinerNodesWithSectionsPending && IsBroadcasting() )
{
bEmptySelectedOutlinerNodesWithSectionsPending = false;
TArray<UMovieSceneSection*> Sections;
for (TWeakObjectPtr<UMovieSceneSection> SelectedSection : SelectedSections)
{
if (SelectedSection.IsValid())
{
Sections.Add(SelectedSection.Get());
}
}
for (FSequencerSelectedKey SelectedKey : SelectedKeys)
{
if (SelectedKey.IsValid() && !Sections.Contains(SelectedKey.Section))
{
Sections.Add(SelectedKey.Section);
}
}
EmptySelectedOutlinerNodesWithoutSections(Sections);
}
}