diff --git a/CMakeLists.txt b/CMakeLists.txt index d70cd4d..3e3a137 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) project(MayaLiveLink NONE) # Enable no language. -set(MAYA_VERSIONS 2020 2022 2023) +set(MAYA_VERSIONS 2022 2023 2024) if(WIN32) set(Platform Win64) set(Extension .mll) diff --git a/Plugins/Runtime/MayaLiveLink/MayaLiveLink.uplugin b/Plugins/Runtime/MayaLiveLink/MayaLiveLink.uplugin index b627caa..35db681 100644 --- a/Plugins/Runtime/MayaLiveLink/MayaLiveLink.uplugin +++ b/Plugins/Runtime/MayaLiveLink/MayaLiveLink.uplugin @@ -1,13 +1,13 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "2.2.0", + "VersionName": "2.3.0", "FriendlyName": "Maya Live Link", "Description": "Maya Live Link allows streaming of animated data into the Unreal Editor", "Category": "Animation", "CreatedBy": "Autodesk, Inc.", "CreatedByURL": "https://www.autodesk.com", - "DocsURL": "https://help.autodesk.com/view/MAYAUL/2023/ENU/?guid=UnrealLiveLink_unreal_livelink_landing_html", + "DocsURL": "https://help.autodesk.com/view/MAYAUL/2024/ENU/?guid=UnrealLiveLink_unreal_livelink_landing_html", "MarketplaceURL": "", "SupportURL": "https://forums.autodesk.com/t5/unreal-live-link-for-maya-forum/bd-p/6143", "CanContainContent": false, @@ -51,6 +51,10 @@ { "Name": "SequencerScripting", "Enabled": true + }, + { + "Name": "AnimationData", + "Enabled": true } ] } \ No newline at end of file diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/MayaLiveLink.Build.cs b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/MayaLiveLink.Build.cs index 7d5e16a..a9f31b8 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/MayaLiveLink.Build.cs +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/MayaLiveLink.Build.cs @@ -38,7 +38,7 @@ public MayaLiveLink(ReadOnlyTargetRules Target) : base(Target) PrivateDependencyModuleNames.AddRange( new string[] { - "HeadMountedDisplay", + "AnimationData", "InputCore", "Media", "Projects", diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/Private/MayaLiveLinkMessageBusSource.cpp b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/Private/MayaLiveLinkMessageBusSource.cpp index acac94e..3922f06 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/Private/MayaLiveLinkMessageBusSource.cpp +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLink/Private/MayaLiveLinkMessageBusSource.cpp @@ -516,7 +516,7 @@ void FMayaLiveLinkMessageBusSource::PushStaticDataToAnimSequence(const FName& Su auto& StaticData = *TimelineStaticDataPtr; // Push to the static data to generate an animation sequence - TArray BoneTrackRemapping; + TArray BoneTrackRemapping; FString AnimSequenceName; UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(StaticData, BoneTrackRemapping, AnimSequenceName); { diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Private/MayaLiveLinkInterface.cpp b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Private/MayaLiveLinkInterface.cpp index f5a58e8..c565c11 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Private/MayaLiveLinkInterface.cpp +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Private/MayaLiveLinkInterface.cpp @@ -32,7 +32,7 @@ IMPLEMENT_MODULE(FMayaLiveLinkInterfaceModule, MayaLiveLinkInterface) namespace { - static const FString PluginVersion = "v2.2.0"; + static const FString PluginVersion = "v2.3.0"; static const FString UnrealEngineVersion = VERSION_STRINGIFY(ENGINE_MAJOR_VERSION) TEXT(".") VERSION_STRINGIFY(ENGINE_MINOR_VERSION); } diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Public/Roles/MayaLiveLinkTimelineTypes.h b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Public/Roles/MayaLiveLinkTimelineTypes.h index 2925d1d..853c4b5 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Public/Roles/MayaLiveLinkTimelineTypes.h +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkInterface/Public/Roles/MayaLiveLinkTimelineTypes.h @@ -41,7 +41,7 @@ struct MAYALIVELINKINTERFACE_API FMayaLiveLinkTimelineBaseParams struct MAYALIVELINKINTERFACE_API FMayaLiveLinkAnimSequenceParams : public FMayaLiveLinkTimelineBaseParams { - TArray BoneTrackRemapping; + TArray BoneTrackRemapping; FString FullSequenceName; }; diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkAnimSequenceHelper.cpp b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkAnimSequenceHelper.cpp index 7b8dede..37edb68 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkAnimSequenceHelper.cpp +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkAnimSequenceHelper.cpp @@ -25,6 +25,7 @@ #include "MayaLiveLinkUtils.h" #include "Animation/AnimBlueprint.h" +#include "Animation/AnimCompress.h" #include "Animation/AnimSequence.h" #include "Animation/AnimSequenceHelpers.h" #include "Animation/Skeleton.h" @@ -34,9 +35,12 @@ #include "Kismet2/BlueprintEditorUtils.h" #include "Kismet2/KismetEditorUtilities.h" +#include "Misc/FeedbackContext.h" + #include "Roles/MayaLiveLinkTimelineTypes.h" #include "AssetToolsModule.h" +#include "CoreGlobals.h" #include "Editor.h" #define LOCTEXT_NAMESPACE "MayaLiveLinkAnimSequenceHelper" @@ -59,7 +63,7 @@ UMayaLiveLinkAnimSequenceHelper::UMayaLiveLinkAnimSequenceHelper(const FObjectIn } void UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(const FMayaLiveLinkAnimSequenceStaticData& StaticData, - TArray& BoneTrackRemapping, + TArray& BoneTrackRemapping, FString& AnimSequenceName) { if (StaticData.LinkedAssetPath.IsEmpty() || @@ -143,20 +147,26 @@ void UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(const FMayaLi { for (auto& BoneName : StaticData.BoneNames) { - int32 TrackIndex = INDEX_NONE; if (RefSkeleton.FindBoneIndex(BoneName) != INDEX_NONE) { - TrackIndex = AnimSequence->GetDataModel()->GetBoneTrackIndexByName(BoneName); + bool bValidBone = AnimSequence->GetDataModel()->IsValidBoneTrackName(BoneName); - if (TrackIndex == INDEX_NONE) + if (!bValidBone) { FRawAnimSequenceTrack RawTrack; RawTrack.PosKeys.Init(FVector3f::ZeroVector, NumberOfFrames); RawTrack.RotKeys.Init(FQuat4f::Identity, NumberOfFrames); RawTrack.ScaleKeys.Init(FVector3f::OneVector, NumberOfFrames); - TrackIndex = Controller.AddBoneTrack(BoneName, false); - Controller.SetBoneTrackKeys(BoneName, RawTrack.PosKeys, RawTrack.RotKeys, RawTrack.ScaleKeys, false); + bValidBone = Controller.AddBoneCurve(BoneName, false); + if (bValidBone) + { + Controller.SetBoneTrackKeys(BoneName, RawTrack.PosKeys, RawTrack.RotKeys, RawTrack.ScaleKeys, false); + } + else + { + continue; + } } FRawAnimSequenceTrack RawTrack; @@ -182,9 +192,10 @@ void UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(const FMayaLi Controller.SetBoneTrackKeys(BoneName, RawTrack.PosKeys, RawTrack.RotKeys, RawTrack.ScaleKeys, false); } } - BoneTrackRemapping.Add(TrackIndex); + BoneTrackRemapping.Add(BoneName); } } + Controller.CloseBracket(false); } @@ -218,8 +229,8 @@ void UMayaLiveLinkAnimSequenceHelper::PushFrameDataToAnimSequence(const FMayaLiv // Update the baked animation frame for each bone bool SequenceUpdated = false; - const auto RawAnimationDataSize = AnimSequence->GetDataModel()->GetBoneAnimationTracks().Num(); TMap FramesByBone; + const int32 NumberOfFrames = GetAnimSequenceNumberOfFrames(*AnimSequence); for (int FrameIndex = 0; FrameIndex < FrameData.Frames.Num(); ++FrameIndex) { auto& Frame = FrameData.Frames[FrameIndex]; @@ -231,23 +242,18 @@ void UMayaLiveLinkAnimSequenceHelper::PushFrameDataToAnimSequence(const FMayaLiv { continue; } - int32 TrackIndex = TimelineParams.BoneTrackRemapping[BoneIndex]; - if (TrackIndex >= RawAnimationDataSize || TrackIndex == INDEX_NONE) + const FName& TrackName = TimelineParams.BoneTrackRemapping[BoneIndex]; + if (!TrackName.IsValid()) { continue; } - const auto& TrackData = AnimSequence->GetDataModel()->GetBoneTrackByIndex(TrackIndex); - const auto& AnimTrack = TrackData.InternalTrackData; - - if (AnimTrack.PosKeys.Num() > 0 && FrameIndex < AnimTrack.PosKeys.Num() && - AnimTrack.RotKeys.Num() > 0 && FrameIndex < AnimTrack.RotKeys.Num() && - AnimTrack.ScaleKeys.Num() > 0 && FrameIndex < AnimTrack.ScaleKeys.Num()) + if (NumberOfFrames > 0 && FrameIndex < NumberOfFrames) { - auto BoneTrackPtr = FramesByBone.Find(TrackData.Name); + auto BoneTrackPtr = FramesByBone.Find(TrackName); if (!BoneTrackPtr) { - BoneTrackPtr = &FramesByBone.Emplace(TrackData.Name); + BoneTrackPtr = &FramesByBone.Emplace(TrackName); BoneTrackPtr->Locations.Init(FVector::ZeroVector, FrameData.Frames.Num()); BoneTrackPtr->Rotations.Init(FQuat::Identity, FrameData.Frames.Num()); BoneTrackPtr->Scales.Init(FVector::OneVector, FrameData.Frames.Num()); @@ -281,6 +287,7 @@ void UMayaLiveLinkAnimSequenceHelper::PushFrameDataToAnimSequence(const FMayaLiv false); } } + Controller.CloseBracket(false); } @@ -336,6 +343,25 @@ void UMayaLiveLinkAnimSequenceHelper::PushFrameDataToAnimSequence(const FMayaLiv } } + if (SequenceUpdated) + { + // Need to start a compression task to update the AnimSequence + GWarn->BeginSlowTask(LOCTEXT("AnimCompressing", "Compressing"), true); + { + UE::Anim::Compression::FAnimationCompressionMemorySummaryScope Scope; + + // Disable the modal summary window + UE::Anim::Compression::FAnimationCompressionMemorySummaryScope::CompressionSummary = MakeUnique(false); + + // Clear CompressCommandletVersion so we can recompress these animations later. + AnimSequence->CompressCommandletVersion = 0; + AnimSequence->ClearAllCachedCookedPlatformData(); + AnimSequence->CacheDerivedDataForCurrentPlatform(); + } + + GWarn->EndSlowTask(); + } + FMayaLiveLinkUtils::RefreshContentBrowser(*AnimSequence); } @@ -353,6 +379,8 @@ bool UMayaLiveLinkAnimSequenceHelper::StaticUpdateAnimSequence(UAnimSequence& An { AnimSequence.SetSkeleton(Skeleton); Updated = true; + + AnimSequence.GetController().InitializeModel(); } // Resize the AnimSequence length @@ -366,10 +394,10 @@ bool UMayaLiveLinkAnimSequenceHelper::StaticUpdateAnimSequence(UAnimSequence& An auto& Controller = AnimSequence.GetController(); Controller.RemoveAllCurvesOfType(ERawCurveTrackTypes::RCT_Float); Controller.RemoveAllCurvesOfType(ERawCurveTrackTypes::RCT_Transform); - Controller.SetPlayLength(SequenceLength); + Controller.SetFrameRate(FrameRate); + Controller.SetNumberOfFrames(NumberOfFrames); AnimSequence.ImportResampleFramerate = FrameRate.AsDecimal(); AnimSequence.ImportFileFramerate = FrameRate.AsDecimal(); - Controller.SetFrameRate(FrameRate); // Trigger a notification to update the target/sampling frame rate used to playback the anim sequence Controller.NotifyPopulated(); diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkLevelSequenceHelper.cpp b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkLevelSequenceHelper.cpp index 94d6cd2..0d2b115 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkLevelSequenceHelper.cpp +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Private/MayaLiveLinkLevelSequenceHelper.cpp @@ -44,6 +44,8 @@ #include "GameFramework/Actor.h" +#include "MovieScene.h" + // Sections #include "Sections/MovieScene3DTransformSection.h" #include "Sections/MovieSceneBoolSection.h" diff --git a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Public/MayaLiveLinkAnimSequenceHelper.h b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Public/MayaLiveLinkAnimSequenceHelper.h index 8f717cf..e91efeb 100644 --- a/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Public/MayaLiveLinkAnimSequenceHelper.h +++ b/Plugins/Runtime/MayaLiveLink/Source/MayaLiveLinkTimelineSync/Public/MayaLiveLinkAnimSequenceHelper.h @@ -32,7 +32,7 @@ class UMayaLiveLinkAnimSequenceHelper : public UObject GENERATED_UCLASS_BODY() static MAYALIVELINKTIMELINESYNC_API void PushStaticDataToAnimSequence(const struct FMayaLiveLinkAnimSequenceStaticData& StaticData, - TArray& BoneTrackRemapping, + TArray& BoneTrackRemapping, FString& AnimSequenceName); static MAYALIVELINKTIMELINESYNC_API void PushFrameDataToAnimSequence(const struct FMayaLiveLinkAnimSequenceFrameData& FrameData, const struct FMayaLiveLinkAnimSequenceParams& TimelineParams); diff --git a/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.sh b/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.sh index 8a8c33f..4f2c764 100755 --- a/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.sh +++ b/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.sh @@ -24,7 +24,7 @@ scriptDir="$(dirname "$(readlink -f "$0")")" -# arg[1] specifies the Maya version (2020|2022|2023 ...), see BuildMayaUnrealLiveLinkPlugin.xml for default value +# arg[1] specifies the Maya version (2022|2023|2024 ...), see BuildMayaUnrealLiveLinkPlugin.xml for default value if [ ! -z "$1" ]; then MayaVersion=-set:MayaVersion=$1 fi diff --git a/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.xml b/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.xml index ee14e55..a426fd4 100644 --- a/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.xml +++ b/Source/Programs/MayaUnrealLiveLinkPlugin/BuildMayaUnrealLiveLinkPlugin.xml @@ -2,7 +2,7 @@