void FSequencerNodeTree::Update() { // @todo Sequencer - This update pass is too aggressive. Some nodes may still be valid Empty(); UMovieScene* MovieScene = Sequencer.GetFocusedMovieScene(); // Get the master tracks so we can get sections from them const TArray<UMovieSceneTrack*>& MasterTracks = MovieScene->GetMasterTracks(); for( int32 TrackIndex = 0; TrackIndex < MasterTracks.Num(); ++TrackIndex ) { UMovieSceneTrack& Track = *MasterTracks[TrackIndex]; TSharedRef<FTrackNode> SectionNode = MakeShareable( new FTrackNode( Track.GetTrackName(), Track, NULL, *this ) ); RootNodes.Add( SectionNode ); MakeSectionInterfaces( Track, SectionNode ); SectionNode->PinNode(); } const TArray<FMovieSceneObjectBinding>& ObjectBindings = MovieScene->GetObjectBindings(); // Make nodes for all object bindings for( int32 BindingIndex = 0; BindingIndex < ObjectBindings.Num(); ++BindingIndex ) { TSharedRef<FObjectBindingNode> ObjectBindingNode = AddObjectBinding( ObjectBindings[BindingIndex].GetDisplayName(), ObjectBindings[BindingIndex].GetObjectGuid() ); const TArray<UMovieSceneTrack*>& Tracks = ObjectBindings[BindingIndex].GetTracks(); for( int32 TrackIndex = 0; TrackIndex < Tracks.Num(); ++TrackIndex ) { UMovieSceneTrack& Track = *Tracks[TrackIndex]; FName SectionName = Track.GetTrackName(); check( SectionName != NAME_None ); TSharedRef<FTrackNode> SectionAreaNode = ObjectBindingNode->AddSectionAreaNode( SectionName, Track ); MakeSectionInterfaces( Track, SectionAreaNode ); } } struct FRootNodeSorter { bool operator()( const TSharedRef<FSequencerDisplayNode>& A, const TSharedRef<FSequencerDisplayNode>& B ) const { return A->GetType() == ESequencerNode::Object ? false : true; } }; // Sort so that master tracks appear before object tracks RootNodes.Sort( FRootNodeSorter() ); // Re-filter the tree after updating // @todo Sequencer - Newly added sections may need to be visible even when there is a filter FilterNodes( FilterString ); }
void SDetailsViewBase::UpdateFilteredDetails() { auto RootPropertyNode = GetRootNode(); if (RootPropertyNode.IsValid()) { RootPropertyNode->FilterNodes(CurrentFilter.FilterStrings); RootPropertyNode->ProcessSeenFlags(true); for (int32 NodeIndex = 0; NodeIndex < ExternalRootPropertyNodes.Num(); ++NodeIndex) { TSharedPtr<FPropertyNode> PropertyNode = ExternalRootPropertyNodes[NodeIndex].Pin(); if (PropertyNode.IsValid()) { PropertyNode->FilterNodes(CurrentFilter.FilterStrings); PropertyNode->ProcessSeenFlags(true); } } if (DetailLayout.IsValid()) { DetailLayout->FilterDetailLayout(CurrentFilter); } RootTreeNodes = DetailLayout->GetRootTreeNodes(); } RefreshTree(); }
void FSequencerNodeTree::Update() { // @todo Sequencer - This update pass is too aggressive. Some nodes may still be valid Empty(); UMovieScene* MovieScene = Sequencer.GetFocusedMovieSceneSequence()->GetMovieScene(); TArray< TSharedRef<FSequencerDisplayNode> > NewRootNodes; // Get the master tracks so we can get sections from them const TArray<UMovieSceneTrack*>& MasterTracks = MovieScene->GetMasterTracks(); for( UMovieSceneTrack* Track : MasterTracks ) { UMovieSceneTrack& TrackRef = *Track; TSharedRef<FTrackNode> SectionNode = MakeShareable( new FTrackNode( TrackRef.GetTrackName(), TrackRef, NULL, *this ) ); NewRootNodes.Add( SectionNode ); MakeSectionInterfaces( TrackRef, SectionNode ); SectionNode->PinNode(); } const TArray<FMovieSceneBinding>& Bindings = MovieScene->GetBindings(); TMap<FGuid, const FMovieSceneBinding*> GuidToBindingMap; for (const FMovieSceneBinding& Binding : Bindings) { GuidToBindingMap.Add(Binding.GetObjectGuid(), &Binding); } // Make nodes for all object bindings TArray< TSharedRef<FSequencerDisplayNode> > NewObjectNodes; for( const FMovieSceneBinding& Binding : Bindings ) { TSharedRef<FObjectBindingNode> ObjectBindingNode = AddObjectBinding( Binding.GetName(), Binding.GetObjectGuid(), GuidToBindingMap, NewObjectNodes ); const TArray<UMovieSceneTrack*>& Tracks = Binding.GetTracks(); for( UMovieSceneTrack* Track : Tracks ) { UMovieSceneTrack& TrackRef = *Track; FName SectionName = TrackRef.GetTrackName(); check( SectionName != NAME_None ); TSharedRef<FTrackNode> SectionAreaNode = ObjectBindingNode->AddSectionAreaNode( SectionName, TrackRef ); MakeSectionInterfaces( TrackRef, SectionAreaNode ); } } struct FObjectNodeSorter { bool operator()( const TSharedRef<FSequencerDisplayNode>& A, const TSharedRef<FSequencerDisplayNode>& B ) const { if (A->GetType() == ESequencerNode::Object && B->GetType() != ESequencerNode::Object) { return true; } if (A->GetType() != ESequencerNode::Object && B->GetType() == ESequencerNode::Object) { return false; } return A->GetDisplayName().ToString() < B->GetDisplayName().ToString(); } }; NewObjectNodes.Sort( FObjectNodeSorter() ); for (TSharedRef<FSequencerDisplayNode> NewObjectNode : NewObjectNodes) { NewObjectNode->SortChildNodes(FObjectNodeSorter()); } NewRootNodes.Append(NewObjectNodes); // Look for a shot track. It will always come first if it exists UMovieSceneTrack* ShotTrack = MovieScene->GetShotTrack(); if( ShotTrack ) { TSharedRef<FTrackNode> SectionNode = MakeShareable( new FTrackNode( ShotTrack->GetTrackName(), *ShotTrack, NULL, *this ) ); // Shot track always comes first RootNodes.Add( SectionNode ); MakeSectionInterfaces( *ShotTrack, SectionNode ); SectionNode->PinNode(); } // Add all other nodes after the shot track RootNodes.Append( NewRootNodes ); // Set up virtual offsets, and expansion states float VerticalOffset = 0.f; for (auto& Node : RootNodes) { Node->Traverse_ParentFirst([&](FSequencerDisplayNode& InNode){ float VerticalTop = VerticalOffset; VerticalOffset += InNode.GetNodeHeight() + InNode.GetNodePadding().Combined(); InNode.Initialize(VerticalTop, VerticalOffset); return true; }); } // Re-filter the tree after updating // @todo Sequencer - Newly added sections may need to be visible even when there is a filter FilterNodes( FilterString ); }
ALERROR CConquerNodesProc::OnProcess (CSystemMap *pMap, CTopology &Topology, CTopologyNodeList &NodeList, CString *retsError) // OnProcess // // Process on topology { ALERROR error; int i; // If no conquerors, then we're done int iConquerorCount = m_Conquerors.GetCount(); if (iConquerorCount == 0) return NOERROR; // If we have a criteria, the filter the nodes CTopologyNodeList FilteredNodeList; CTopologyNodeList *pNodeList = FilterNodes(Topology, m_Criteria, NodeList, FilteredNodeList); if (pNodeList == NULL) { *retsError = CONSTLIT("Error filtering nodes"); return ERR_FAIL; } // We mark nodes that are available for us // (So we first save the marks) TArray<bool> SavedMarks; SaveAndMarkNodes(Topology, *pNodeList, &SavedMarks); // Initialize some conqueror temporaries for (i = 0; i < m_Conquerors.GetCount(); i++) { m_Conquerors[i].iSeedCount = 0; m_Conquerors[i].iNodeCount = 0; } // We keep a structure for each seed TArray<SSeed> Seeds; // Loop until we have placed all nodes in a partition int iMaxRounds = 10000; int iRounds = 0; int iNodesLeft = pNodeList->GetCount(); while (iNodesLeft > 0 && iRounds < iMaxRounds) { // See if any conqueror adds a new seed for (i = 0; i < m_Conquerors.GetCount(); i++) { SConqueror *pConqueror = &m_Conquerors[i]; if ((pConqueror->iMaxSeeds == -1 || pConqueror->iSeedCount < pConqueror->iMaxSeeds) && (pConqueror->iMaxNodes == -1 || pConqueror->iNodeCount < pConqueror->iMaxNodes) && (mathRandom(1, 100) <= pConqueror->iSeedChance)) { // Pick a random available node CTopologyNode *pNewNode = ChooseRandomNode(*pNodeList, GetSeedWeightTable(pConqueror)); if (pNewNode == NULL) continue; // Add a seed SSeed *pNewSeed = Seeds.Insert(); pNewSeed->pConqueror = pConqueror; // Node is conquered ConquerNode(pConqueror, pNewSeed, pNewNode); iNodesLeft--; } } // Now expand each seed for (i = 0; i < Seeds.GetCount(); i++) { SSeed *pSeed = &Seeds[i]; SConqueror *pConqueror = pSeed->pConqueror; // Compute the chance that this seed will expand int iExpandChance = pConqueror->iExpandChance; // See if we expand if ((pConqueror->iMaxNodes == -1 || pConqueror->iNodeCount < pConqueror->iMaxNodes) && (mathRandom(1, 100) <= iExpandChance)) { // Generate a list of all available adjacent nodes CTopologyNodeList NodesAvail; CalcAdjacentNodes(pSeed->Nodes, &NodesAvail); // Pick a random node CTopologyNode *pNewNode = ChooseRandomNode(NodesAvail, GetExpandWeightTable(pConqueror)); if (pNewNode == NULL) continue; // Expand ConquerNode(pConqueror, pSeed, pNewNode); iNodesLeft--; } } iRounds++; } // Run the processor on all seeds for (i = 0; i < Seeds.GetCount(); i++) { SSeed *pSeed = &Seeds[i]; if (error = pSeed->pConqueror->pProc->Process(pMap, Topology, pSeed->Nodes, retsError)) return error; } // Remove from the original node list if (pNodeList == &NodeList && iNodesLeft == 0) NodeList.DeleteAll(); else { for (i = 0; i < pNodeList->GetCount(); i++) NodeList.Delete(pNodeList->GetAt(i)); } // Done RestoreMarks(Topology, SavedMarks); return NOERROR; }