I have been struggling with a problem lately, and have been looking for solutions in the documentation and elsewhere on the forums, but haven’t encountered any information about my problem, so I was hoping someone could help me out with this.
I am trying to make an automated tool that can take multiple sections of an animation and make it into separate animation clips.
So far I have managed to make a function that creates a new animation file from an existing animation with the correct length and in theory the animation should be in there too, but the character is just frozen unless I change the AdditiveAnimType to something besides No additive. This isn’t really a solution, as I need to get it to work under normal playback.
I assume there is something I should be doing in the function that I am currently not doing.
So I provide the code I use for the function below so you can have a look and see if you can find what I am doing wrong.
UAnimSequenceBase* UAnimLibrary::GenerateAnimationSegment(UAnimSequenceBase* Anim, FFloatInterval Segment, FString AssetPath)
{
if(!IsValid(Anim) || Segment.Size() <= 0)
return nullptr;
int Start = Anim->GetFrameAtTime(Segment.Min);
int End = Anim->GetFrameAtTime(Segment.Max);
auto Factory = NewObject<UAnimSequenceFactory>();
Factory->TargetSkeleton = Anim->GetSkeleton();
FString AssetName = FPaths::GetBaseFilename(AssetPath);
FString FinalPackageName = AssetPath;
UPackage* Package = CreatePackage(*FinalPackageName);
UPackage* OutermostPkg = Package->GetPackage();
auto Sequence = Cast<UAnimSequence>(Factory->FactoryCreateNew(UAnimSequence::StaticClass(), OutermostPkg, *AssetName, RF_Standalone | RF_Public, NULL, GWarn));
auto& Controller = Sequence->GetController();
auto DataModel = Sequence->GetDataModel();
Sequence->MarkPackageDirty();
Package->SetDirtyFlag(true);
auto FrameRate = Anim->GetSamplingFrameRate();
Controller.SetPlayLength(FrameRate.AsInterval() * (End - Start));
if(auto AnimData = Anim->GetDataModel())
{
auto& BoneTracks = AnimData->GetBoneAnimationTracks();
auto& SequenceBoneTracks = *const_cast<TArray<FBoneAnimationTrack>*>(&DataModel->GetBoneAnimationTracks());
FBoneAnimationTrack NewTrack;
for(auto& BoneTrack : BoneTracks)
{
NewTrack.BoneTreeIndex = BoneTrack.BoneTreeIndex;
NewTrack.Name = BoneTrack.Name;
NewTrack.InternalTrackData.PosKeys.Reset();
NewTrack.InternalTrackData.RotKeys.Reset();
NewTrack.InternalTrackData.ScaleKeys.Reset();
NewTrack.InternalTrackData.PosKeys.Reserve(End - Start);
auto PosData = BoneTrack.InternalTrackData.PosKeys.GetData();
NewTrack.InternalTrackData.PosKeys.Append(PosData + Start, End - Start);
NewTrack.InternalTrackData.RotKeys.Reserve(End - Start);
auto RotData = BoneTrack.InternalTrackData.RotKeys.GetData();
NewTrack.InternalTrackData.RotKeys.Append(RotData + Start, End - Start);
NewTrack.InternalTrackData.ScaleKeys.Reserve(End - Start);
auto ScaleData = BoneTrack.InternalTrackData.ScaleKeys.GetData();
NewTrack.InternalTrackData.ScaleKeys.Append(ScaleData + Start, End - Start);
SequenceBoneTracks.Add(NewTrack);
}
Controller.SetFrameRate(FrameRate, true);
DataModel->GetModifiedEvent().Broadcast(EAnimDataModelNotifyType::Populated, DataModel, FAnimDataModelNotifPayload());
TSharedPtr<FAnimCompressContext> CompressContext = MakeShareable(new FAnimCompressContext(false, false));
Sequence->RequestAnimCompression(FRequestAnimCompressionParams(false, CompressContext));
Sequence->PostEditChange();
Sequence->AddToRoot();
FAssetRegistryModule::AssetCreated(Sequence);
return Sequence;
}
return nullptr;
}