/** Takes sorted array Base and then adds any elements from sorted array Insert which is missing from it, preserving order. */ static void MergeInBoneIndexArrays(TArray<FBoneIndexType>& BaseArray, TArray<FBoneIndexType>& InsertArray) { // Then we merge them into the array of required bones. int32 BaseBonePos = 0; int32 InsertBonePos = 0; // Iterate over each of the bones we need. while( InsertBonePos < InsertArray.Num() ) { // Find index of physics bone FBoneIndexType InsertBoneIndex = InsertArray[InsertBonePos]; // If at end of BaseArray array - just append. if( BaseBonePos == BaseArray.Num() ) { BaseArray.Add(InsertBoneIndex); BaseBonePos++; InsertBonePos++; } // If in the middle of BaseArray, merge together. else { // Check that the BaseArray array is strictly increasing, otherwise merge code does not work. check( BaseBonePos == 0 || BaseArray[BaseBonePos-1] < BaseArray[BaseBonePos] ); // Get next required bone index. FBoneIndexType BaseBoneIndex = BaseArray[BaseBonePos]; // We have a bone in BaseArray not required by Insert. Thats ok - skip. if( BaseBoneIndex < InsertBoneIndex ) { BaseBonePos++; } // Bone required by Insert is in else if( BaseBoneIndex == InsertBoneIndex ) { BaseBonePos++; InsertBonePos++; } // Bone required by Insert is missing - insert it now. else // BaseBoneIndex > InsertBoneIndex { BaseArray.InsertUninitialized(BaseBonePos); BaseArray[BaseBonePos] = InsertBoneIndex; BaseBonePos++; InsertBonePos++; } } } }
/** * Utility for taking an array of bone indices and ensuring that all parents are present * (ie. all bones between those in the array and the root are present). * Note that this must ensure the invariant that parent occur before children in BoneIndices. */ void FAnimationRuntime::EnsureParentsPresent(TArray<FBoneIndexType> & BoneIndices, USkeletalMesh * SkelMesh ) { const int32 NumBones = SkelMesh->RefSkeleton.GetNum(); // Iterate through existing array. int32 i=0; while( i<BoneIndices.Num() ) { const int32 BoneIndex = BoneIndices[i]; // For the root bone, just move on. if( BoneIndex > 0 ) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) // Warn if we're getting bad data. // Bones are matched as int32, and a non found bone will be set to INDEX_NONE == -1 // This should never happen, so if it does, something is wrong! if( BoneIndex >= NumBones ) { UE_LOG(LogAnimation, Log, TEXT("FAnimationRuntime::EnsureParentsPresent, BoneIndex >= SkelMesh->RefSkeleton.GetNum().")); i++; continue; } #endif const int32 ParentIndex = SkelMesh->RefSkeleton.GetParentIndex(BoneIndex); // If we do not have this parent in the array, we add it in this location, and leave 'i' where it is. // This can happen if somebody removes bones in the physics asset, then it will try add back in, and in the process, // parent can be missing if( !BoneIndices.Contains(ParentIndex) ) { BoneIndices.InsertUninitialized(i); BoneIndices[i] = ParentIndex; } // If parent was in array, just move on. else { i++; } } else { i++; } } }
void Insert(int32 index) override { Array->InsertUninitialized(index); Super::Construct(index); }