// Copyright Epic Games, Inc. All Rights Reserved. #include "AnimDataControllerActions.h" #include "AnimDataController.h" #include "Animation/AnimData/IAnimationDataModel.h" #include "UObject/StrongObjectPtr.h" #define LOCTEXT_NAMESPACE "AnimDataControllerActions" #if WITH_EDITOR namespace UE { namespace Anim { TUniquePtr FAnimDataBaseAction::Execute(UObject* Object) { const TScriptInterface DataModelInterface(Object); checkf(DataModelInterface, TEXT("Invalid IAnimationDataModel Object")); const TScriptInterface Controller = DataModelInterface->GetController(); Controller->SetModel(DataModelInterface); return ExecuteInternal(DataModelInterface.GetInterface(), Controller.GetInterface()); } FString FAnimDataBaseAction::ToString() const { return ToStringInternal(); } TUniquePtr FOpenBracketAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { Controller->NotifyBracketOpen(); return MakeUnique(Description); } FString FOpenBracketAction::ToStringInternal() const { return FString::Printf(TEXT("Open Bracket: %s"), *Description); } TUniquePtr FCloseBracketAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { Controller->NotifyBracketClosed(); return MakeUnique(Description); } FString FCloseBracketAction::ToStringInternal() const { return TEXT("Closing Bracket"); } FAddTrackAction::FAddTrackAction(const FName& InName, TArray&& InTransformData) { Name = InName; TransformData = MoveTemp(InTransformData); } TUniquePtr FAddTrackAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { Controller->AddBoneCurve(Name, false); if (TransformData.Num()) { TArray PosKeys; TArray RotKeys; TArray ScaleKeys; PosKeys.Reserve(TransformData.Num()); RotKeys.Reserve(TransformData.Num()); ScaleKeys.Reserve(TransformData.Num()); for (const FTransform& Transform : TransformData) { PosKeys.Add(FVector3f(Transform.GetLocation())); RotKeys.Add(FQuat4f(Transform.GetRotation())); ScaleKeys.Add(FVector3f(Transform.GetScale3D())); } Controller->SetBoneTrackKeys(Name, PosKeys, RotKeys, ScaleKeys, false); } return MakeUnique(Name); } FString FAddTrackAction::ToStringInternal() const { return FText::Format(LOCTEXT("AddTrackAction_Description", "Adding animation bone track '{0}'."), FText::FromName(Name)).ToString(); } FRemoveTrackAction::FRemoveTrackAction(const FName& InName) : Name(InName) { } TUniquePtr FRemoveTrackAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { ensure(Model->IsValidBoneTrackName(Name)); TArray BoneTransforms; Model->GetBoneTrackTransforms(Name, BoneTransforms); TUniquePtr InverseAction = MakeUnique(Name, MoveTemp(BoneTransforms)); Controller->RemoveBoneTrack(Name, false); return InverseAction; } FString FRemoveTrackAction::ToStringInternal() const { return FText::Format(LOCTEXT("RemoveTrackAction_Description", "Removing animation bone Track '{0}'."), FText::FromName(Name)).ToString(); } FSetTrackKeysAction::FSetTrackKeysAction(const FName& InName, TArray& InTransformData) { Name = InName; TransformData = MoveTemp(InTransformData); } TUniquePtr FSetTrackKeysAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TArray CurrentBoneTransforms; Model->GetBoneTrackTransforms(Name, CurrentBoneTransforms); TUniquePtr InverseAction = MakeUnique(Name, CurrentBoneTransforms); TArray PosKeys; TArray RotKeys; TArray ScaleKeys; PosKeys.Reserve(TransformData.Num()); RotKeys.Reserve(TransformData.Num()); ScaleKeys.Reserve(TransformData.Num()); for (const FTransform& Transform : TransformData) { PosKeys.Add(FVector3f(Transform.GetLocation())); RotKeys.Add(FQuat4f(Transform.GetRotation())); ScaleKeys.Add(FVector3f(Transform.GetScale3D())); } Controller->SetBoneTrackKeys(Name, PosKeys, RotKeys, ScaleKeys, false); return InverseAction; } FString FSetTrackKeysAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetTrackKeysAction_Description", "Setting keys for animation bone track '{0}'."), FText::FromName(Name)).ToString(); } FResizePlayLengthInFramesAction::FResizePlayLengthInFramesAction(const IAnimationDataModel* InModel, FFrameNumber F0, FFrameNumber F1) : Frame0(F0), Frame1(F1) { Length = InModel->GetNumberOfFrames(); } TUniquePtr FResizePlayLengthInFramesAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(Model, Frame0, Frame1); Controller->ResizeNumberOfFrames(Length, Frame0, Frame1, false); return InverseAction; } FString FResizePlayLengthInFramesAction::ToStringInternal() const { return FText::Format(LOCTEXT("ResizePlayLengthInFramesAction_Description", "Resizing play length to {0} frames."), FText::AsNumber(Length.Value)).ToString(); } FSetFrameRateAction::FSetFrameRateAction(const IAnimationDataModel* InModel) { FrameRate = InModel->GetFrameRate(); } TUniquePtr FSetFrameRateAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(Model); Controller->SetFrameRate(FrameRate, false); return InverseAction; } FString FSetFrameRateAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetFrameRateAction_Description", "Setting Frame Rate to {0}."), FrameRate.ToPrettyText()).ToString(); } TUniquePtr FAddCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(CurveId); Controller->AddCurve(CurveId, Flags, false); return InverseAction; } FString FAddCurveAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("AddCurveAction_Description", "Adding {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FRemoveCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction; if (CurveId.CurveType == ERawCurveTrackTypes::RCT_Float) { const FFloatCurve& Curve = Model->GetFloatCurve(CurveId); InverseAction = MakeUnique(CurveId, Curve.GetCurveTypeFlags(), Curve.FloatCurve.GetConstRefOfKeys(), Curve.Color); } else if (CurveId.CurveType == ERawCurveTrackTypes::RCT_Transform) { const FTransformCurve& Curve = Model->GetTransformCurve(CurveId); InverseAction = MakeUnique(CurveId, Curve.GetCurveTypeFlags(), Curve); } Controller->RemoveCurve(CurveId, false); return InverseAction; } FString FRemoveCurveAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("RemoveCurveAction_Description", "Removing {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetCurveFlagsAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimCurveBase& Curve = Model->GetCurve(CurveId); const int32 CurrentFlags = Curve.GetCurveTypeFlags(); TUniquePtr InverseAction = MakeUnique(CurveId, CurrentFlags, CurveType); Controller->SetCurveFlags(CurveId, Flags, false); return InverseAction; } FString FSetCurveFlagsAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("SetCurveFlagsAction_Description", "Setting flags for {0} curve '{1}'."), FText::FromString(CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FRenameCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { Controller->RenameCurve(CurveId, NewCurveId, false); return MakeUnique(NewCurveId, CurveId); } FString FRenameCurveAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("RenameCurveAction_Description", "Renaming {0} curve '{1}' to '{2}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName), FText::FromName(NewCurveId.CurveName)).ToString(); } FScaleCurveAction::FScaleCurveAction(const FAnimationCurveIdentifier& InCurveId, float InOrigin, float InFactor, ERawCurveTrackTypes InCurveType) : CurveId(InCurveId), CurveType(InCurveType), Origin(InOrigin), Factor(InFactor) { ensure(CurveType == ERawCurveTrackTypes::RCT_Float); } TUniquePtr FScaleCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const float InverseFactor = 1.0f / Factor; TUniquePtr InverseAction = MakeUnique(CurveId, Origin, InverseFactor, CurveType); Controller->ScaleCurve(CurveId, Origin, Factor, false); return InverseAction; } FString FScaleCurveAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("ScaleCurveAction_Description", "Scaling {0} curve '{1}'."), FText::FromString(CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FAddFloatCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(CurveId); Controller->OpenBracket(LOCTEXT("AddFloatCurveAction_Description", "Adding float curve."), false); Controller->AddCurve(CurveId, Flags, false); Controller->SetCurveKeys(CurveId, Keys, false); Controller->SetCurveColor(CurveId, Color, false); Controller->CloseBracket(); return InverseAction; } FString FAddFloatCurveAction::ToStringInternal() const { return FText::Format(LOCTEXT("AddFloatCurveAction_Format", "Adding float curve '{0}'."), FText::FromName(CurveId.CurveName)).ToString(); } FAddTransformCurveAction::FAddTransformCurveAction(const FAnimationCurveIdentifier& InCurveId, int32 InFlags, const FTransformCurve& InTransformCurve) : CurveId(InCurveId), Flags(InFlags) { SubCurveKeys[0] = InTransformCurve.TranslationCurve.FloatCurves[0].GetConstRefOfKeys(); SubCurveKeys[1] = InTransformCurve.TranslationCurve.FloatCurves[1].GetConstRefOfKeys(); SubCurveKeys[2] = InTransformCurve.TranslationCurve.FloatCurves[2].GetConstRefOfKeys(); SubCurveKeys[3] = InTransformCurve.RotationCurve.FloatCurves[0].GetConstRefOfKeys(); SubCurveKeys[4] = InTransformCurve.RotationCurve.FloatCurves[1].GetConstRefOfKeys(); SubCurveKeys[5] = InTransformCurve.RotationCurve.FloatCurves[2].GetConstRefOfKeys(); SubCurveKeys[6] = InTransformCurve.ScaleCurve.FloatCurves[0].GetConstRefOfKeys(); SubCurveKeys[7] = InTransformCurve.ScaleCurve.FloatCurves[1].GetConstRefOfKeys(); SubCurveKeys[8] = InTransformCurve.ScaleCurve.FloatCurves[2].GetConstRefOfKeys(); } TUniquePtr FAddTransformCurveAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(CurveId); Controller->AddCurve(CurveId, Flags, false); for (int32 SubCurveIndex = 0; SubCurveIndex < 3; ++SubCurveIndex) { const ETransformCurveChannel Channel = static_cast(SubCurveIndex); for (int32 ChannelIndex = 0; ChannelIndex < 3; ++ChannelIndex) { const EVectorCurveChannel Axis = static_cast(ChannelIndex); FAnimationCurveIdentifier TargetCurveIdentifier = CurveId; UAnimationCurveIdentifierExtensions::GetTransformChildCurveIdentifier(TargetCurveIdentifier, Channel, Axis); Controller->SetCurveKeys(TargetCurveIdentifier, SubCurveKeys[(SubCurveIndex * 3) + ChannelIndex], false); } } return InverseAction; } FString FAddTransformCurveAction::ToStringInternal() const { return FText::Format(LOCTEXT("AddTransformCurveAction_Description", "Adding transform curve '{0}'."), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FAddRichCurveKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(CurveId, Key.Time); Controller->SetCurveKey(CurveId, Key, false); return InverseAction; } FString FAddRichCurveKeyAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("AddNamedRichCurveKeyAction_Description", "Adding key to {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetRichCurveKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FRichCurve& RichCurve = Model->GetRichCurve(CurveId); const FKeyHandle Handle = RichCurve.FindKey(Key.Time, 0.f); ensure(Handle != FKeyHandle::Invalid()); FRichCurveKey CurrentKey = RichCurve.GetKey(Handle); Controller->SetCurveKey(CurveId, Key, false); return MakeUnique(CurveId, CurrentKey); } FString FSetRichCurveKeyAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("SetNamedRichCurveKeyAction_Description", "Setting key for {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FRemoveRichCurveKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FRichCurve& RichCurve = Model->GetRichCurve(CurveId); const FKeyHandle Handle = RichCurve.FindKey(Time, 0.f); ensure(Handle != FKeyHandle::Invalid()); FRichCurveKey CurrentKey = RichCurve.GetKey(Handle); Controller->RemoveCurveKey(CurveId, Time, false); return MakeUnique(CurveId, CurrentKey); } FString FRemoveRichCurveKeyAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("RemoveNamedRichCurveKeyAction_Description", "Removing key from {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetRichCurveKeysAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FRichCurve& RichCurve = Model->GetRichCurve(CurveId); TUniquePtr InverseAction = MakeUnique(CurveId, RichCurve.GetConstRefOfKeys()); Controller->SetCurveKeys(CurveId, Keys, false); return InverseAction; } FString FSetRichCurveKeysAction::ToStringInternal() const { const FString FloatLabel(TEXT("float")); const FString TransformLabel(TEXT("transform")); return FText::Format(LOCTEXT("SetNamedRichCurveKeysAction_Description", "Replacing keys for {0} curve '{1}'."), FText::FromString(CurveId.CurveType == ERawCurveTrackTypes::RCT_Float ? FloatLabel : TransformLabel), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetRichCurveAttributesAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FRichCurve& RichCurve = Model->GetRichCurve(CurveId); FCurveAttributes CurrentAttributes; CurrentAttributes.SetPreExtrapolation(RichCurve.PreInfinityExtrap); CurrentAttributes.SetPostExtrapolation(RichCurve.PostInfinityExtrap); TUniquePtr InverseAction = MakeUnique(CurveId, CurrentAttributes); Controller->SetCurveAttributes(CurveId, Attributes, false); return InverseAction; } FString FSetRichCurveAttributesAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetCurveAttributesAction_Description", "Setting curve attributes '{0}'."), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetCurveColorAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimCurveBase& AnimationCurve = Model->GetCurve(CurveId); const FLinearColor CurrentColor = AnimationCurve.Color; Controller->SetCurveColor(CurveId, Color, false); return MakeUnique(CurveId, CurrentColor); } FString FSetCurveColorAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetCurveColorAction_Description", "Setting curve color '{0}'."), FText::FromName(CurveId.CurveName)).ToString(); } TUniquePtr FSetCurveCommentAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimCurveBase& AnimationCurve = Model->GetCurve(CurveId); const FString& CurrentComment = AnimationCurve.Comment; Controller->SetCurveComment(CurveId, Comment, false); return MakeUnique(CurveId, CurrentComment); } FString FSetCurveCommentAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetCurveCommentAction_Description", "Setting curve comment '{0}'."), FText::FromName(CurveId.CurveName)).ToString(); } FAddAtributeAction::FAddAtributeAction(const FAnimatedBoneAttribute& InAttribute) : AttributeId(InAttribute.Identifier) { Keys = InAttribute.Curve.GetConstRefOfKeys(); } TUniquePtr FAddAtributeAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TArray VoidValues; Algo::Transform(Keys, VoidValues, [](const FAttributeKey& Key) { return Key.GetValuePtr(); }); TArray Times; Algo::Transform(Keys, Times, [](const FAttributeKey& Key) { return Key.Time; }); Controller->AddAttribute(AttributeId, false); Controller->SetAttributeKeys(AttributeId, MakeArrayView(Times), MakeArrayView(VoidValues), AttributeId.GetType(), false); return MakeUnique(AttributeId); } FString FAddAtributeAction::ToStringInternal() const { return FText::Format(LOCTEXT("AddAttributeAction_Description", "Adding attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } TUniquePtr FRemoveAtributeAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimatedBoneAttribute& Attribute = Model->GetAttribute(AttributeId); TUniquePtr InverseAction = MakeUnique(Attribute); Controller->RemoveAttribute(AttributeId, false); return InverseAction; } FString FRemoveAtributeAction::ToStringInternal() const { return FText::Format(LOCTEXT("RemoveAttributeAction_Description", "Removing attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } TUniquePtr FAddAtributeKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { Controller->SetAttributeKey(AttributeId, Key.Time, Key.GetValuePtr(), AttributeId.GetType(), false); return MakeUnique(AttributeId, Key.Time); } FString FAddAtributeKeyAction::ToStringInternal() const { return FText::Format(LOCTEXT("AddAttributeKeyAction_Description", "Adding key to attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } TUniquePtr FSetAtributeKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimatedBoneAttribute& Attribute = Model->GetAttribute(AttributeId); const FKeyHandle Handle = Attribute.Curve.FindKey(Key.Time, 0.f); ensure(Handle != FKeyHandle::Invalid()); FAttributeKey CurrentKey = Attribute.Curve.GetKey(Handle); Controller->SetAttributeKey(AttributeId, Key.Time, Key.GetValuePtr(), AttributeId.GetType(), false); return MakeUnique(AttributeId, CurrentKey); } FString FSetAtributeKeyAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetAttributeKeyAction_Description", "Setting key on attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } TUniquePtr FRemoveAtributeKeyAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { const FAnimatedBoneAttribute& Attribute = Model->GetAttribute(AttributeId); const FKeyHandle Handle = Attribute.Curve.FindKey(Time, 0.f); ensure(Handle != FKeyHandle::Invalid()); FAttributeKey CurrentKey = Attribute.Curve.GetKey(Handle); Controller->RemoveAttributeKey(AttributeId, Time, false); return MakeUnique(AttributeId, CurrentKey); } FString FRemoveAtributeKeyAction::ToStringInternal() const { return FText::Format(LOCTEXT("RemoveAttributeKeyAction_Description", "Removing key from attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } FSetAtributeKeysAction::FSetAtributeKeysAction(const FAnimatedBoneAttribute& InAttribute) : AttributeId(InAttribute.Identifier) { Keys = InAttribute.Curve.GetConstRefOfKeys(); } TUniquePtr FSetAtributeKeysAction::ExecuteInternal(IAnimationDataModel* Model, IAnimationDataController* Controller) { TUniquePtr InverseAction = MakeUnique(Model->GetAttribute(AttributeId)); TArray VoidValues; Algo::Transform(Keys, VoidValues, [](const FAttributeKey& Key) { return Key.GetValuePtr(); }); TArray Times; Algo::Transform(Keys, Times, [](const FAttributeKey& Key) { return Key.Time; }); Controller->SetAttributeKeys(AttributeId, MakeArrayView(Times), MakeArrayView(VoidValues), AttributeId.GetType(), false); return InverseAction; } FString FSetAtributeKeysAction::ToStringInternal() const { return FText::Format(LOCTEXT("SetAttributeKeysAction_Description", "Replacing keys for attribute '{0}'."), FText::FromName(AttributeId.GetName())).ToString(); } } // namespace Anim } // namespace UE #endif // WITH_EDITOR #undef LOCTEXT_NAMESPACE // "AnimDataControllerActions"