Example #1
0
FKeyAreaLayout::FKeyAreaLayout(FSequencerDisplayNode& InNode, int32 InSectionIndex)
{
	TotalHeight = 0.f;

	float LastPadding = 0.f;

	auto SetupKeyArea = [&](FSequencerDisplayNode& Node){

		if (Node.GetType() == ESequencerNode::KeyArea)
		{
			Elements.Add(FKeyAreaLayoutElement::FromKeyAreaNode(StaticCastSharedRef<FSectionKeyAreaNode>(Node.AsShared()), InSectionIndex, TotalHeight));
		}
		else if (!Node.IsExpanded())
		{
			Elements.Add(FKeyAreaLayoutElement::FromGroup(Node.UpdateKeyGrouping(InSectionIndex), TotalHeight, Node.GetNodeHeight()));
		}

	};


	// First, layout the parent
	{
		FSequencerDisplayNode* LayoutNode = &InNode;
		if (InNode.GetType() == ESequencerNode::Track)
		{
			TSharedPtr<FSequencerDisplayNode> KeyAreaNode = static_cast<FTrackNode&>(InNode).GetTopLevelKeyNode();
			if (KeyAreaNode.IsValid())
			{
				LayoutNode = KeyAreaNode.Get();
			}
		}

		SetupKeyArea(*LayoutNode);

		LastPadding = LayoutNode->GetNodePadding().Bottom;
		TotalHeight += LayoutNode->GetNodeHeight() + LastPadding;
	}

	// Then any children
	InNode.TraverseVisible_ParentFirst([&](FSequencerDisplayNode& Node){
		
		TotalHeight += Node.GetNodePadding().Top;

		SetupKeyArea(Node);

		LastPadding = Node.GetNodePadding().Bottom;
		TotalHeight += Node.GetNodeHeight() + LastPadding;
		return true;

	}, false);

	// Remove the padding from the bottom
	TotalHeight -= LastPadding;
}
TSharedPtr<FSequencerTrackNode> GetParentTrackNode(FSequencerDisplayNode& In)
{
	FSequencerDisplayNode* Current = &In;
	while(Current && Current->GetType() != ESequencerNode::Object)
	{
		if (Current->GetType() == ESequencerNode::Track)
		{
			return StaticCastSharedRef<FSequencerTrackNode>(Current->AsShared());
		}
		Current = Current->GetParent().Get();
	}

	return nullptr;
}
void FSequencerNodeTree::SaveExpansionState( const FSequencerDisplayNode& Node, bool bExpanded )
{	
	UMovieScene* MovieScene = Sequencer.GetFocusedMovieScene();

	FMovieSceneEditorData& EditorData = MovieScene->GetEditorData();

	if( bExpanded )
	{
		EditorData.CollapsedSequencerNodes.Remove( Node.GetPathName() );
	}
	else
	{
		// Collapsed nodes are stored instead of expanded so that new nodes are expanded by default
		EditorData.CollapsedSequencerNodes.AddUnique( Node.GetPathName() ) ;
	}

}
void FSequencerNodeTree::SaveExpansionState( const FSequencerDisplayNode& Node, bool bExpanded )
{	
	// @todo Sequencer - This should be moved to the sequence level
	UMovieScene* MovieScene = Sequencer.GetFocusedMovieSceneSequence()->GetMovieScene();

	FMovieSceneEditorData& EditorData = MovieScene->GetEditorData();

	EditorData.ExpansionStates.Add( Node.GetPathName(), FMovieSceneExpansionState(bExpanded) );
}
bool FSequencerNodeTree::GetSavedExpansionState( const FSequencerDisplayNode& Node ) const
{
	// @todo Sequencer - This should be moved to the sequence level
	UMovieScene* MovieScene = Sequencer.GetFocusedMovieSceneSequence()->GetMovieScene();

	FMovieSceneEditorData& EditorData = MovieScene->GetEditorData();
	FMovieSceneExpansionState* ExpansionState = EditorData.ExpansionStates.Find( Node.GetPathName() );

	return ExpansionState ? ExpansionState->bExpanded : GetDefaultExpansionState(Node);
}
bool FSequencerNodeTree::GetSavedExpansionState( const FSequencerDisplayNode& Node ) const
{
	UMovieScene* MovieScene = Sequencer.GetFocusedMovieScene();

	FMovieSceneEditorData& EditorData = MovieScene->GetEditorData();

	// Collapsed nodes are stored instead of expanded so that new nodes are expanded by default
	bool bCollapsed = EditorData.CollapsedSequencerNodes.Contains( Node.GetPathName() );

	return !bCollapsed;
}
FGroupedKeyArea::FGroupedKeyArea(FSequencerDisplayNode& InNode, int32 InSectionIndex)
	: Section(nullptr)
{
	// Calling this virtual function is safe here, as it's just called through standard name-lookup, not runtime dispatch
	FGroupedKeyCollection::InitializeRecursive(InNode, InSectionIndex);

	for (const TSharedPtr<IKeyArea>& KeyArea : KeyAreas)
	{
		auto* OwningSection = KeyArea->GetOwningSection();
		// Ensure they all belong to the same section
		ensure(!Section || Section == OwningSection);
		Section = OwningSection;
	}

	if (Section)
	{
		IndexKey = FIndexKey(InNode.GetPathName(), Section);
		UpdateIndex();
	}
}
void FGroupedKeyCollection::InitializeRecursive(FSequencerDisplayNode& InNode, int32 InSectionIndex, float DuplicateThreshold)
{
	KeyAreas.Reset();
	Groups.Reset();

	TArray<TSharedRef<FSequencerSectionKeyAreaNode>> AllKeyAreaNodes;
	AllKeyAreaNodes.Reserve(36);
	InNode.GetChildKeyAreaNodesRecursively(AllKeyAreaNodes);

	for (const auto& Node : AllKeyAreaNodes)
	{
		TSharedPtr<IKeyArea> KeyArea = Node->GetKeyArea(InSectionIndex);
		if (KeyArea.IsValid())
		{
			AddKeyArea(KeyArea.ToSharedRef());
		}
	}

	RemoveDuplicateKeys(DuplicateThreshold);
}
FSectionLayout::FSectionLayout(FSequencerDisplayNode& InNode, int32 InSectionIndex)
{
	float VerticalOffset = 0.f;

	auto SetupKeyArea = [&](FSequencerDisplayNode& Node){

		if (Node.GetType() == ESequencerNode::KeyArea)
		{
			Elements.Add(FSectionLayoutElement::FromKeyAreaNode(
				StaticCastSharedRef<FSequencerSectionKeyAreaNode>(Node.AsShared()),
				InSectionIndex,
				VerticalOffset
			));
		}
		else if (Node.GetType() == ESequencerNode::Track && static_cast<FSequencerTrackNode&>(Node).GetTopLevelKeyNode().IsValid())
		{
			Elements.Add(FSectionLayoutElement::FromTrack(
				StaticCastSharedRef<FSequencerTrackNode>(Node.AsShared()),
				InSectionIndex,
				VerticalOffset
			));
		}
		else if (!Node.IsExpanded())
		{
			Elements.Add(FSectionLayoutElement::FromGroup(
				Node.AsShared(),
				Node.UpdateKeyGrouping(InSectionIndex),
				VerticalOffset
			));
		}
		else
		{
			// It's benign space
			Elements.Add(FSectionLayoutElement::EmptySpace(
				Node.AsShared(),
				VerticalOffset
			));
		}

	};

	// First, layout the parent
	{
		VerticalOffset += InNode.GetNodePadding().Top;

		SetupKeyArea(InNode);

		VerticalOffset += InNode.GetNodeHeight() + InNode.GetNodePadding().Bottom;
	}

	// Then any children
	InNode.TraverseVisible_ParentFirst([&](FSequencerDisplayNode& Node){
		
		VerticalOffset += Node.GetNodePadding().Top;

		SetupKeyArea(Node);

		VerticalOffset += Node.GetNodeHeight() + Node.GetNodePadding().Bottom;
		return true;

	}, false);
}
bool FSequencerNodeTree::GetDefaultExpansionState( const FSequencerDisplayNode& Node ) const
{
	// For now, all types except categories and key areas are expanded by default
	return Node.GetType() != ESequencerNode::Category && Node.GetType() != ESequencerNode::KeyArea;
}
bool FSequencerNodeTree::GetDefaultExpansionState( const FSequencerDisplayNode& Node ) const
{
	// For now, only object nodes are expanded by default
	return Node.GetType() == ESequencerNode::Object;
}