Skip to content

Commit

Permalink
Release 2.4.0 (#35)
Browse files Browse the repository at this point in the history
Unreal® Live Link for Maya for UE 5.3 has been updated to work with Unreal Engine 5.3. It will NOT work with Unreal Engine 5.2 or earlier. See other tagged versions for support for earlier Unreal versions.

Version 2.4.0 includes the following changes:

- Adds support for Unreal Engine 5.3.2. It will NOT work with Unreal Engine 5.2 or earlier.
- Adds support for Maya 2025. Maya 2022, 2023, and 2024 continue to be supported.
- Adds an option to toggle real-time synchronization of data. With this option enabled, changes in Maya are reflected immediately in Unreal. When the option is disabled, changes are reflected in Unreal when the mouse button is released.
Real-time synchronization is limited to "unlinked" assets and Linked Joint Hierarchies (Characters).
- Performance Improvements when using linked assets.
  • Loading branch information
adsk-gwood authored May 1, 2024
1 parent 603849f commit dcb8139
Show file tree
Hide file tree
Showing 28 changed files with 493 additions and 134 deletions.
4 changes: 2 additions & 2 deletions Plugins/Runtime/MayaLiveLink/MayaLiveLink.uplugin
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "2.3.0",
"VersionName": "2.4.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/2024/ENU/?guid=UnrealLiveLink_unreal_livelink_landing_html",
"DocsURL": "https://help.autodesk.com/view/MAYAUL/2025/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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ IMPLEMENT_MODULE(FMayaLiveLinkInterfaceModule, MayaLiveLinkInterface)

namespace
{
static const FString PluginVersion = "v2.3.0";
static const FString PluginVersion = "v2.4.0";
static const FString UnrealEngineVersion = VERSION_STRINGIFY(ENGINE_MAJOR_VERSION) TEXT(".") VERSION_STRINGIFY(ENGINE_MINOR_VERSION);
}

Expand All @@ -56,4 +56,4 @@ const FString& FMayaLiveLinkInterfaceModule::GetEngineVersion()
return UnrealEngineVersion;
}

#undef LOCTEXT_NAMESPACE
#undef LOCTEXT_NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,28 @@ namespace

int32 GetAnimSequenceNumberOfFrames(const UAnimSequence& AnimSequence)
{
return AnimSequence.GetDataModel()->GetNumberOfKeys();
return AnimSequence.GetDataModel()->GetNumberOfFrames();
}

void RandomizeVector3Array(TArray<FVector3f>& VecArray)
{
for (auto& k : VecArray)
{
k.X = FMath::FRand();
k.Y = FMath::FRand();
k.Z = FMath::FRand();
}
}

void RandomizeQuaternionArray(TArray<FQuat4f>& QuatArray)
{
for (auto& k : QuatArray)
{
k.X = FMath::FRand();
k.Y = FMath::FRand();
k.Z = FMath::FRand();
k.W = FMath::FRand();
}
}
}

