Example #1
0
bool UBlendSpaceBase::ValidateSampleInput(FBlendSample & BlendSample, int32 OriginalIndex) const
{
	// make sure we get same kinds of samples(additive or nonadditive)
	if (SampleData.Num() > 0 && BlendSample.Animation)
	{
		if (IsValidAdditive() != (BlendSample.Animation->IsValidAdditive()))
		{
			UE_LOG(LogAnimation, Log, TEXT("Adding sample failed. Please add same kinds of sequence (additive/non-additive)."));
			return false;
		}
	}

	const USkeleton* MySkeleton = GetSkeleton();
	if (BlendSample.Animation &&
		(! MySkeleton ||
		! BlendSample.Animation->GetSkeleton()->IsCompatible(MySkeleton)))
	{
		UE_LOG(LogAnimation, Log, TEXT("Adding sample failed. Please add same kinds of sequence (additive/non-additive)."));
		return false;
	}

	SnapToBorder(BlendSample);
	// make sure blendsample is within the parameter range
	BlendSample.SampleValue = ClampBlendInput(BlendSample.SampleValue);

	if (IsTooCloseToExistingSamplePoint(BlendSample.SampleValue, OriginalIndex))
	{
		UE_LOG(LogAnimation, Log, TEXT("Adding sample failed. Too close to existing sample point."));
		return false;
	}

	return true;
}
bool UBlendSpaceBase::EditSample(const FBlendSample& BlendSample, FVector& NewValue)
{
	int32 NewIndex = SampleData.Find(BlendSample);
	if (NewIndex!=INDEX_NONE)
	{
		// edit is more work when we check if there is duplicate, so 
		// just delete old one, and add new one, 
		// when add it will verify if it isn't duplicate
		FBlendSample NewSample = BlendSample;
		NewSample.SampleValue = NewValue;

		if ( ValidateSampleInput(NewSample, NewIndex) == false )
		{
			return false;
		}

		SampleData[NewIndex] = NewSample;

#if WITH_EDITORONLY_DATA
		// fill upt PreviewBasePose if it does not set yet
		if ( IsValidAdditive() )
		{
			if ( PreviewBasePose == NULL && NewSample.Animation )
			{
				PreviewBasePose = NewSample.Animation->RefPoseSeq;
			}
		}
		// if not additive, clear pose
		else if ( PreviewBasePose )
		{
			PreviewBasePose = NULL;
		}
#endif // WITH_EDITORONLY_DATA

		// copy back the sample value, so it can display in the correct position
		NewValue = NewSample.SampleValue;
		MarkPackageDirty();
		return true;
	}

	return false;
}
Example #3
0
void UAnimMontage::PostLoad()
{
	Super::PostLoad();

	// copy deprecated variable to new one, temporary code to keep data copied. Am deleting it right after this
	for ( auto SlotIter = SlotAnimTracks.CreateIterator() ; SlotIter ; ++SlotIter)
	{
		FAnimTrack & Track = (*SlotIter).AnimTrack;
		for ( auto SegIter = Track.AnimSegments.CreateIterator() ; SegIter ; ++SegIter )
		{
			FAnimSegment & Segment = (*SegIter);
			if ( Segment.AnimStartOffset_DEPRECATED!=0.f )
			{
				Segment.AnimStartTime = Segment.AnimStartOffset_DEPRECATED;
				Segment.AnimStartOffset_DEPRECATED = 0.f;
			}
			if ( Segment.AnimEndOffset_DEPRECATED!=0.f )
			{
				Segment.AnimEndTime = Segment.AnimEndOffset_DEPRECATED;
				Segment.AnimEndOffset_DEPRECATED = 0.f;
			}
		}
			}

	for ( auto CompositeIter = CompositeSections.CreateIterator(); CompositeIter; ++CompositeIter )
	{
		FCompositeSection & Composite = (*CompositeIter);
		if (Composite.StarTime_DEPRECATED!=0.f)
		{
			Composite.StartTime = Composite.StarTime_DEPRECATED;
			Composite.StarTime_DEPRECATED = 0.f;
		}
	}

	SortAnimBranchingPointByTime();

	// find preview base pose if it can
#if WITH_EDITORONLY_DATA
	if ( IsValidAdditive() && PreviewBasePose == NULL )
	{
		for (int32 I=0; I<SlotAnimTracks.Num(); ++I)
		{
			if ( SlotAnimTracks[I].AnimTrack.AnimSegments.Num() > 0 )
			{
				UAnimSequence * Sequence = Cast<UAnimSequence>(SlotAnimTracks[I].AnimTrack.AnimSegments[0].AnimReference);
				if ( Sequence && Sequence->RefPoseSeq )
				{
					PreviewBasePose = Sequence->RefPoseSeq;
					MarkPackageDirty();
					break;
				}
			}
		}
	}

	// verify if skeleton matches, otherwise clear it, this can happen if anim sequence has been modified when this hasn't been loaded. 
	USkeleton* MySkeleton = GetSkeleton();
	for (int32 I=0; I<SlotAnimTracks.Num(); ++I)
	{
		if ( SlotAnimTracks[I].AnimTrack.AnimSegments.Num() > 0 )
		{
			UAnimSequence * Sequence = Cast<UAnimSequence>(SlotAnimTracks[I].AnimTrack.AnimSegments[0].AnimReference);
			if ( Sequence && Sequence->GetSkeleton() != MySkeleton )
			{
				SlotAnimTracks[I].AnimTrack.AnimSegments[0].AnimReference = 0;
				MarkPackageDirty();
				break;
			}
		}
	}
#endif // WITH_EDITORONLY_DATA
}
void UBlendSpaceBase::GetAnimationPose(TArray<FBlendSampleData>& BlendSampleDataCache, /*out*/ FCompactPose& OutPose, /*out*/ FBlendedCurve& OutCurve)
{
	SCOPE_CYCLE_COUNTER(STAT_BlendSpace_GetAnimPose);
	FScopeCycleCounterUObject BlendSpaceScope(this);

	if(BlendSampleDataCache.Num() == 0)
	{
		OutPose.ResetToRefPose();
		return;
	}

	const int32 NumPoses = BlendSampleDataCache.Num();

	TArray<FCompactPose, TInlineAllocator<8>> ChildrenPoses;
	ChildrenPoses.AddZeroed(NumPoses);

	TArray<FBlendedCurve, TInlineAllocator<8>> ChildrenCurves;
	ChildrenCurves.AddZeroed(NumPoses);

	TArray<float, TInlineAllocator<8>> ChildrenWeights;
	ChildrenWeights.AddZeroed(NumPoses);

	for(int32 ChildrenIdx=0; ChildrenIdx<ChildrenPoses.Num(); ++ChildrenIdx)
	{
		ChildrenPoses[ChildrenIdx].SetBoneContainer(&OutPose.GetBoneContainer());
		ChildrenCurves[ChildrenIdx].InitFrom(OutCurve);
	}

	// get all child atoms we interested in
	for(int32 I = 0; I < BlendSampleDataCache.Num(); ++I)
	{
		FCompactPose& Pose = ChildrenPoses[I];

		if(SampleData.IsValidIndex(BlendSampleDataCache[I].SampleDataIndex))
		{
			const FBlendSample& Sample = SampleData[BlendSampleDataCache[I].SampleDataIndex];
			ChildrenWeights[I] = BlendSampleDataCache[I].GetWeight();

			if(Sample.Animation)
			{
				const float Time = FMath::Clamp<float>(BlendSampleDataCache[I].Time, 0.f, Sample.Animation->SequenceLength);

				// first one always fills up the source one
				Sample.Animation->GetAnimationPose(Pose, ChildrenCurves[I], FAnimExtractContext(Time, true));
			}
			else
			{
				Pose.ResetToRefPose();
			}
		}
		else
		{
			Pose.ResetToRefPose();
		}
	}

	TArrayView<FCompactPose> ChildrenPosesView(ChildrenPoses);

	if (PerBoneBlend.Num() > 0)
	{
		if (IsValidAdditive())
		{
			if (bRotationBlendInMeshSpace)
			{
				FAnimationRuntime::BlendPosesTogetherPerBoneInMeshSpace(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve);
			}
			else
			{
				FAnimationRuntime::BlendPosesTogetherPerBone(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve);
			}
		}
		else
		{
			FAnimationRuntime::BlendPosesTogetherPerBone(ChildrenPosesView, ChildrenCurves, this, BlendSampleDataCache, OutPose, OutCurve);
		}
	}
	else
	{
		FAnimationRuntime::BlendPosesTogether(ChildrenPosesView, ChildrenCurves, ChildrenWeights, OutPose, OutCurve);
	}

	// Once all the accumulation and blending has been done, normalize rotations.
	OutPose.NormalizeRotations();
}