// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Channels/MovieSceneChannel.h" #include "Channels/MovieSceneChannelData.h" #include "Channels/MovieSceneChannelTraits.h" #include "Containers/Array.h" #include "Containers/ArrayView.h" #include "Containers/Map.h" #include "Containers/UnrealString.h" #include "CoreMinimal.h" #include "Curves/IntegralCurve.h" #include "Curves/KeyHandle.h" #include "HAL/Platform.h" #include "HAL/PlatformCrt.h" #include "Math/Range.h" #include "Misc/AssertionMacros.h" #include "Misc/FrameNumber.h" #include "Misc/FrameRate.h" #include "Misc/FrameTime.h" #include "Misc/Guid.h" #include "MovieSceneFwd.h" #include "MovieSceneObjectBindingID.h" #include "MovieSceneSection.h" #include "UObject/NameTypes.h" #include "UObject/ObjectMacros.h" #include "UObject/UObjectGlobals.h" #include "MovieSceneActorReferenceSection.generated.h" class IMovieScenePlayer; class UObject; struct FKeyHandle; struct FMovieSceneSequenceHierarchy; struct FMovieSceneSequenceID; USTRUCT() struct FMovieSceneActorReferenceKey { GENERATED_BODY() FMovieSceneActorReferenceKey() {} FMovieSceneActorReferenceKey(const FMovieSceneObjectBindingID& InBindingID) : Object(InBindingID) {} friend bool operator==(const FMovieSceneActorReferenceKey& A, const FMovieSceneActorReferenceKey& B) { return A.Object == B.Object && A.ComponentName == B.ComponentName && A.SocketName == B.SocketName; } friend bool operator!=(const FMovieSceneActorReferenceKey& A, const FMovieSceneActorReferenceKey& B) { return A.Object != B.Object || A.ComponentName != B.ComponentName || A.SocketName != B.SocketName; } UPROPERTY(EditAnywhere, Category="Key") FMovieSceneObjectBindingID Object; UPROPERTY(EditAnywhere, Category="Key") FName ComponentName; UPROPERTY(EditAnywhere, Category="Key") FName SocketName; }; /** A curve of events */ USTRUCT() struct FMovieSceneActorReferenceData : public FMovieSceneChannel { GENERATED_BODY() typedef FMovieSceneActorReferenceKey CurveValueType; FMovieSceneActorReferenceData() : DefaultValue() {} /** * Access a mutable interface for this channel's data * * @return An object that is able to manipulate this channel's data */ inline TMovieSceneChannelData GetData() { return TMovieSceneChannelData(&KeyTimes, &KeyValues, this, &KeyHandles); } /** * Access a constant interface for this channel's data * * @return An object that is able to interrogate this channel's data */ inline TMovieSceneChannelData GetData() const { return TMovieSceneChannelData(&KeyTimes, &KeyValues); } /** * Evaluate this channel * * @param InTime The time to evaluate at * @param OutValue A value to receive the result * @return true if the channel was evaluated successfully, false otherwise */ MOVIESCENETRACKS_API bool Evaluate(FFrameTime InTime, FMovieSceneActorReferenceKey& OutValue) const; public: // ~ FMovieSceneChannel Interface MOVIESCENETRACKS_API virtual void GetKeys(const TRange& WithinRange, TArray* OutKeyTimes, TArray* OutKeyHandles) override; MOVIESCENETRACKS_API virtual void GetKeyTimes(TArrayView InHandles, TArrayView OutKeyTimes) override; MOVIESCENETRACKS_API virtual void SetKeyTimes(TArrayView InHandles, TArrayView InKeyTimes) override; MOVIESCENETRACKS_API virtual void DuplicateKeys(TArrayView InHandles, TArrayView OutNewHandles) override; MOVIESCENETRACKS_API virtual void DeleteKeys(TArrayView InHandles) override; MOVIESCENETRACKS_API virtual void DeleteKeysFrom(FFrameNumber InTime, bool bDeleteKeysBefore) override; MOVIESCENETRACKS_API virtual void RemapTimes(const UE::MovieScene::IRetimingInterface& Retimer) override; MOVIESCENETRACKS_API virtual TRange ComputeEffectiveRange() const override; MOVIESCENETRACKS_API virtual int32 GetNumKeys() const override; MOVIESCENETRACKS_API virtual void Reset() override; MOVIESCENETRACKS_API virtual void Offset(FFrameNumber DeltaPosition) override; MOVIESCENETRACKS_API virtual void ClearDefault() override; MOVIESCENETRACKS_API virtual FKeyHandle GetHandle(int32 Index) override; MOVIESCENETRACKS_API virtual int32 GetIndex(FKeyHandle Handle) override; public: /** * Set this channel's default value that should be used when no keys are present * * @param InDefaultValue The desired default value */ inline void SetDefault(FMovieSceneActorReferenceKey InDefaultValue) { DefaultValue = InDefaultValue; } /** * Get this channel's default value that will be used when no keys are present * * @return (Optional) The channel's default value */ inline const FMovieSceneActorReferenceKey& GetDefault() const { return DefaultValue; } /** * Upgrade legacy data by appending to the end of the array. Assumes sorted data */ void UpgradeLegacyTime(UObject* Context, double Time, FMovieSceneActorReferenceKey Value) { FFrameRate LegacyFrameRate = GetLegacyConversionFrameRate(); FFrameNumber KeyTime = UpgradeLegacyMovieSceneTime(nullptr, LegacyFrameRate, Time); check(KeyTimes.Num() == 0 || KeyTime >= KeyTimes.Last()); KeyTimes.Add(KeyTime); KeyValues.Add(Value); } private: /** Sorted array of key times */ UPROPERTY(meta=(KeyTimes)) TArray KeyTimes; /** Default value used when there are no keys */ UPROPERTY() FMovieSceneActorReferenceKey DefaultValue; /** Array of values that correspond to each key time */ UPROPERTY(meta=(KeyValues)) TArray KeyValues; /** This needs to be a UPROPERTY so it gets saved into editor transactions but transient so it doesn't get saved into assets. */ UPROPERTY(Transient) FMovieSceneKeyHandleMap KeyHandles; }; /** * A single actor reference point section */ UCLASS(MinimalAPI) class UMovieSceneActorReferenceSection : public UMovieSceneSection { GENERATED_UCLASS_BODY() public: //~ UObject interface virtual void PostLoad() override; //~ UMovieSceneSection interface virtual void OnBindingIDsUpdated(const TMap& OldFixedToNewFixedMap, FMovieSceneSequenceID LocalSequenceID, TSharedRef SharedPlaybackState) override; const FMovieSceneActorReferenceData& GetActorReferenceData() const { return ActorReferenceData; } private: UPROPERTY() FMovieSceneActorReferenceData ActorReferenceData; private: /** Curve data */ UPROPERTY() FIntegralCurve ActorGuidIndexCurve_DEPRECATED; UPROPERTY() TArray ActorGuidStrings_DEPRECATED; }; inline bool EvaluateChannel(const FMovieSceneActorReferenceData* InChannel, FFrameTime InTime, FMovieSceneActorReferenceKey& OutValue) { return InChannel->Evaluate(InTime, OutValue); } inline bool GetChannelDefault(const FMovieSceneActorReferenceData* Channel, FMovieSceneActorReferenceKey& OutDefaultValue) { OutDefaultValue = Channel->GetDefault(); return true; }