52 TWeakObjectPtr<UAnimSequence> FinalAnimation;
56 return FinalAnimation;
65 return FinalAnimation;
69 FText InvalidPathReason;
70 bool const bValidPackageName = FPackageName::IsValidLongPackageName(InAssetPath,
false, &InvalidPathReason);
71 if (bValidPackageName ==
false)
73 UE_LOG(LogAnimation, Log, TEXT(
"%s is an invalid asset path, prompting user for new asset path. Reason: %s"), *InAssetPath, *InvalidPathReason.ToString());
76 FString ValidatedAssetPath = InAssetPath;
77 FString ValidatedAssetName = InAssetName;
79 UObject* Parent = bValidPackageName ? CreatePackage(*ValidatedAssetPath) :
nullptr;
80 if (Parent ==
nullptr)
85 return FinalAnimation;
88 Parent = CreatePackage(*ValidatedAssetPath);
91 UObject*
const Object = LoadObject<UObject>(Parent, *ValidatedAssetName,
nullptr, LOAD_Quiet,
nullptr);
95 EAppReturnType::Type ReturnValue = FMessageDialog::Open(EAppMsgType::YesNo, NSLOCTEXT(
"UnrealEd",
"Error_AssetExist",
"Asset with same name exists. Do you wish to overwrite it?"));
96 if (ReturnValue == EAppReturnType::No)
98 return FinalAnimation;
103 TArray<FTransform> LocalPoses;
111 UAnimSequence*
const NewSeq = NewObject<UAnimSequence>(Parent, *ValidatedAssetName, RF_Public | RF_Standalone);
117 NewSeq->SetSkeleton(BaseAnimation->GetSkeleton());
125 FAssetRegistryModule::AssetCreated(NewSeq);
129 UAnimSequence* AnimationObject = NewSeq;
131 AnimationObject->RecycleAnimSequence();
134 AnimationObject->BoneCompressionSettings = BaseAnimation->BoneCompressionSettings;
138 AnimationObject->BoneCompressionSettings = FAnimationUtils::GetDefaultAnimationBoneCompressionSettings();
141 AnimationObject->SequenceLength = 4.f;
142 AnimationObject->SetRawNumberOfFrame(1);
146 for (FName TrackName : BaseAnimation->GetAnimationTrackNames())
148 AnimationObject->AddNewRawTrack(TrackName);
154 for (
int i = 0; i < LocalPoses.Num() && i < numBones; ++i)
156 AnimationObject->AddNewRawTrack(
HandSocketComponent->VisualizationMesh->GetRefSkeleton().GetBoneName(i));
162 AnimationObject->RetargetSource = BaseAnimation->RetargetSource;
173 for (int32 TrackIndex = 0; TrackIndex < BaseAnimation->GetRawAnimationData().Num(); ++TrackIndex)
175 FRawAnimSequenceTrack& RawTrack = BaseAnimation->GetRawAnimationTrack(TrackIndex);
177 bool bHadLoc =
false;
178 bool bHadRot =
false;
179 bool bHadScale =
false;
180 FVector Loc = FVector::ZeroVector;
181 FQuat Rot = FQuat::Identity;
182 FVector Scale = FVector::ZeroVector;
184 if (RawTrack.PosKeys.Num())
186 Loc = RawTrack.PosKeys[0];
190 if (RawTrack.RotKeys.Num())
192 Rot = RawTrack.RotKeys[0];
196 if (RawTrack.ScaleKeys.Num())
198 Scale = RawTrack.ScaleKeys[0];
202 FTransform FinalTrans(Rot, Loc, Scale);
204 FName TrackName = (BaseAnimation->GetAnimationTrackNames())[TrackIndex];
206 FQuat DeltaQuat = FQuat::Identity;
209 if (HandPair.BoneName == TrackName)
211 DeltaQuat = HandPair.DeltaPose;
217 FinalTrans.ConcatenateRotation(DeltaQuat);
218 FinalTrans.NormalizeRotation();
220 FRawAnimSequenceTrack& RawNewTrack = AnimationObject->GetRawAnimationTrack(TrackIndex);
222 RawNewTrack.PosKeys.Add(FinalTrans.GetTranslation());
224 RawNewTrack.RotKeys.Add(FinalTrans.GetRotation());
226 RawNewTrack.ScaleKeys.Add(FinalTrans.GetScale3D());
232 USkeleton* AnimSkeleton = SkeletalMesh->GetSkeleton();
233 for (int32 TrackIndex = 0; TrackIndex < AnimationObject->GetRawAnimationData().Num(); ++TrackIndex)
236 int32 BoneTreeIndex = AnimationObject->GetSkeletonIndexFromRawDataTrackIndex(TrackIndex);
237 if (BoneTreeIndex != INDEX_NONE)
239 int32 BoneIndex = AnimSkeleton->GetMeshBoneIndexFromSkeletonBoneIndex(SkeletalMesh, BoneTreeIndex);
241 FTransform LocalTransform = LocalPoses[BoneIndex];
244 FName BoneName = AnimSkeleton->GetReferenceSkeleton().GetBoneName(BoneIndex);
246 FQuat DeltaQuat = FQuat::Identity;
249 if (HandPair.BoneName == BoneName)
251 DeltaQuat = HandPair.DeltaPose;
255 LocalTransform.ConcatenateRotation(DeltaQuat);
256 LocalTransform.NormalizeRotation();
258 FRawAnimSequenceTrack& RawTrack = AnimationObject->GetRawAnimationTrack(TrackIndex);
259 RawTrack.PosKeys.Add(LocalTransform.GetTranslation());
260 RawTrack.RotKeys.Add(LocalTransform.GetRotation());
261 RawTrack.ScaleKeys.Add(LocalTransform.GetScale3D());
272 AnimationObject->InitializeNotifyTrack();
273 AnimationObject->PostProcessSequence();
274 AnimationObject->MarkPackageDirty();
278 UPackage*
const Package = AnimationObject->GetOutermost();
279 FString
const PackageName = Package->GetName();
280 FString
const PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
282 double StartTime = FPlatformTime::Seconds();
284 UPackage::SavePackage(Package, NULL, RF_Standalone, *PackageFileName, GError,
nullptr,
false,
true, SAVE_NoError);
286 double ElapsedTime = FPlatformTime::Seconds() - StartTime;
287 UE_LOG(LogAnimation, Log, TEXT(
"Animation Recorder saved %s in %0.2f seconds"), *PackageName, ElapsedTime);
290 FinalAnimation = AnimationObject;
291 return FinalAnimation;
294 return FinalAnimation;
454 TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized;
455 DetailBuilder.GetObjectsBeingCustomized(ObjectsBeingCustomized);
457 if (ObjectsBeingCustomized.Num() == 1)
459 UHandSocketComponent* CurrentHandSocket = Cast<UHandSocketComponent>(ObjectsBeingCustomized[0]);
460 if (CurrentHandSocket != NULL)
464 TSharedPtr<FComponentVisualizer> Visualizer = GUnrealEd->FindComponentVisualizer(CurrentHandSocket->GetClass());
509 DetailBuilder.HideCategory(
FName(
"ComponentTick"));
510 DetailBuilder.HideCategory(
FName(
"GameplayTags"));
511 DetailBuilder.HideCategory(
FName(
"VRGripInterface"));
512 DetailBuilder.HideCategory(
FName(
"VRGripInterface|Replication"));
513 DetailBuilder.HideCategory(
FName(
"Tags"));
514 DetailBuilder.HideCategory(
FName(
"AssetUserData"));
515 DetailBuilder.HideCategory(
FName(
"Events"));
516 DetailBuilder.HideCategory(
FName(
"Activation"));
517 DetailBuilder.HideCategory(
FName(
"Cooking"));
518 DetailBuilder.HideCategory(
FName(
"ComponentReplication"));
520 TSharedPtr<IPropertyHandle> LockedLocationProperty = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, bDecoupleMeshPlacement));
521 TSharedPtr<IPropertyHandle> HandRelativePlacementProperty = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, HandRelativePlacement));
522 TSharedPtr<IPropertyHandle> LeftHandDominateProperty = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, bLeftHandDominant));
525 HandRelativePlacementProperty->SetOnPropertyValueChanged(OnHandRelativeChangedDelegate);
528 LockedLocationProperty->SetOnPropertyValueChanged(OnLockedStateChangedDelegate);
531 LeftHandDominateProperty->SetOnPropertyValueChanged(OnLeftDominateChangedDelegate);
533 TSharedPtr<IPropertyHandle> ShowVisualizationProperty = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, bShowVisualizationMesh));
536 ShowVisualizationProperty->SetOnPropertyValueChanged(OnShowVisChangedDelegate);
538 DetailBuilder.EditCategory(
"Hand Animation")
539 .AddCustomRow(NSLOCTEXT(
"HandSocketDetails",
"UpdateHandSocket",
"Save Current Pose"))
543 .Font(IDetailLayoutBuilder::GetDetailFont())
544 .Text(NSLOCTEXT(
"HandSocketDetails",
"UpdateHandSocket",
"Save Current Pose"))
547 .MaxDesiredWidth(125.f)
548 .MinDesiredWidth(125.f)
552 .VAlign(VAlign_Center)
553 .HAlign(HAlign_Center)
557 .Font(IDetailLayoutBuilder::GetDetailFont())
558 .Text(NSLOCTEXT(
"HandSocketDetails",
"UpdateHandSocket",
"Save"))
637 AssetPath = FText::FromString(FPackageName::GetLongPackagePath(InArgs._DefaultAssetPath.ToString()));
638 AssetName = FText::FromString(FPackageName::GetLongPackageAssetName(InArgs._DefaultAssetPath.ToString()));
646 AssetPath = FText::FromString(TEXT(
"/Game"));
657 FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>(
"AssetTools");
658 FString OutPackageName, OutAssetName;
659 FString PackageName =
AssetPath.ToString() + TEXT(
"/NewAnimation");
661 AssetToolsModule.Get().CreateUniqueAssetName(PackageName, TEXT(
""), OutPackageName, OutAssetName);
662 AssetName = FText::FromString(OutAssetName);
665 FPathPickerConfig PathPickerConfig;
666 PathPickerConfig.DefaultPath =
AssetPath.ToString();
668 PathPickerConfig.bAddDefaultPath =
true;
670 FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(
"ContentBrowser");
672 SWindow::Construct(SWindow::FArguments()
673 .Title(LOCTEXT(
"SCreateHandAnimationDlg_Title",
"Create New Animation Object"))
674 .SupportsMinimize(
false)
675 .SupportsMaximize(
false)
677 .ClientSize(FVector2D(450, 450))
681 + SVerticalBox::Slot()
685 .BorderImage(FEditorStyle::GetBrush(
"ToolPanel.GroupBorder"))
689 + SVerticalBox::Slot()
693 .Text(LOCTEXT(
"SelectPath",
"Select Path to create animation"))
694 .Font(FCoreStyle::GetDefaultFontStyle(
"Regular", 14))
697 + SVerticalBox::Slot()
701 ContentBrowserModule.Get().CreatePathPicker(PathPickerConfig)
704 + SVerticalBox::Slot()
710 + SVerticalBox::Slot()
716 + SHorizontalBox::Slot()
718 .Padding(0, 0, 10, 0)
719 .VAlign(VAlign_Center)
722 .Text(LOCTEXT(
"AnimationName",
"Animation Name"))
725 + SHorizontalBox::Slot()
727 SNew(SEditableTextBox)
730 .MinDesiredWidth(250)
736 + SVerticalBox::Slot()
738 .HAlign(HAlign_Right)
741 SNew(SUniformGridPanel)
742 .SlotPadding(FEditorStyle::GetMargin(
"StandardDialog.SlotPadding"))
743 .MinDesiredSlotWidth(FEditorStyle::GetFloat(
"StandardDialog.MinDesiredSlotWidth"))
744 .MinDesiredSlotHeight(FEditorStyle::GetFloat(
"StandardDialog.MinDesiredSlotHeight"))
745 + SUniformGridPanel::Slot(0, 0)
748 .HAlign(HAlign_Center)
749 .ContentPadding(FEditorStyle::GetMargin(
"StandardDialog.ContentPadding"))
750 .Text(LOCTEXT(
"OK",
"OK"))
753 + SUniformGridPanel::Slot(1, 0)
756 .HAlign(HAlign_Center)
757 .ContentPadding(FEditorStyle::GetMargin(
"StandardDialog.ContentPadding"))
758 .Text(LOCTEXT(
"Cancel",
"Cancel"))