int32 UAnimPreviewInstance::MontagePreview_FindLastSection(int32 StartSectionIdx) { int32 ResultIdx = StartSectionIdx; if (UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset)) { if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { int32 TotalSection = Montage->CompositeSections.Num(); if (TotalSection > 0) { TArray<bool> AlreadyVisited; AlreadyVisited.AddZeroed(TotalSection); int32 CurrentSectionIdx = StartSectionIdx; while (CurrentSectionIdx != INDEX_NONE && ! AlreadyVisited[CurrentSectionIdx]) { AlreadyVisited[CurrentSectionIdx] = true; ResultIdx = CurrentSectionIdx; if (CurMontageInstance->NextSections.IsValidIndex(CurrentSectionIdx)) { CurrentSectionIdx = CurMontageInstance->NextSections[CurrentSectionIdx]; } } } } } return ResultIdx; }
void UAnimSingleNodeInstance::SetPosition(float InPosition, bool bFireNotifies) { float PreviousTime = CurrentTime; CurrentTime = FMath::Clamp<float>(InPosition, 0.f, GetLength()); if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->SetPosition(CurrentTime); } // Handle notifies // the way AnimInstance handles notifies doesn't work for single node because this does not tick or anything // this will need to handle manually, emptying, it and collect it, and trigger them at once. if (bFireNotifies) { UAnimSequenceBase * SequenceBase = Cast<UAnimSequenceBase> (CurrentAsset); if (SequenceBase) { AnimNotifies.Empty(); TArray<const FAnimNotifyEvent*> Notifies; SequenceBase->GetAnimNotifiesFromDeltaPositions(PreviousTime, CurrentTime, Notifies); if ( Notifies.Num() > 0 ) { // single node instance only has 1 asset at a time AddAnimNotifies(Notifies, 1.0f); } TriggerAnimNotifies(0.f); } } }
void UAnimPreviewInstance::MontagePreview_RemoveBlendOut() { if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->DefaultBlendTimeMultiplier = 0.0f; } }
void UAnimPreviewInstance::MontagePreview_SetPlaying(bool bIsPlaying) { bPlaying = bIsPlaying; if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->bPlaying = bIsPlaying; } else if (bPlaying) { UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset); if (Montage) { switch (MontagePreviewType) { case EMPT_AllSections: MontagePreview_PreviewAllSections(); break; case EMPT_Normal: default: MontagePreview_PreviewNormal(); break; } } } }
void UAnimInstance::Montage_SetBlendingOutDelegate(FOnMontageBlendingOutStarted & OnMontageBlendingOut) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { CurMontageInstance->OnMontageBlendingOutStarted = OnMontageBlendingOut; } }
void UAnimInstance::Montage_SetEndDelegate(FOnMontageEnded & OnMontageEnded) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { CurMontageInstance->OnMontageEnded = OnMontageEnded; } }
void UAnimInstance::Montage_Stop(float InBlendOutTime) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { CurMontageInstance->Stop(InBlendOutTime); } }
void UAnimInstance::Montage_SetPlayRate(UAnimMontage* Montage, float NewPlayRate) { FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance(); if( CurMontageInstance ) { CurMontageInstance->PlayRate = NewPlayRate; } }
void UAnimSingleNodeInstance::SetPlayRate(float InPlayRate) { PlayRate = InPlayRate; if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->SetPlayRate(InPlayRate); } }
void UAnimInstance::UpdateRootMotionMontageInstance() { FAnimMontageInstance * ActiveMontageInstance = GetActiveMontageInstance(); const bool bValidRootMotionInstance = (ActiveMontageInstance && ActiveMontageInstance->IsValid() && ActiveMontageInstance->Montage && (ActiveMontageInstance->Montage->bEnableRootMotionTranslation || ActiveMontageInstance->Montage->bEnableRootMotionRotation) ); RootMotionMontageInstance = bValidRootMotionInstance ? ActiveMontageInstance : NULL; }
void UAnimInstance::Montage_SetPosition(UAnimMontage* Montage, float NewPosition) { // @laurent we probably want (an option?) to advance time rather than jump? As that skips notifies/events? FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance(); if( CurMontageInstance ) { CurMontageInstance->Position = NewPosition; } }
void UAnimPreviewInstance::MontagePreview_SetReverse(bool bInReverse) { Super::SetReverse(bInReverse); if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { // copy the current playrate CurMontageInstance->SetPlayRate(PlayRate); } }
FOnMontageBlendingOutStarted* UAnimInstance::Montage_GetBlendingOutDelegate() { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { return &CurMontageInstance->OnMontageBlendingOutStarted; } return NULL; }
void UAnimSingleNodeInstance::Montage_Advance(float DeltaTime) { Super::Montage_Advance(DeltaTime); FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { CurrentTime = CurMontageInstance->GetPosition(); } }
UAnimMontage * UAnimInstance::GetCurrentActiveMontage() { FAnimMontageInstance* CurrentActiveMontage = GetActiveMontageInstance(); if (CurrentActiveMontage) { return CurrentActiveMontage->Montage; } return NULL; }
int32 UAnimInstance::Montage_GetNextSectionID(UAnimMontage* Montage, int32 CurrentSectionID) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if( CurMontageInstance && CurrentSectionID < CurMontageInstance->NextSections.Num() ) { return CurMontageInstance->NextSections[CurrentSectionID]; } return INDEX_NONE; }
FName UAnimInstance::Montage_GetCurrentSection() { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance ) { return CurMontageInstance->GetCurrentSection(); } return NAME_None; }
void UAnimInstance::Montage_SetNextSection(FName SectionNameToChange, FName NextSection) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance && CurMontageInstance->ChangeNextSection(SectionNameToChange, NextSection) == false ) { UE_LOG(LogAnimation, Warning, TEXT("Changing section from %s to %s failed for Montage (%s) "), *SectionNameToChange.ToString(), *NextSection.ToString(), *CurMontageInstance->Montage->GetName() ); } else { OnMontagePositionChanged(CurMontageInstance, NextSection); } }
void UAnimInstance::Montage_JumpToSectionsEnd(FName SectionName) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); if ( CurMontageInstance && CurMontageInstance->ChangePositionToSection(SectionName, CurMontageInstance->PlayRate >= 0.0f) == false ) { UE_LOG(LogAnimation, Warning, TEXT("Jumping section to %s failed for Montage (%s) "), *SectionName.ToString(), *CurMontageInstance->Montage->GetName() ); } else { OnMontagePositionChanged(CurMontageInstance, SectionName); } }
void UAnimSingleNodeInstance::SetPlaying(bool bIsPlaying) { bPlaying = bIsPlaying; if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->bPlaying = bIsPlaying; } else if (bPlaying) { UAnimMontage* Montage = Cast<UAnimMontage>(CurrentAsset); if (Montage) { RestartMontage(Montage); } } }
bool UAnimInstance::IsPlayingSlotAnimation(UAnimSequenceBase* Asset, FName SlotNodeName ) { // check if this is playing FAnimMontageInstance * CurrentInstance = GetActiveMontageInstance(); // make sure what is active right now is transient that we created by request if ( CurrentInstance && CurrentInstance->Montage && CurrentInstance->Montage->GetOuter() == GetTransientPackage() ) { UAnimMontage * CurMontage = CurrentInstance->Montage; const FAnimTrack * AnimTrack = CurMontage->GetAnimationData(SlotNodeName); if (AnimTrack && AnimTrack->AnimSegments.Num() == 1) { // find if the return (AnimTrack->AnimSegments[0].AnimReference == Asset); } } return false; }
void UAnimSingleNodeInstance::SetPosition(float InPosition, bool bFireNotifies) { float PreviousTime = CurrentTime; CurrentTime = FMath::Clamp<float>(InPosition, 0.f, GetLength()); if (FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance()) { CurMontageInstance->SetPosition(CurrentTime); } // Handle notifies // the way AnimInstance handles notifies doesn't work for single node because this does not tick or anything // this will need to handle manually, emptying, it and collect it, and trigger them at once. if (bFireNotifies) { UAnimSequenceBase * SequenceBase = Cast<UAnimSequenceBase> (CurrentAsset); if (SequenceBase) { AnimNotifies.Empty(); TArray<const FAnimNotifyEvent*> Notifies; SequenceBase->GetAnimNotifiesFromDeltaPositions(PreviousTime, CurrentTime, Notifies); if ( Notifies.Num() > 0 ) { // single node instance only has 1 asset at a time AddAnimNotifies(Notifies, 1.0f); } TriggerAnimNotifies(0.f); // since this is singlenode instance, if position changes, we can't keep old morphtarget curves // we clear it and evaluate curve here with new asset. MorphTargetCurves.Empty(); MaterialParameterCurves.Empty(); // Evaluate Curve data now - even if time did not move, we still need to return curve if it exists SequenceBase->EvaluateCurveData(this, CurrentTime, 1.0); } } }
void UAnimSingleNodeInstance::NativeUpdateAnimation(float DeltaTimeX) { float NewDeltaTime = DeltaTimeX; if (bReverse) { NewDeltaTime = -NewDeltaTime; } UAnimSequence* PreviewBasePose = NULL; if (!bPlaying) { // if not playing, make DeltaTime to be 0.f; // we still have to tick when NewDeltaTime == 0.f for retrieving curve datas // -i.e. Morph Target Curves // if we need an optimization, we can just grab curve separate, but for now this is better for consistency NewDeltaTime = 0.f; } if(CurrentAsset != NULL) { if (UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(CurrentAsset)) { BlendSpaceAdvanceImmediate(BlendSpace, BlendSpaceInput, BlendSampleData, BlendFilter, bLooping, PlayRate, NewDeltaTime, CurrentTime); #if WITH_EDITORONLY_DATA PreviewBasePose = BlendSpace->PreviewBasePose; #endif } else if (UAnimSequence* Sequence = Cast<UAnimSequence>(CurrentAsset)) { SequenceAdvanceImmediate(Sequence, bLooping, PlayRate, NewDeltaTime, CurrentTime); // if it's not looping, just set play to be false when reached to end if (!bLooping) { if ((bReverse && CurrentTime <= 0.f) || (!bReverse && CurrentTime >= Sequence->SequenceLength)) { SetPlaying(false); } } } else if(UAnimComposite* Composite = Cast<UAnimComposite>(CurrentAsset)) { SequenceAdvanceImmediate(Composite, bLooping, PlayRate, NewDeltaTime, CurrentTime); // if it's not looping, just set play to be false when reached to end if (!bLooping) { if ((bReverse && CurrentTime <= 0.f) || (!bReverse && CurrentTime >= Composite->SequenceLength)) { SetPlaying(false); } } } else if (UAnimMontage * Montage = Cast<UAnimMontage>(CurrentAsset)) { // Full weight , if you don't have slot track, you won't be able to see animation playing if ( Montage->SlotAnimTracks.Num() > 0 ) { UpdateSlotNodeWeight(Montage->SlotAnimTracks[0].SlotName, 1.f); } // get the montage position // @todo anim: temporarily just choose first slot and show the location FAnimMontageInstance * ActiveMontageInstance = GetActiveMontageInstance(); if (ActiveMontageInstance) { CurrentTime = ActiveMontageInstance->Position; } else if (bPlaying) { SetPlaying(false); } #if WITH_EDITORONLY_DATA PreviewBasePose = Montage->PreviewBasePose; #endif } } else if(CurrentVertexAnim != NULL) { float MoveDelta = NewDeltaTime * PlayRate; FAnimationRuntime::AdvanceTime(bLooping, MoveDelta, CurrentTime, CurrentVertexAnim->GetAnimLength()); } #if WITH_EDITORONLY_DATA if(PreviewBasePose) { float MoveDelta = NewDeltaTime * PlayRate; const bool bIsPreviewPoseLooping = true; FAnimationRuntime::AdvanceTime(bIsPreviewPoseLooping, MoveDelta, PreviewPoseCurrentTime, PreviewBasePose->SequenceLength); } #endif }
float UAnimInstance::Montage_GetPlayRate(UAnimMontage* Montage) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); return CurMontageInstance ? CurMontageInstance->PlayRate : 0.f; }
float UAnimInstance::Montage_GetPosition(UAnimMontage* Montage) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); return CurMontageInstance ? CurMontageInstance->Position : 0.f; }
bool UAnimInstance::Montage_IsPlaying(UAnimMontage * Montage) { FAnimMontageInstance * CurMontageInstance = GetActiveMontageInstance(); return ( CurMontageInstance && CurMontageInstance->Montage == Montage && CurMontageInstance->IsPlaying() ); }
/** Has Montage been stopped? */ bool UAnimInstance::Montage_GetIsStopped(UAnimMontage* Montage) { FAnimMontageInstance* CurMontageInstance = GetActiveMontageInstance(); return (!CurMontageInstance || (CurMontageInstance->Montage != Montage) || (CurMontageInstance->DesiredWeight == 0.f)); }
void UAnimSingleNodeInstance::NativeUpdateAnimation(float DeltaTimeX) { float NewPlayRate = PlayRate; UAnimSequence* PreviewBasePose = NULL; if (bPlaying == false) { // we still have to tick animation when bPlaying is false because NewPlayRate = 0.f; } if(CurrentAsset != NULL) { FAnimGroupInstance* SyncGroup; if (UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(CurrentAsset)) { FAnimTickRecord& TickRecord = CreateUninitializedTickRecord(INDEX_NONE, /*out*/ SyncGroup); MakeBlendSpaceTickRecord(TickRecord, BlendSpace, BlendSpaceInput, BlendSampleData, BlendFilter, bLooping, NewPlayRate, 1.f, /*inout*/ CurrentTime); #if WITH_EDITORONLY_DATA PreviewBasePose = BlendSpace->PreviewBasePose; #endif } else if (UAnimSequence* Sequence = Cast<UAnimSequence>(CurrentAsset)) { FAnimTickRecord& TickRecord = CreateUninitializedTickRecord(INDEX_NONE, /*out*/ SyncGroup); MakeSequenceTickRecord(TickRecord, Sequence, bLooping, NewPlayRate, 1.f, /*inout*/ CurrentTime); // if it's not looping, just set play to be false when reached to end if (!bLooping) { if ((NewPlayRate < 0.f && CurrentTime <= 0.f) || (NewPlayRate > 0.f && CurrentTime >= Sequence->SequenceLength)) { SetPlaying(false); } } } else if(UAnimComposite* Composite = Cast<UAnimComposite>(CurrentAsset)) { FAnimTickRecord& TickRecord = CreateUninitializedTickRecord(INDEX_NONE, /*out*/ SyncGroup); MakeSequenceTickRecord(TickRecord, Composite, bLooping, NewPlayRate, 1.f, /*inout*/ CurrentTime); // if it's not looping, just set play to be false when reached to end if (!bLooping) { if ((NewPlayRate < 0.f && CurrentTime <= 0.f) || (NewPlayRate > 0.f && CurrentTime >= Composite->SequenceLength)) { SetPlaying(false); } } } else if (UAnimMontage * Montage = Cast<UAnimMontage>(CurrentAsset)) { // Full weight , if you don't have slot track, you won't be able to see animation playing if ( Montage->SlotAnimTracks.Num() > 0 ) { UpdateSlotNodeWeight(Montage->SlotAnimTracks[0].SlotName, 1.f); } // get the montage position // @todo anim: temporarily just choose first slot and show the location FAnimMontageInstance * ActiveMontageInstance = GetActiveMontageInstance(); if (ActiveMontageInstance) { CurrentTime = ActiveMontageInstance->GetPosition(); } else if (bPlaying) { SetPlaying(false); } #if WITH_EDITORONLY_DATA PreviewBasePose = Montage->PreviewBasePose; #endif } } else if(CurrentVertexAnim != NULL) { float MoveDelta = DeltaTimeX * NewPlayRate; FAnimationRuntime::AdvanceTime(bLooping, MoveDelta, CurrentTime, CurrentVertexAnim->GetAnimLength()); } #if WITH_EDITORONLY_DATA if(PreviewBasePose) { float MoveDelta = DeltaTimeX * NewPlayRate; const bool bIsPreviewPoseLooping = true; FAnimationRuntime::AdvanceTime(bIsPreviewPoseLooping, MoveDelta, PreviewPoseCurrentTime, PreviewBasePose->SequenceLength); } #endif }