Expand Down Expand Up @@ -158,6 +179,21 @@ void UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(const FMayaLi
RawTrack.RotKeys.Init(FQuat4f::Identity, NumberOfFrames);
RawTrack.ScaleKeys.Init(FVector3f::OneVector, NumberOfFrames);

// NOTE: When we call SetBoneTrackKeys below, we are populating it with uniform "Identity" data for all
// keys. Unreal is detecting that the data is uniform and is optimizing it to a single DefaultValue
// internally. This is fine in principle. However, there is a bug in Unreal 5.2 and 5.3 (and possibly
// earlier) that prevents this DefaultValue flag/optimization to be cleared when we later populate
// the bone track with "real" (non-uniform) data, when we start receiving values from Maya. Epic are
// aware of this bug and a fix will likely make it into a later version of Unreal.
//
// To avoid the optimization from kicking in in the first place, we are randomizing the initial data,
// so it no longer looks uniform. Since we'll be replacing it all with messages received from Maya,
// anyway, this is fine for the time being.
//
RandomizeVector3Array(RawTrack.PosKeys);
RandomizeQuaternionArray(RawTrack.RotKeys);
RandomizeVector3Array(RawTrack.ScaleKeys);

bValidBone = Controller.AddBoneCurve(BoneName, false);
if (bValidBone)
{
Expand All @@ -175,16 +211,22 @@ void UMayaLiveLinkAnimSequenceHelper::PushStaticDataToAnimSequence(const FMayaLi
{
ResizeSequenceRequested = true;
RawTrack.PosKeys.Init(FVector3f::ZeroVector, NumberOfFrames);
// NOTE: See comment above for an explanation of why this is needed
RandomizeVector3Array(RawTrack.PosKeys);
}
if (NumberOfFrames != RawTrack.RotKeys.Num())
{
ResizeSequenceRequested = true;
RawTrack.RotKeys.Init(FQuat4f::Identity, NumberOfFrames);
// NOTE: See comment above for an explanation of why this is needed
RandomizeQuaternionArray(RawTrack.RotKeys);
}
if (NumberOfFrames != RawTrack.ScaleKeys.Num())
{
ResizeSequenceRequested = true;
RawTrack.ScaleKeys.Init(FVector3f::OneVector, NumberOfFrames);
// NOTE: See comment above for an explanation of why this is needed
RandomizeVector3Array(RawTrack.ScaleKeys);
}

if (ResizeSequenceRequested)
Expand Down Expand Up @@ -307,59 +349,35 @@ void UMayaLiveLinkAnimSequenceHelper::PushFrameDataToAnimSequence(const FMayaLiv
const FString& CurveName = CurvePair.Key;
const FMayaLiveLinkCurve& Curve = CurvePair.Value;

FSmartName SmartName;
FName CurveFName(*CurveName);
AnimSequence->GetSkeleton()->GetSmartNameByName(ContainerName, CurveFName, SmartName);

if (SmartName.IsValid())
FAnimationCurveIdentifier CurveId(CurveFName, ERawCurveTrackTypes::RCT_Float);
const FAnimCurveBase* RichCurve = Controller.GetModel()->FindCurve(CurveId);
if (!RichCurve)
{
FAnimationCurveIdentifier CurveId(SmartName, ERawCurveTrackTypes::RCT_Float);
const FAnimCurveBase* RichCurve = Controller.GetModel()->FindCurve(CurveId);
if (!RichCurve)
{
Controller.AddCurve(CurveId, EAnimAssetCurveFlags::AACF_Editable, false);
}

TArray<FRichCurveKey> RichCurves;

for (const auto& KeyPair : Curve.KeyFrames)
{
const auto& Value = KeyPair.Value;
FRichCurveKey CurveKey;
CurveKey.Time = KeyPair.Key * Interval;
CurveKey.Value = Value.Value;
CurveKey.ArriveTangent = FMath::RadiansToDegrees(Value.TangentAngleIn) * 0.5f;
CurveKey.ArriveTangentWeight = Value.TangentWeightIn;
CurveKey.LeaveTangent = FMath::RadiansToDegrees(Value.TangentAngleOut) * 0.5f;
CurveKey.LeaveTangentWeight = Value.TangentWeightOut;
CurveKey.InterpMode = static_cast<ERichCurveInterpMode>(Value.InterpMode.GetValue());
CurveKey.TangentMode = static_cast<ERichCurveTangentMode>(Value.TangentMode.GetValue());
CurveKey.TangentWeightMode = static_cast<ERichCurveTangentWeightMode>(Value.TangentWeightMode.GetValue());
RichCurves.Emplace(MoveTemp(CurveKey));
}

Controller.SetCurveKeys(CurveId, RichCurves, false);
Controller.AddCurve(CurveId, EAnimAssetCurveFlags::AACF_Editable, false);
}
}
}

if (SequenceUpdated)
{
// Need to start a compression task to update the AnimSequence
GWarn->BeginSlowTask(LOCTEXT("AnimCompressing", "Compressing"), true);
{
UE::Anim::Compression::FAnimationCompressionMemorySummaryScope Scope;
TArray<FRichCurveKey> RichCurves;

// Disable the modal summary window
UE::Anim::Compression::FAnimationCompressionMemorySummaryScope::CompressionSummary = MakeUnique<FCompressionMemorySummary>(false);
for (const auto& KeyPair : Curve.KeyFrames)
{
const auto& Value = KeyPair.Value;
FRichCurveKey CurveKey;
CurveKey.Time = KeyPair.Key * Interval;
CurveKey.Value = Value.Value;
CurveKey.ArriveTangent = FMath::RadiansToDegrees(Value.TangentAngleIn) * 0.5f;
CurveKey.ArriveTangentWeight = Value.TangentWeightIn;
CurveKey.LeaveTangent = FMath::RadiansToDegrees(Value.TangentAngleOut) * 0.5f;
CurveKey.LeaveTangentWeight = Value.TangentWeightOut;
CurveKey.InterpMode = static_cast<ERichCurveInterpMode>(Value.InterpMode.GetValue());
CurveKey.TangentMode = static_cast<ERichCurveTangentMode>(Value.TangentMode.GetValue());
CurveKey.TangentWeightMode = static_cast<ERichCurveTangentWeightMode>(Value.TangentWeightMode.GetValue());
RichCurves.Emplace(MoveTemp(CurveKey));
}

// Clear CompressCommandletVersion so we can recompress these animations later.
AnimSequence->CompressCommandletVersion = 0;
AnimSequence->ClearAllCachedCookedPlatformData();
AnimSequence->CacheDerivedDataForCurrentPlatform();
Controller.SetCurveKeys(CurveId, RichCurves, false);
}

GWarn->EndSlowTask();
}

FMayaLiveLinkUtils::RefreshContentBrowser(*AnimSequence);
Expand Down Expand Up @@ -408,4 +426,4 @@ bool UMayaLiveLinkAnimSequenceHelper::StaticUpdateAnimSequence(UAnimSequence& An
return Updated;
}

#undef LOCTEXT_NAMESPACE
#undef LOCTEXT_NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<BuildGraph xmlns="http://www.epicgames.com/BuildGraph" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epicgames.com/BuildGraph ../../../../../Engine/Build/Graph/Schema.xsd" >

<Option Name="PublishZipDir_Win" DefaultValue="$(RootDir)/LocalBuilds/Engine/WindowsZips" Description="The output directory for published zip artifacts on Windows"/>
<Option Name="MayaVersion" Restrict="2022|2023|2024" DefaultValue="2024" Description="Select the maya version"/>
<Option Name="MayaVersion" Restrict="2022|2023|2024|2025" DefaultValue="2025" Description="Select the maya version"/>
<Option Name="MayaPlatform" Restrict="Win64|Linux" DefaultValue="Win64" Description="Select the platform"/>
<Option Name="BuildTarget" Restrict="Debug|Development" DefaultValue="Development" Description="Select the build target"/>

Expand All @@ -14,11 +14,7 @@
<Property Name="LocalBinaryDir" Value="$(RootDir)\Engine\Restricted\NotForLicensees\Binaries\$(MayaPlatform)\Maya"/>
<Property Name="LocalExtraDir" Value="$(RootDir)\Engine\Restricted\NotForLicensees\Extras\MayaUnrealLiveLinkPlugin"/>

<Node Name="Compile UnrealHeaderTool Maya">
<Compile Target="UnrealHeaderTool" Platform="$(MayaPlatform)" Configuration="$(BuildTarget)" Arguments="-precompile -nodebuginfo"/>
</Node>

<Node Name="Compile Maya $(MayaVersion)" Requires="Compile UnrealHeaderTool Maya">
<Node Name="Compile Maya $(MayaVersion)">
<Compile Target="MayaUnrealLiveLinkPlugin$(MayaVersion)" Platform="$(MayaPlatform)" Configuration="$(BuildTarget)" Arguments="-noxge"/>
<Copy From="$(LocalSourceDir)\MayaUnrealLiveLinkPlugin.mod" To="$(LocalBinaryDir)\MayaUnrealLiveLinkPlugin.mod" />
</Node>
Expand All @@ -34,4 +30,4 @@
</Node>

</Agent>
</BuildGraph>
</BuildGraph>
Loading

0 comments on commit dcb8139

Please sign in to comment.