TSharedRef<FObjectBindingNode> FSequencerNodeTree::AddObjectBinding(const FString& ObjectName, const FGuid& ObjectBinding, TMap<FGuid, const FMovieSceneBinding*>& GuidToBindingMap, TArray< TSharedRef<FSequencerDisplayNode> >& OutNodeList) { TSharedPtr<FObjectBindingNode> ObjectNode; TSharedPtr<FObjectBindingNode>* FoundObjectNode = ObjectBindingMap.Find(ObjectBinding); if (FoundObjectNode != nullptr) { ObjectNode = *FoundObjectNode; } else { // The node name is the object guid FName ObjectNodeName = *ObjectBinding.ToString(); // Try to get the parent object node if there is one. TSharedPtr<FObjectBindingNode> ParentNode; TArray<UObject*> RuntimeObjects; UMovieSceneSequence* Animation = Sequencer.GetFocusedMovieSceneSequence(); UObject* RuntimeObject = Animation->FindObject(ObjectBinding); if ( RuntimeObject != nullptr) { UObject* ParentObject = Animation->GetParentObject(RuntimeObject); if (ParentObject != nullptr) { FGuid ParentBinding = Animation->FindObjectId(*ParentObject); TSharedPtr<FObjectBindingNode>* FoundParentNode = ObjectBindingMap.Find( ParentBinding ); if ( FoundParentNode != nullptr ) { ParentNode = *FoundParentNode; } else { const FMovieSceneBinding** FoundParentMovieSceneBinding = GuidToBindingMap.Find( ParentBinding ); if ( FoundParentMovieSceneBinding != nullptr ) { ParentNode = AddObjectBinding( (*FoundParentMovieSceneBinding)->GetName(), ParentBinding, GuidToBindingMap, OutNodeList ); } } } } // Create the node. ObjectNode = MakeShareable( new FObjectBindingNode( ObjectNodeName, ObjectName, ObjectBinding, ParentNode, *this ) ); if (ParentNode.IsValid()) { ParentNode->AddObjectBindingNode(ObjectNode.ToSharedRef()); } else { OutNodeList.Add( ObjectNode.ToSharedRef() ); } // Map the guid to the object binding node for fast lookup later ObjectBindingMap.Add( ObjectBinding, ObjectNode ); } return ObjectNode.ToSharedRef(); }
void FColorPropertySection::ConsolidateColorCurves( TArray< TKeyValuePair<float, FLinearColor> >& OutColorKeys, const UMovieSceneColorSection* Section ) const { // Get the default color of the first instance FLinearColor DefaultColor( 0.0f, 0.0f, 0.0f, 0.0f ); static const FName SlateColorName( "SlateColor" ); UMovieSceneSequence* Sequence = Sequencer->GetFocusedMovieSceneSequence(); const TArray<FMovieSceneBinding>& MovieSceneBindings = Sequence->GetMovieScene()->GetBindings(); bool bFoundColor = false; for ( int32 BindingIndex = 0; BindingIndex < MovieSceneBindings.Num() && !bFoundColor; ++BindingIndex ) { const FMovieSceneBinding& MovieSceneBinding = MovieSceneBindings[BindingIndex]; for ( int32 TrackIndex = 0; TrackIndex < MovieSceneBinding.GetTracks().Num() && !bFoundColor; ++TrackIndex ) { if ( MovieSceneBinding.GetTracks()[TrackIndex] == Track ) { UObject* RuntimeObject = Sequence->FindObject( MovieSceneBinding.GetObjectGuid() ); if ( RuntimeObject != nullptr ) { UProperty* Property = RuntimeObject->GetClass()->FindPropertyByName( CastChecked<UMovieSceneColorTrack>( Track )->GetPropertyName() ); UStructProperty* ColorStructProp = Cast<UStructProperty>( Property ); if ( ColorStructProp && ColorStructProp->Struct ) { if ( ColorStructProp->Struct->GetFName() == SlateColorName ) { DefaultColor = (*Property->ContainerPtrToValuePtr<FSlateColor>( RuntimeObject )).GetSpecifiedColor(); } else if ( ColorStructProp->Struct->GetFName() == NAME_LinearColor ) { DefaultColor = *Property->ContainerPtrToValuePtr<FLinearColor>( RuntimeObject ); } else { DefaultColor = Property->ContainerPtrToValuePtr<FColor>( RuntimeObject )->ReinterpretAsLinear(); } bFoundColor = true; break; } } } } } // @todo Sequencer Optimize - This could all get cached, instead of recalculating everything every OnPaint const FRichCurve* Curves[4] = { &Section->GetRedCurve(), &Section->GetGreenCurve(), &Section->GetBlueCurve(), &Section->GetAlphaCurve() }; // @todo Sequencer Optimize - This is a O(n^2) loop! // Our times are floats, which means we can't use a map and // do a quick lookup to see if the keys already exist // because the keys are ordered, we could take advantage of that, however TArray<float> TimesWithKeys; for ( int32 i = 0; i < 4; ++i ) { const FRichCurve* Curve = Curves[i]; for ( auto It( Curve->GetKeyIterator() ); It; ++It ) { float KeyTime = It->Time; bool bShouldAddKey = true; int32 InsertKeyIndex = INDEX_NONE; for ( int32 k = 0; k < TimesWithKeys.Num(); ++k ) { if ( FMath::IsNearlyEqual( TimesWithKeys[k], KeyTime ) ) { bShouldAddKey = false; break; } else if ( TimesWithKeys[k] > KeyTime ) { InsertKeyIndex = k; break; } } if ( InsertKeyIndex == INDEX_NONE && bShouldAddKey ) { InsertKeyIndex = TimesWithKeys.Num(); } if ( bShouldAddKey ) { TimesWithKeys.Insert( KeyTime, InsertKeyIndex ); } } } // @todo Sequencer Optimize - This another O(n^2) loop, since Eval is O(n)! for ( int32 i = 0; i < TimesWithKeys.Num(); ++i ) { OutColorKeys.Add( TKeyValuePair<float, FLinearColor>( TimesWithKeys[i], Section->Eval( TimesWithKeys[i], DefaultColor ) ) ); } }