void UAnimPreviewInstance::MontagePreview_JumpToEnd() { if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { int32 SectionIdx = 0; if (MontagePreviewType == EMPT_Normal) { SectionIdx = MontagePreviewStartSectionIdx; } // TODO hack - Montage_JumpToSectionsEnd requires montage being played bool bWasPlaying = IsPlayingMontage(); if (! bWasPlaying) { MontagePreview_Restart(); } if (PlayRate < 0.f) { Montage_JumpToSection(Montage->GetSectionName(MontagePreview_FindLastSection(SectionIdx))); } else { Montage_JumpToSectionsEnd(Montage->GetSectionName(MontagePreview_FindLastSection(SectionIdx))); } if (! bWasPlaying) { MontagePreview_SetPlaying(false); } } }
void UAnimPreviewInstance::MontagePreview_StepBackward() { if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { bool bWasPlaying = IsPlayingMontage() && (bLooping || bPlaying); // we need to handle non-looped case separately, even if paused during playthrough MontagePreview_SetReverse(true); if (! bWasPlaying) { if (! bLooping) { float StoppedAt = CurrentTime; if (! bWasPlaying) { // play montage but at last known location MontagePreview_Restart(); SetPosition(StoppedAt, false); } int32 LastPreviewSectionIdx = MontagePreview_FindLastSection(MontagePreviewStartSectionIdx); if (FMath::Abs(CurrentTime - (Montage->CompositeSections[LastPreviewSectionIdx].GetTime() + Montage->GetSectionLength(LastPreviewSectionIdx))) <= MontagePreview_CalculateStepLength()) { // special case as we could stop at the end of our last section which is also beginning of following section - we don't want to get stuck there, but be inside of our starting section Montage_JumpToSection(Montage->GetSectionName(LastPreviewSectionIdx)); } else if (FMath::Abs(CurrentTime - Montage->CompositeSections[MontagePreviewStartSectionIdx].GetTime()) <= MontagePreview_CalculateStepLength()) { // we're at the end of playing backward, jump right to the end Montage_JumpToSectionsEnd(Montage->GetSectionName(MontagePreviewStartSectionIdx)); if (! bWasPlaying) { MontagePreview_SetPlaying(false); } return; // can't go further than beginning of first section } } else { MontagePreview_Restart(); } } MontagePreview_SetPlaying(true); // Advance a single frame, leaving it paused afterwards int32 NumFrames = Montage->GetNumberOfFrames(); // Add DELTA to prefer next frame when we're close to the boundary float CurrentFraction = CurrentTime / Montage->SequenceLength + DELTA; float NextFrame = FMath::Clamp<float>(FMath::FloorToFloat(CurrentFraction * NumFrames) - 1.0f, 0, NumFrames); float NewTime = Montage->SequenceLength * (NextFrame / NumFrames); GetSkelMeshComponent()->GlobalAnimRateScale = 1.0f; GetSkelMeshComponent()->TickAnimation(FMath::Abs(NewTime - CurrentTime)); MontagePreview_SetPlaying(false); } }
void UAnimSingleNodeInstance::RestartMontage(UAnimMontage * Montage, FName FromSection) { if( Montage == CurrentAsset ) { Montage_Play(Montage, PlayRate); if( FromSection != NAME_None ) { Montage_JumpToSection(FromSection); } SetMontageLoop(Montage, bLooping, FromSection); } }
void UAnimPreviewInstance::RestartMontage(UAnimMontage* Montage, FName FromSection) { if (Montage == CurrentAsset) { MontagePreviewType = EMPT_Normal; Montage_Play(Montage, PlayRate); if (FromSection != NAME_None) { Montage_JumpToSection(FromSection); } MontagePreview_SetLoopNormal(bLooping, Montage->GetSectionIndex(FromSection)); } }
void UAnimPreviewInstance::MontagePreview_PreviewNormal(int32 FromSectionIdx) { if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { int32 PreviewFromSection = FromSectionIdx; if (FromSectionIdx != INDEX_NONE) { MontagePreviewStartSectionIdx = MontagePreview_FindFirstSectionAsInMontage(FromSectionIdx); } else { FromSectionIdx = MontagePreviewStartSectionIdx; PreviewFromSection = MontagePreviewStartSectionIdx; } MontagePreviewType = EMPT_Normal; Montage_Play(Montage, PlayRate); MontagePreview_SetLoopNormal(bLooping, FromSectionIdx); Montage_JumpToSection(Montage->GetSectionName(PreviewFromSection)); MontagePreview_RemoveBlendOut(); bPlaying = true; } }