// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Array.h" #include "Containers/ArrayView.h" #include "Containers/Map.h" #include "Containers/Set.h" #include "Containers/UnrealString.h" #include "CoreMinimal.h" #include "CoreTypes.h" #include "Delegates/Delegate.h" #include "EditorSequenceNavigationDefs.h" #include "EventHandlers/MovieSceneDataEventContainer.h" #include "Decorations/MovieSceneDecorationContainer.h" #include "HAL/PlatformCrt.h" #include "Internationalization/Text.h" #include "Math/Color.h" #include "Math/Range.h" #include "Misc/FrameNumber.h" #include "Misc/FrameRate.h" #include "Misc/Guid.h" #include "MovieSceneBinding.h" #include "MovieSceneFrameMigration.h" #include "MovieSceneFwd.h" #include "MovieSceneMarkedFrame.h" #include "MovieSceneObjectBindingID.h" #include "MovieScenePossessable.h" #include "MovieSceneSequenceID.h" #include "MovieSceneSignedObject.h" #include "MovieSceneSpawnable.h" #include "MovieSceneTimeController.h" #include "MovieSceneTrack.h" #include "Templates/Casts.h" #include "Templates/SharedPointer.h" #include "Templates/SubclassOf.h" #include "Templates/UnrealTemplate.h" #include "UObject/NameTypes.h" #include "UObject/Object.h" #include "UObject/ObjectMacros.h" #include "UObject/ObjectPtr.h" #include "UObject/SoftObjectPath.h" #include "UObject/UObjectGlobals.h" #include "UObject/UnrealNames.h" #include "UObject/WeakObjectPtrTemplates.h" #include "MovieScene.generated.h" class FArchive; class FObjectPreSaveContext; class UClass; class UMovieSceneClock; class UK2Node; class UMovieSceneFolder; class UMovieSceneSection; class UMovieSceneTrack; class UMovieSceneGroupCondition; namespace UE { namespace MovieScene { class ISequenceDataEventHandler; } } struct FMovieSceneChannelMetaData; struct FMovieSceneTimeController; struct FMovieSceneTimecodeSource; template class TFunctionRef; //delegates for use when some data in the MovieScene changes, WIP right now, hopefully will replace delegates on ISequencer //and be used for moving towards a true MVC system DECLARE_MULTICAST_DELEGATE_TwoParams(FMovieSceneOnChannelChanged, const FMovieSceneChannelMetaData* MetaData, UMovieSceneSection*) /** @todo: remove this type when support for intrinsics on TMap values is added? */ USTRUCT() struct FMovieSceneExpansionState { GENERATED_BODY() FMovieSceneExpansionState(bool bInExpanded = true) : bExpanded(bInExpanded) {} UPROPERTY() bool bExpanded; }; /** * Editor only data that needs to be saved between sessions for editing but has no runtime purpose */ USTRUCT() struct FMovieSceneEditorData { GENERATED_USTRUCT_BODY() FMovieSceneEditorData() : ViewStart(0.0), ViewEnd(0.0) , WorkStart(0.0), WorkEnd(0.0) {} TRange GetViewRange() const { return TRange(ViewStart, ViewEnd); } TRange GetWorkingRange() const { return TRange(WorkStart, WorkEnd); } /** Map of node path -> expansion state. */ UPROPERTY() TMap ExpansionStates; /** List of Pinned nodes. */ UPROPERTY() TArray PinnedNodes; /** The last view-range start that the user was observing */ UPROPERTY() double ViewStart; /** The last view-range end that the user was observing */ UPROPERTY() double ViewEnd; /** User-defined working range start in which the entire sequence should reside. */ UPROPERTY() double WorkStart; /** User-defined working range end in which the entire sequence should reside. */ UPROPERTY() double WorkEnd; /** Deprecated */ UPROPERTY() TSet MarkedFrames_DEPRECATED; UPROPERTY() FFloatRange WorkingRange_DEPRECATED; UPROPERTY() FFloatRange ViewRange_DEPRECATED; /** Saved Navigation Tool state to restore */ UPROPERTY() FNavigationToolSaveState NavigationToolState; /** Nodes currently marked Solo, stored as node tree paths */ UPROPERTY(Transient) TArray SoloNodes; /** Nodes currently marked Mute, stored as node tree paths */ UPROPERTY(Transient) TArray MuteNodes; }; /** * Structure for labels that can be assigned to movie scene tracks. */ USTRUCT() struct FMovieSceneTrackLabels { GENERATED_BODY() UPROPERTY() TArray Strings; void FromString(const FString& LabelString) { LabelString.ParseIntoArray(Strings, TEXT(" ")); } FString ToString() const { return FString::Join(Strings, TEXT(" ")); } }; /** * Structure that comprises a list of object binding IDs */ USTRUCT() struct FMovieSceneObjectBindingIDs { GENERATED_BODY() UPROPERTY() TArray IDs; }; /** * Structure that represents a group of sections */ USTRUCT() struct FMovieSceneSectionGroup { GENERATED_BODY() public: /* @return Whether the section is part of this group */ MOVIESCENE_API bool Contains(const UMovieSceneSection& Section) const; /* Add the section to this group */ MOVIESCENE_API void Add(UMovieSceneSection& Section); /* Remove the section from this group */ MOVIESCENE_API void Remove(const UMovieSceneSection& Section); /* Add all members of a group to this group */ MOVIESCENE_API void Append(const FMovieSceneSectionGroup& SectionGroup); /* Removes any sections which the pointers are stale or otherwise not valid */ MOVIESCENE_API void Clean(); int32 Num() const { return Sections.Num(); } protected: UPROPERTY() TArray > Sections; public: /** * Comparison operators * We only need these for being stored in a container, to check if it's the same object. * Not intended for direct use. */ FORCEINLINE bool operator==(const FMovieSceneSectionGroup& Other) const { return &Sections == &Other.Sections; } FORCEINLINE bool operator!=(const FMovieSceneSectionGroup& Other) const { return &Sections != &Other.Sections; } /** * DO NOT USE DIRECTLY * STL-like iterators to enable range-based for loop support. */ FORCEINLINE TArray >::RangedForIteratorType begin() { return Sections.begin(); } FORCEINLINE TArray >::RangedForConstIteratorType begin() const { return Sections.begin(); } FORCEINLINE TArray >::RangedForIteratorType end() { return Sections.end(); } FORCEINLINE TArray >::RangedForConstIteratorType end() const { return Sections.end(); } }; /** * Structure that represents a group of nodes */ UCLASS(MinimalAPI) class UMovieSceneNodeGroup : public UObject { GENERATED_BODY() virtual bool IsEditorOnly() const override { return true; } #if WITH_EDITORONLY_DATA public: const FName GetName() const { return Name; } MOVIESCENE_API void SetName(const FName& Name); MOVIESCENE_API void AddNode(const FString& Path); MOVIESCENE_API void RemoveNode(const FString& Path); TArrayView GetNodes() { return Nodes; } MOVIESCENE_API bool ContainsNode(const FString& Path) const; MOVIESCENE_API void UpdateNodePath(const FString& OldPath, const FString& NewPath); bool GetEnableFilter() const { return bEnableFilter; } MOVIESCENE_API void SetEnableFilter(bool bInEnableFilter); /** Event that is triggered whenever this node group has changed */ DECLARE_EVENT(UMovieSceneNodeGroup, FOnNodeGroupChanged) FOnNodeGroupChanged& OnNodeGroupChanged() { return OnNodeGroupChangedEvent; } private: UPROPERTY() FName Name; /** Nodes that are part of this node group, stored as node tree paths */ UPROPERTY() TArray Nodes; /** Whether sequencer should filter to only show this nodes in this group */ bool bEnableFilter; /** Event that is triggered whenever this node group has changed */ FOnNodeGroupChanged OnNodeGroupChangedEvent; /** * Comparison operators * We only need these for being stored in a container, to check if it's the same object. * Not intended for direct use. */ FORCEINLINE bool operator==(const UMovieSceneNodeGroup& Other) const { return &Nodes == &Other.Nodes; } FORCEINLINE bool operator!=(const UMovieSceneNodeGroup& Other) const { return &Nodes != &Other.Nodes; } #endif }; /** * Structure that represents a collection of NodeGroups */ UCLASS(MinimalAPI) class UMovieSceneNodeGroupCollection : public UObject { GENERATED_BODY() virtual bool IsEditorOnly() const override { return true; } #if WITH_EDITORONLY_DATA public: /** Called after this object has been deserialized */ MOVIESCENE_API virtual void PostLoad() override; MOVIESCENE_API virtual void PostEditUndo() override; MOVIESCENE_API void AddNodeGroup(UMovieSceneNodeGroup* NodeGroup); MOVIESCENE_API void RemoveNodeGroup(UMovieSceneNodeGroup* NodeGroup); bool Contains(UMovieSceneNodeGroup* NodeGroup) const { return NodeGroups.Contains(NodeGroup); } const int32 Num() const { return NodeGroups.Num(); } bool HasAnyActiveFilter() const { return bAnyActiveFilter; } MOVIESCENE_API void UpdateNodePath(const FString& OldPath, const FString& NewPath); /** Event that is triggered whenever this collection of node groups, or an included node group, has changed */ DECLARE_EVENT(UMovieSceneNodeGroupCollection, FOnNodeGroupCollectionChanged) FOnNodeGroupCollectionChanged& OnNodeGroupCollectionChanged() { return OnNodeGroupCollectionChangedEvent; } private: MOVIESCENE_API void Refresh(); UPROPERTY() TArray> NodeGroups; bool bAnyActiveFilter; MOVIESCENE_API void OnNodeGroupChanged(); /** Event that is triggered whenever this collection of node groups, or an included node group, has changed */ FOnNodeGroupCollectionChanged OnNodeGroupCollectionChangedEvent; public: /** * DO NOT USE DIRECTLY * STL-like iterators to enable range-based for loop support. */ FORCEINLINE auto begin() { return NodeGroups.begin(); } FORCEINLINE auto begin() const { return NodeGroups.begin(); } FORCEINLINE auto end() { return NodeGroups.end(); } FORCEINLINE auto end() const { return NodeGroups.end(); } #endif }; /** * Implements a movie scene asset. */ UCLASS(DefaultToInstanced, MinimalAPI) class UMovieScene : public UMovieSceneDecorationContainerObject { GENERATED_UCLASS_BODY() public: /**~ UObject implementation */ MOVIESCENE_API virtual void Serialize( FArchive& Ar ) override; MOVIESCENE_API virtual bool IsPostLoadThreadSafe() const override; MOVIESCENE_API virtual void PostInitProperties() override; MOVIESCENE_API virtual void PostLoad() override; #if WITH_EDITORONLY_DATA static MOVIESCENE_API void DeclareConstructClasses(TArray& OutConstructClasses, const UClass* SpecificSubclass); #endif #if WITH_EDITOR MOVIESCENE_API virtual void PostEditUndo() override; #endif public: UE::MovieScene::TDataEventContainer EventHandlers; /** * Add a spawnable to this movie scene's list of owned blueprints. * * These objects are stored as "inners" of the MovieScene. * * @param Name Name of the spawnable. * @param ObjectTemplate The object template to use for the spawnable * @return Guid of the newly-added spawnable. */ MOVIESCENE_API FGuid AddSpawnable(const FString& Name, UObject& ObjectTemplate); /* * Adds an existing spawnable to this movie scene. * * @param InNewSpawnable The posssesable to add. * @param InNewBinding The object binding to add. */ MOVIESCENE_API void AddSpawnable(const FMovieSceneSpawnable& InNewSpawnable, const FMovieSceneBinding& InNewBinding); /** * Removes a spawnable from this movie scene. * * @param Guid The guid of a spawnable to find and remove. * @return true if anything was removed. */ MOVIESCENE_API bool RemoveSpawnable(const FGuid& Guid); /** * Attempt to find a spawnable using some custom predicate * * @param InPredicate A predicate to test each spawnable against * @return Spawnable object that was found (or nullptr if not found). */ MOVIESCENE_API FMovieSceneSpawnable* FindSpawnable( const TFunctionRef& InPredicate ); /** * Tries to locate a spawnable in this MovieScene for the specified spawnable GUID. * * @param Guid The spawnable guid to search for. * @return Spawnable object that was found (or nullptr if not found). */ MOVIESCENE_API FMovieSceneSpawnable* FindSpawnable(const FGuid& Guid); /** * Grabs a reference to a specific spawnable by index. * * @param Index of spawnable to return. Must be between 0 and GetSpawnableCount() * @return Returns the specified spawnable by index. */ MOVIESCENE_API FMovieSceneSpawnable& GetSpawnable(int32 Index); /** * Get the number of spawnable objects in this scene. * * @return Spawnable object count. */ MOVIESCENE_API int32 GetSpawnableCount() const; public: /** * Adds a possessable to this movie scene. * * @param Name Name of the possessable. * @param Class The class of object that will be possessed. * @return Guid of the newly-added possessable. */ MOVIESCENE_API FGuid AddPossessable(const FString& Name, UClass* Class); /* * Adds an existing possessable to this movie scene. * * @param InNewPossessable The posssesable to add. * @param InNewBinding The object binding to add. */ MOVIESCENE_API void AddPossessable(const FMovieScenePossessable& InNewPossessable, const FMovieSceneBinding& InNewBinding); /** * Removes a possessable from this movie scene. * * @param PossessableGuid Guid of possessable to remove. */ MOVIESCENE_API bool RemovePossessable(const FGuid& PossessableGuid); /* * Replace an existing possessable with another */ MOVIESCENE_API bool ReplacePossessable(const FGuid& OldGuid, const FMovieScenePossessable& InNewPosessable); /** * Tries to locate a possessable in this MovieScene for the specified possessable GUID. * * @param Guid The possessable guid to search for. * @return Possessable object that was found (or nullptr if not found). */ MOVIESCENE_API struct FMovieScenePossessable* FindPossessable(const FGuid& Guid); /** * Attempt to find a possessable using some custom prdeicate * * @param InPredicate A predicate to test each possessable against * @return Possessable object that was found (or nullptr if not found). */ MOVIESCENE_API FMovieScenePossessable* FindPossessable( const TFunctionRef& InPredicate ); /** * Grabs a reference to a specific possessable by index. * * @param Index of possessable to return. * @return Returns the specified possessable by index. */ MOVIESCENE_API FMovieScenePossessable& GetPossessable(const int32 Index); /** * Get the number of possessable objects in this scene. * * @return Possessable object count. */ MOVIESCENE_API int32 GetPossessableCount() const; public: /** * Adds a track. * * Note: The type should not already exist. * * @param TrackClass The class of the track to create. * @param ObjectGuid The runtime object guid that the type should bind to. * @param Type The newly created type. * @see FindTrack, RemoveTrack */ MOVIESCENE_API UMovieSceneTrack* AddTrack(TSubclassOf TrackClass, const FGuid& ObjectGuid); /** * Adds a given track. * * @param InTrack The track to add. * @param ObjectGuid The runtime object guid that the type should bind to * @see FindTrack, RemoveTrack * @return true if the track is successfully added, false otherwise. */ MOVIESCENE_API bool AddGivenTrack(UMovieSceneTrack* InTrack, const FGuid& ObjectGuid); /** * Adds a track. * * Note: The type should not already exist. * * @param TrackClass The class of the track to create. * @param ObjectGuid The runtime object guid that the type should bind to. * @param Type The newly created type. * @see FindTrack, RemoveTrack */ template TrackClass* AddTrack(const FGuid& ObjectGuid) { return Cast(AddTrack(TrackClass::StaticClass(), ObjectGuid)); } /** * Finds a track. * * @param TrackClass The class of the track to find. * @param ObjectGuid The runtime object guid that the track is bound to. * @param TrackName The name of the track to differentiate the one we are searching for from other tracks of the same class (optional). * @return The found track or nullptr if one does not exist. * @see AddTrack, RemoveTrack, FindTracks */ MOVIESCENE_API UMovieSceneTrack* FindTrack(TSubclassOf TrackClass, const FGuid& ObjectGuid, const FName& TrackName = NAME_None) const; /** * Finds a track. * * @param TrackClass The class of the track to find. * @param ObjectGuid The runtime object guid that the track is bound to. * @param TrackName The name of the track to differentiate the one we are searching for from other tracks of the same class (optional). * @return The found track or nullptr if one does not exist. * @see AddTrack, RemoveTrack, FindTracks */ template TrackClass* FindTrack(const FGuid& ObjectGuid, const FName& TrackName = NAME_None) const { return Cast(FindTrack(TrackClass::StaticClass(), ObjectGuid, TrackName)); } /** * Find all tracks of a given class. * * @param TrackClass The class of the track to find. * @param ObjectGuid The runtime object guid that the track is bound to. * @param TrackName The name of the track to differentiate the one we are searching for from other tracks of the same class (optional). * @return The found tracks or an empty array if none exist * @see AddTrack, RemoveTrack, FindTrack */ MOVIESCENE_API TArray FindTracks(TSubclassOf TrackClass, const FGuid& ObjectGuid, const FName& TrackName = NAME_None) const; /** * Removes a track. * * @param Track The track to remove. * @return true if anything was removed. * @see AddTrack, FindTrack */ MOVIESCENE_API bool RemoveTrack(UMovieSceneTrack& Track); /** * Find a track binding Guid from a UMovieSceneTrack * * @param InTrack The track to find the binding for. * @param OutGuid The binding's Guid if one was found. * @return true if a binding was found for this track. */ MOVIESCENE_API bool FindTrackBinding(const UMovieSceneTrack& InTrack, FGuid& OutGuid) const; #if WITH_EDITOR DECLARE_DELEGATE_RetVal_OneParam(bool, FIsTrackClassAllowedEvent, UClass*); static MOVIESCENE_API FIsTrackClassAllowedEvent IsTrackClassAllowedEvent; static MOVIESCENE_API bool IsTrackClassAllowed(UClass* InClass); DECLARE_DELEGATE_RetVal_OneParam(bool, FIsCustomBindingClassAllowedEvent, UClass*); static MOVIESCENE_API FIsCustomBindingClassAllowedEvent IsCustomBindingClassAllowedEvent; static MOVIESCENE_API bool IsCustomBindingClassAllowed(UClass* InClass); DECLARE_DELEGATE_RetVal_OneParam(bool, FIsConditionClassAllowedEvent, const UClass*); static MOVIESCENE_API FIsConditionClassAllowedEvent IsConditionClassAllowedEvent; static MOVIESCENE_API bool IsConditionClassAllowed(const UClass* InClass); void OnDynamicBindingUserDefinedPinRenamed(UK2Node* InNode, FName OldPinName, FName NewPinName) { FixupDynamicBindingPayloadParameterNameEvent.Broadcast(this, InNode, OldPinName, NewPinName); } DECLARE_MULTICAST_DELEGATE_FourParams(FFixupDynamicBindingPayloadParameterNameEvent, UMovieScene*, UK2Node*, FName, FName); static MOVIESCENE_API FFixupDynamicBindingPayloadParameterNameEvent FixupDynamicBindingPayloadParameterNameEvent; void OnDirectorBlueprintConditionUserDefinedPinRenamed(UK2Node* InNode, FName OldPinName, FName NewPinName) { FixupDirectorBlueprintConditionPayloadParameterNameEvent.Broadcast(this, InNode, OldPinName, NewPinName); } DECLARE_MULTICAST_DELEGATE_FourParams(FFixupDirectorBlueprintConditionPayloadParameterNameEvent, UMovieScene*, UK2Node*, FName, FName); static MOVIESCENE_API FFixupDirectorBlueprintConditionPayloadParameterNameEvent FixupDirectorBlueprintConditionPayloadParameterNameEvent; #endif public: /** * Adds a track. * * Note: The type should not already exist. * * @param TrackClass The class of the track to create * @param Type The newly created type * @see FindTrack, GetTracks, IsTrack, RemoveTrack */ MOVIESCENE_API UMovieSceneTrack* AddTrack(TSubclassOf TrackClass); /** * Adds a track. * * Note: The type should not already exist. * * @param TrackClass The class of the track to create * @param Type The newly created type * @see FindTrack, GetTracks, IsTrack, RemoveTrack */ template TrackClass* AddTrack() { return Cast(AddTrack(TrackClass::StaticClass())); } /** * Adds a given track as a track * * @param InTrack The track to add. * @see FindTrack, RemoveTrack * @return true if the track is successfully added, false otherwise. */ MOVIESCENE_API bool AddGivenTrack(UMovieSceneTrack* InTrack); /** * Finds a track (one not bound to a runtime objects). * * @param TrackClass The class of the track to find. * @return The found track or nullptr if one does not exist. * @see AddTrack, GetTracks, IsTrack, RemoveTrack */ MOVIESCENE_API UMovieSceneTrack* FindTrack(TSubclassOf TrackClass) const; /** * Finds a track (one not bound to a runtime objects). * * @param TrackClass The class of the track to find. * @return The found track or nullptr if one does not exist. * @see AddTrack, GetTracks, IsTrack, RemoveTrack */ template TrackClass* FindTrack() const { return Cast(FindTrack(TrackClass::StaticClass())); } /** * Get all tracks. * * @return Track collection. * @see AddTrack, FindTrack, IsTrack, RemoveTrack */ const TArray& GetTracks() const { return Tracks; } /** * Check whether the specified track is a track in this movie scene. * * @return true if the track is a track, false otherwise. * @see AddTrack, FindTrack, GetTracks, RemoveTrack */ MOVIESCENE_API bool ContainsTrack(const UMovieSceneTrack& Track) const; /** * Move all the contents (tracks, child bindings) of the specified binding ID onto another * * @param SourceBindingId The identifier of the binding ID to move all tracks and children from * @param DestinationBindingId The identifier of the binding ID to move the contents to */ MOVIESCENE_API void MoveBindingContents(const FGuid& SourceBindingId, const FGuid& DestinationBindingId); /** * Tries to find an FMovieSceneBinding for the specified Guid. * * @param ForGuid The binding's Guid to look for. * @return Pointer to the binding, otherwise nullptr. */ MOVIESCENE_API FMovieSceneBinding* FindBinding(const FGuid& ForGuid); /** * Tries to find an FMovieSceneBinding for the specified Guid. * * @param ForGuid The binding's Guid to look for. * @return Pointer to the binding, otherwise nullptr. */ MOVIESCENE_API const FMovieSceneBinding* FindBinding(const FGuid& ForGuid) const; public: // @todo sequencer: the following methods really shouldn't be here /** * Adds a new camera cut track if it doesn't exist * A camera cut track allows for cutting between camera views * There is only one per movie scene. * * @param TrackClass The camera cut track class type * @return The created camera cut track */ MOVIESCENE_API UMovieSceneTrack* AddCameraCutTrack( TSubclassOf TrackClass ); /** @return The camera cut track if it exists. */ MOVIESCENE_API UMovieSceneTrack* GetCameraCutTrack() const; /** Removes the camera cut track if it exists. */ MOVIESCENE_API void RemoveCameraCutTrack(); MOVIESCENE_API void SetCameraCutTrack(UMovieSceneTrack* Track); public: /** * Returns all sections and their associated binding data. * * @return A list of sections with object bindings and names. */ MOVIESCENE_API TArray GetAllSections() const; /** * @return All object bindings. */ const TArray& GetBindings() const { return ObjectBindings; } /** * @return All object bindings. */ TArray& GetBindings() { return ObjectBindings; } /** Get the current selection range. */ TRange GetSelectionRange() const { return SelectionRange.Value; } /** * Get the display name of the object with the specified identifier. * * @param ObjectId The object identifier. * @return The object's display name. */ MOVIESCENE_API FText GetObjectDisplayName(const FGuid& ObjectId); /** Get the playback time range of this movie scene, relative to its 0-time offset. */ TRange GetPlaybackRange() const { return PlaybackRange.Value; } /** * Retrieve the tick resolution at which all frame numbers within this movie scene are defined */ FFrameRate GetTickResolution() const { return TickResolution; } /** * Directly set the tick resolution for this movie scene without applying any conversion whatsoever, or modifying the data */ MOVIESCENE_API void SetTickResolutionDirectly(FFrameRate InTickResolution); /** * Retrieve the display frame rate for this data, in which frame numbers should be displayed on UI, and interacted with in movie scene players */ FFrameRate GetDisplayRate() const { return DisplayRate; } /** * Set the play rate for this movie scene */ void SetDisplayRate(FFrameRate InDisplayRate) { DisplayRate = InDisplayRate; } /** * Retrieve a value signifying how to evaluate this movie scene data */ EMovieSceneEvaluationType GetEvaluationType() const { return EvaluationType; } /** * Assign a value signifying how to evaluate this movie scene data */ void SetEvaluationType(EMovieSceneEvaluationType InNewEvaluationType) { EvaluationType = InNewEvaluationType; if (EvaluationType == EMovieSceneEvaluationType::FrameLocked && ClockSource == EUpdateClockSource::Tick) { ClockSource = EUpdateClockSource::Platform; } } /** * retrieve the clock source to be used for this moviescene */ EUpdateClockSource GetClockSource() const { return ClockSource; } UMovieSceneClock* GetCustomClock() const { return ClockSource == EUpdateClockSource::Custom ? CustomClock : nullptr; } template T* GetCustomClockAs() const { return Cast(GetCustomClock()); } /** * Retrieve a time controller from this sequence instance, if the clock source is set to custom */ MOVIESCENE_API TSharedPtr MakeCustomTimeController(UObject* PlaybackContext); /** * Assign the clock source to be used for this moviescene */ MOVIESCENE_API void SetClockSource(EUpdateClockSource InNewClockSource); /** * Assign the clock source to be used for this moviescene */ UE_DEPRECATED(5.6, "Please call SetCustomClock with an instance of UMovieSceneExternalClock") MOVIESCENE_API void SetClockSource(UObject* InNewClockSource); MOVIESCENE_API void SetCustomClock(UMovieSceneClock* InNewClockSource); /** * Get the earliest timecode source out of all of the movie scene sections contained within this movie scene. */ MOVIESCENE_API FMovieSceneTimecodeSource GetEarliestTimecodeSource() const; /* * Replace an existing binding with another */ MOVIESCENE_API void ReplaceBinding(const FGuid& OldGuid, const FGuid& NewGuid, const FString& Name); /* * Replace an existing binding with another. Assumes ownership of any * tracks listed in the binding. Does nothing if no binding can be found. * @param BindingToReplaceGuid Binding Guid that should be replaced * @param NewBinding Binding Data that should replace the original one specified by BindingToReplaceGuid. */ MOVIESCENE_API void ReplaceBinding(const FGuid& BindingToReplaceGuid, const FMovieSceneBinding& NewBinding); #if WITH_EDITORONLY_DATA /** */ TMap& GetObjectsToLabels() { return ObjectsToLabels; } /** Set the selection range. */ void SetSelectionRange(TRange Range) { SelectionRange.Value = Range; } /** * Get the display name of the object with the specified identifier. * * @param ObjectId The object identifier. * @return The object's display name. */ MOVIESCENE_API void SetObjectDisplayName(const FGuid& ObjectId, const FText& DisplayName); /** * Gets the root folders for this movie scene. */ MOVIESCENE_API TArrayView GetRootFolders(); /** * Gets a copy of the root folders for this movie scene. */ MOVIESCENE_API void GetRootFolders(TArray& InRootFolders); /** * Gets the number of root folders in this movie scene. */ MOVIESCENE_API int32 GetNumRootFolders() const; /** * Gets the i-th root folder for this movie scene. */ MOVIESCENE_API UMovieSceneFolder* GetRootFolder(int32 FolderIndex) const; /** * Adds a root folder for this movie scene. */ MOVIESCENE_API void AddRootFolder(UMovieSceneFolder* Folder); /** * Removes a root folder for this movie scene (does not delete tracks or objects contained within) */ MOVIESCENE_API int32 RemoveRootFolder(UMovieSceneFolder* Folder); /** * Removes a root folder for this movie scene (does not delete tracks or objects contained within) */ MOVIESCENE_API bool RemoveRootFolder(int32 FolderIndex); /** * Removes all root folders from this movie scene (does not delete tracks or objects contained within) */ MOVIESCENE_API void EmptyRootFolders(); /** * Gets the nodes marked as transient solo in the editor, as node tree paths */ TArray& GetSoloNodes() { return EditorData.SoloNodes; } /** * Gets the nodes marked as transient muted in the editor, as node tree paths */ TArray& GetMuteNodes() { return EditorData.MuteNodes; } //WIP Set of Delegates /** Gets a multicast delegate which is executed whenever a channel is changed, currently only set by Python/BP actions. * */ FMovieSceneOnChannelChanged& OnChannelChanged() { return OnChannelChangedDelegate; } #endif /** * Set the start and end playback positions (playback range) for this movie scene * * @param Start The offset from 0-time to start playback of this movie scene * @param Duration The number of frames the movie scene should play for * @param bAlwaysMarkDirty Whether to always mark the playback range dirty when changing it. * In the case where the playback range is dynamic and based on section bounds, the playback range doesn't need to be dirtied when set */ MOVIESCENE_API void SetPlaybackRange(FFrameNumber Start, int32 Duration, bool bAlwaysMarkDirty = true); /** * Set the playback range for this movie scene * * @param Range The new playback range. Must not have any open bounds (ie must be a finite range) * @param bAlwaysMarkDirty Whether to always mark the playback range dirty when changing it. * In the case where the playback range is dynamic and based on section bounds, the playback range doesn't need to be dirtied when set */ MOVIESCENE_API void SetPlaybackRange(const TRange& NewRange, bool bAlwaysMarkDirty = true); /** * Set the start and end working range (outer) for this movie scene * * @param Start The offset from 0-time to view this movie scene. * @param End The offset from 0-time to view this movie scene */ MOVIESCENE_API void SetWorkingRange(double Start, double End); /** * Set the start and end view range (inner) for this movie scene * * @param Start The offset from 0-time to view this movie scene * @param End The offset from 0-time to view this movie scene */ MOVIESCENE_API void SetViewRange(double Start, double End); #if WITH_EDITORONLY_DATA public: /* * @return Returns whether this movie scene is read only */ bool IsReadOnly() const { return bReadOnly; } /** * Set whether this movie scene is read only. */ void SetReadOnly(bool bInReadOnly) { bReadOnly = bInReadOnly; } /** * Return whether the playback range is locked. */ MOVIESCENE_API bool IsPlaybackRangeLocked() const; /** * Set whether the playback range is locked. */ MOVIESCENE_API void SetPlaybackRangeLocked(bool bLocked); /** * Return whether marked frames are locked. */ MOVIESCENE_API bool AreMarkedFramesLocked() const; /** * Set whether marked frames are locked. */ MOVIESCENE_API void SetMarkedFramesLocked(bool bLocked); /** * @return The editor only data for use with this movie scene */ FMovieSceneEditorData& GetEditorData() { return EditorData; } const FMovieSceneEditorData& GetEditorData() const { return EditorData; } void SetEditorData(FMovieSceneEditorData& InEditorData) { EditorData = InEditorData; } /* * @return Whether the section is in a group */ MOVIESCENE_API bool IsSectionInGroup(const UMovieSceneSection& InSection) const; /* * Create a group containing InSections, merging any existing groups the sections are in */ MOVIESCENE_API void GroupSections(const TArray InSections); /* * Remove InSection from any group it currently is in */ MOVIESCENE_API void UngroupSection(const UMovieSceneSection& InSection); /* * @return The group containing the InSection, or a nullptr if InSection is not grouped. */ MOVIESCENE_API const FMovieSceneSectionGroup* GetSectionGroup(const UMovieSceneSection& InSection) const; /* * Cleans stale UMovieSceneSection pointers, and removes any section groups which are no longer valid, e.g. contain less that two valid sections */ MOVIESCENE_API void CleanSectionGroups(); UMovieSceneNodeGroupCollection& GetNodeGroups() { return *NodeGroupCollection; } #endif // WITH_EDITORONLY_DATA public: /* * @return Return the user marked frames */ const TArray& GetMarkedFrames() const { return MarkedFrames; } /* * Sets the frame number for the given marked frame index. Does not maintain sort. Call SortMarkedFrames * * @InMarkIndex The given user marked frame index to edit * @InFrameNumber The frame number to set */ MOVIESCENE_API void SetMarkedFrame(int32 InMarkIndex, FFrameNumber InFrameNumber); /* * Add a given user marked frame. * A unique label will be generated if the marked frame label is empty * * @InMarkedFrame The given user marked frame to add * @return The index to the newly added marked frame */ MOVIESCENE_API int32 AddMarkedFrame(const FMovieSceneMarkedFrame& InMarkedFrame); /* * Delete the user marked frame by index. * * @DeleteIndex The index to the user marked frame to delete */ MOVIESCENE_API void DeleteMarkedFrame(int32 DeleteIndex); /* * Delete all user marked frames */ MOVIESCENE_API void DeleteMarkedFrames(); /* * Sort the marked frames in chronological order */ MOVIESCENE_API void SortMarkedFrames(); /* * Find the user marked frame by label * * @InLabel The label to the user marked frame to find */ MOVIESCENE_API int32 FindMarkedFrameByLabel(const FString& InLabel) const; /* * Find the user marked frame by frame number * * @InFrameNumber The frame number of the user marked frame to find */ MOVIESCENE_API int32 FindMarkedFrameByFrameNumber(FFrameNumber InFrameNumber) const; /* * Find the next/previous user marked frame from the given frame number * * @InFrameNumber The frame number to find the next/previous user marked frame from * @bForward Find forward from the given frame number. */ MOVIESCENE_API int32 FindNextMarkedFrame(FFrameNumber InFrameNumber, bool bForward); #if WITH_EDITORONLY_DATA /* * Set whether this scene's marked frames should be shown globally */ void SetGloballyShowMarkedFrames(bool bShowMarkedFrames) { bGloballyShowMarkedFrames = bShowMarkedFrames; } /* * Toggle whether this scene's marked frames should be shown globally */ void ToggleGloballyShowMarkedFrames() { bGloballyShowMarkedFrames = !bGloballyShowMarkedFrames; } /* * Returns whether this scene's marked frames should be shown globally */ bool GetGloballyShowMarkedFrames() const { return bGloballyShowMarkedFrames; } #endif /* * Retrieve all the tagged binding groups for this movie scene */ const TMap& AllTaggedBindings() const { return BindingGroups; } /* * Add a new binding group for the specified name */ MOVIESCENE_API void AddNewBindingTag(const FName& NewTag); /* * Tag the specified binding ID with the specified name */ MOVIESCENE_API void TagBinding(const FName& NewTag, const UE::MovieScene::FFixedObjectBindingID& BindingToTag); /* * Remove a tag from the specified object binding */ MOVIESCENE_API void UntagBinding(const FName& Tag, const UE::MovieScene::FFixedObjectBindingID& Binding); /* * Remove the specified tag from any binding and forget about it completely */ MOVIESCENE_API void RemoveTag(const FName& TagToRemove); /* Called during compilation to add a new generated condition to store in the movie scene. */ void AddGeneratedCondition(UMovieSceneGroupCondition* InGeneratedCondition) { GeneratedConditions.Add(InGeneratedCondition); } /* Called by the compiler to empty the list of generated conditions*/ void ResetGeneratedConditions() { GeneratedConditions.Reset(); } protected: /** * Removes animation data bound to a GUID. * * @param Guid The guid bound to animation data to remove */ MOVIESCENE_API void RemoveBinding(const FGuid& Guid); /** * Tries to find an FMovieSceneBinding for the specified Guid. * * @param ForGuid The binding's Guid to look for. * @return Index of the binding in ObjectBindings array, otherwise INDEX_NONE. */ int32 IndexOfBinding(const FGuid& ForGuid) const; /** * Tries to find an FMovieSceneSpawnable for the specified Guid. * * @param ForGuid The spawnable's Guid to look for. * @return Index of the binding in Spawnables array, otherwise INDEX_NONE. */ int32 IndexOfSpawnable(const FGuid& ForGuid) const; /** * Tries to find an FMovieScenePossessable for the specified Guid. * * @param ForGuid The possessable's Guid to look for. * @return Index of the binding in Possessables array, otherwise INDEX_NONE. */ int32 IndexOfPossessable(const FGuid& ForGuid) const; protected: /** Called before this object is being deserialized. */ MOVIESCENE_API virtual void PreSave(FObjectPreSaveContext ObjectSaveContext) override; MOVIESCENE_API virtual void OnDecorationAdded(UObject* NewDecoration) override; MOVIESCENE_API virtual void OnDecorationRemoved(UObject* NewDecoration) override; /** Perform legacy upgrade of time ranges */ MOVIESCENE_API void UpgradeTimeRanges(); private: #if WITH_EDITOR MOVIESCENE_API void OptimizeForCook(); MOVIESCENE_API void RemoveNullTracks(); #endif private: /** * Data-only blueprints for all of the objects that we we're able to spawn. * These describe objects and actors that we may instantiate at runtime, * or create proxy objects for previewing in the editor. */ UPROPERTY() TArray Spawnables; /** Typed slots for already-spawned objects that we are able to control with this MovieScene */ UPROPERTY() TArray Possessables; /** Tracks bound to possessed or spawned objects */ UPROPERTY() TArray ObjectBindings; /** Map of persistent tagged bindings for this sequence */ UPROPERTY() TMap BindingGroups; /** Tracks which are not bound to spawned or possessed objects */ UPROPERTY(Instanced) TArray> Tracks; /** The camera cut track is a specialized track for switching between cameras on a cinematic */ UPROPERTY(Instanced) TObjectPtr CameraCutTrack; /** A custom clock implementation */ UPROPERTY(Instanced) TObjectPtr CustomClock; /** User-defined selection range. */ UPROPERTY() FMovieSceneFrameRange SelectionRange; /** User-defined playback range for this movie scene. Must be a finite range. Relative to this movie-scene's 0-time origin. */ UPROPERTY() FMovieSceneFrameRange PlaybackRange; /** The resolution at which all frame numbers within this movie-scene data are stored */ UPROPERTY() FFrameRate TickResolution; /** The rate at which we should interact with this moviescene data on UI, and to movie scene players. Also defines the frame locked frame rate. */ UPROPERTY() FFrameRate DisplayRate; /** The type of evaluation to use when playing back this sequence */ UPROPERTY() EMovieSceneEvaluationType EvaluationType; UPROPERTY() EUpdateClockSource ClockSource; #if WITH_EDITORONLY_DATA UPROPERTY() FSoftObjectPath CustomClockSourcePath_DEPRECATED; #endif /** The set of user-marked frames */ UPROPERTY() TArray MarkedFrames; /* List of compiler generated group conditions, stored here to prevent garbage collection. */ UPROPERTY() TArray> GeneratedConditions; #if WITH_EDITORONLY_DATA /** Indicates whether this movie scene is read only */ UPROPERTY() bool bReadOnly; /** User-defined playback range is locked. */ UPROPERTY() bool bPlaybackRangeLocked; /** User-defined marked frames are locked. */ UPROPERTY() bool bMarkedFramesLocked; /** Maps object GUIDs to user defined display names. */ UPROPERTY() TMap ObjectsToDisplayNames; /** Maps object GUIDs to user defined labels. */ UPROPERTY() TMap ObjectsToLabels; /** Editor only data that needs to be saved between sessions for editing but has no runtime purpose */ UPROPERTY() FMovieSceneEditorData EditorData; /** The root folders for this movie scene. */ UPROPERTY() TArray> RootFolders; /** Nodes currently marked Solo, stored as node tree paths */ UPROPERTY(meta = (DeprecatedProperty, DeprecationMessage = "Solo nodes are now saved in FMovieSceneEditorData as transient")) TArray SoloNodes_DEPRECATED; /** Nodes currently marked Mute, stored as node tree paths */ UPROPERTY(meta = (DeprecatedProperty, DeprecationMessage = "Mute nodes are now saved in FMovieSceneEditorData as transient")) TArray MuteNodes_DEPRECATED; /** Groups of sections which should maintain the same relative offset */ UPROPERTY() TArray SectionGroups; /** Collection of user-defined groups */ UPROPERTY() TObjectPtr NodeGroupCollection; /** Whether this scene's marked frames should be shown globally */ UPROPERTY() bool bGloballyShowMarkedFrames; private: UPROPERTY() float InTime_DEPRECATED; UPROPERTY() float OutTime_DEPRECATED; UPROPERTY() float StartTime_DEPRECATED; UPROPERTY() float EndTime_DEPRECATED; UPROPERTY() bool bForceFixedFrameIntervalPlayback_DEPRECATED; UPROPERTY() float FixedFrameInterval_DEPRECATED; UPROPERTY() TArray> MasterTracks_DEPRECATED; //delegates private: FMovieSceneOnChannelChanged OnChannelChangedDelegate; #endif };