void USkeleton::HandleSkeletonHierarchyChange() { MarkPackageDirty(); RegenerateGuid(); // Clear exiting MeshLinkUp tables. ClearCacheData(); // Fix up loaded animations (any animations that aren't loaded will be fixed on load) for(TObjectIterator<UAnimationAsset> It; It; ++It) { UAnimationAsset* CurrentAnimation = *It; if (CurrentAnimation->GetSkeleton() == this) { CurrentAnimation->ValidateSkeleton(); } } #if WITH_EDITORONLY_DATA RefreshAllRetargetSources(); #endif OnSkeletonHierarchyChanged.Broadcast(); }
bool UAnimationAsset::ReplaceSkeleton(USkeleton* NewSkeleton, bool bConvertSpaces/*=false*/) { // if it's not same if (NewSkeleton != Skeleton) { // get all sequences that need to change TArray<UAnimSequence*> AnimSeqsToReplace; if (UAnimSequence* AnimSequence = Cast<UAnimSequence>(this)) { AnimSeqsToReplace.AddUnique(AnimSequence); } if (GetAllAnimationSequencesReferred(AnimSeqsToReplace)) { for (auto Iter = AnimSeqsToReplace.CreateIterator(); Iter; ++Iter) { UAnimSequence* AnimSeq = *Iter; if (AnimSeq && AnimSeq->Skeleton != NewSkeleton) { AnimSeq->RemapTracksToNewSkeleton(NewSkeleton, bConvertSpaces); } } } SetSkeleton(NewSkeleton); PostEditChange(); MarkPackageDirty(); return true; } return false; }
bool UBlendSpaceBase::UpdateParameter(int32 Index, const FBlendParameter& Parameter) { check ( Index >= 0 && Index <=2 ); // too small if (Parameter.GetRange() < SMALL_NUMBER) { return false; } // mini grid number is 3 if (Parameter.GridNum < 3) { return false; } // not valid, return if (Parameter.DisplayName.IsEmpty()) { return false; } BlendParameters[Index] = Parameter; // now update all SamplePoint be within the range for (int32 I=0; I<SampleData.Num(); ++I) { SampleData[I].SampleValue = ClampBlendInput(SampleData[I].SampleValue); } ValidateSampleData(); MarkPackageDirty(); return true; }
void UBlendSpaceBase::ClearAllSamples() { SampleData.Empty(); GridSamples.Empty(); MarkPackageDirty(); AnimLength = 0.f; }
void USkeletalMeshComponent::LoadedFromAnotherClass(const FName& OldClassName) { Super::LoadedFromAnotherClass(OldClassName); if(GetLinkerUE4Version() < VER_UE4_REMOVE_SINGLENODEINSTANCE) { static FName SingleAnimSkeletalComponent_NAME(TEXT("SingleAnimSkeletalComponent")); if(OldClassName == SingleAnimSkeletalComponent_NAME) { SetAnimationMode(EAnimationMode::Type::AnimationSingleNode); // support old compatibility code that changed variable name if (SequenceToPlay_DEPRECATED!=NULL && AnimToPlay_DEPRECATED== NULL) { AnimToPlay_DEPRECATED = SequenceToPlay_DEPRECATED; SequenceToPlay_DEPRECATED = NULL; } AnimationData.AnimToPlay = AnimToPlay_DEPRECATED; AnimationData.bSavedLooping = bDefaultLooping_DEPRECATED; AnimationData.bSavedPlaying = bDefaultPlaying_DEPRECATED; AnimationData.SavedPosition = DefaultPosition_DEPRECATED; AnimationData.SavedPlayRate = DefaultPlayRate_DEPRECATED; MarkPackageDirty(); } } }
void UMorphTarget::PostProcess( USkeletalMesh * NewMesh, const FMorphMeshRawSource& BaseSource, const FMorphMeshRawSource& TargetSource, int32 LODIndex, bool bCompareNormal ) { // @todo anim: update BaseSkelMesh with my information NewMesh->RegisterMorphTarget(this); CreateMorphMeshStreams( BaseSource, TargetSource, LODIndex, bCompareNormal ); MarkPackageDirty(); }
int32 USkeleton::ValidatePreviewAttachedObjects() { int32 NumBrokenAssets = PreviewAttachedAssetContainer.ValidatePreviewAttachedObjects(); if(NumBrokenAssets > 0) { MarkPackageDirty(); } return NumBrokenAssets; }
void UBodySetup::Serialize(FArchive& Ar) { Super::Serialize(Ar); // Load GUID (or create one for older versions) Ar << BodySetupGuid; // If we loaded a ZERO Guid, fix that if(Ar.IsLoading() && !BodySetupGuid.IsValid()) { MarkPackageDirty(); UE_LOG(LogPhysics, Log, TEXT("FIX GUID FOR: %s"), *GetPathName()); BodySetupGuid = FGuid::NewGuid(); } bool bCooked = Ar.IsCooking(); Ar << bCooked; if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading()) { UE_LOG(LogPhysics, Fatal, TEXT("This platform requires cooked packages, and physX data was not cooked into %s."), *GetFullName()); } if (bCooked) { if (Ar.IsCooking()) { // Make sure to reset bHasCookedCollision data to true before calling GetCookedData for cooking bHasCookedCollisionData = true; FName Format = Ar.CookingTarget()->GetPhysicsFormat(this); bHasCookedCollisionData = GetCookedData(Format) != NULL; // Get the data from the DDC or build it TArray<FName> ActualFormatsToSave; ActualFormatsToSave.Add(Format); Ar << bHasCookedCollisionData; CookedFormatData.Serialize(Ar, this, &ActualFormatsToSave); } else { if (Ar.UE4Ver() >= VER_UE4_STORE_HASCOOKEDDATA_FOR_BODYSETUP) { Ar << bHasCookedCollisionData; } CookedFormatData.Serialize(Ar, this); } } if ( Ar.IsLoading() ) { AggGeom.Serialize( Ar ); } }
bool UBlendSpaceBase::DeleteSample(const FBlendSample& BlendSample) { int32 NewIndex = SampleData.Find(BlendSample); if (NewIndex!=INDEX_NONE) { SampleData.RemoveAt(NewIndex); GridSamples.Empty(); MarkPackageDirty(); ValidateSampleData(); return true; } return false; }
void UBlendSpaceBase::ValidateSampleData() { bool bSampleDataChanged=false; AnimLength = 0.f; for (int32 I=0; I<SampleData.Num(); ++I) { if ( SampleData[I].Animation == 0 ) { SampleData.RemoveAt(I); --I; bSampleDataChanged = true; continue; } // set rotation blend in mesh space bRotationBlendInMeshSpace = IsValidAdditiveInternal(AAT_RotationOffsetMeshSpace); // we need data to be snapped on the border // otherwise, you have this grid area that doesn't have valid // sample points. Usually users will put it there // if the value is around border, snap to border SnapToBorder(SampleData[I]); // see if same data exists, by same, same values for (int32 J=I+1; J<SampleData.Num(); ++J) { if ( IsSameSamplePoint(SampleData[I].SampleValue, SampleData[J].SampleValue) ) { SampleData.RemoveAt(J); --J; bSampleDataChanged = true; } } if (SampleData[I].Animation->SequenceLength > AnimLength) { // @todo : should apply scale? If so, we'll need to apply also when blend AnimLength = SampleData[I].Animation->SequenceLength; } } if (bSampleDataChanged) { GridSamples.Empty(); MarkPackageDirty(); } }
void UInheritableComponentHandler::ValidateTemplates() { for (int32 Index = 0; Index < Records.Num();) { bool bIsValidAndNecessary = false; { FComponentOverrideRecord& Record = Records[Index]; FComponentKey& ComponentKey = Record.ComponentKey; FName VarName = ComponentKey.GetSCSVariableName(); if (ComponentKey.RefreshVariableName()) { FName NewName = ComponentKey.GetSCSVariableName(); UE_LOG(LogBlueprint, Log, TEXT("ValidateTemplates '%s': variable old name '%s' new name '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *NewName.ToString()); VarName = NewName; MarkPackageDirty(); } if (IsRecordValid(Record)) { if (IsRecordNecessary(Record)) { bIsValidAndNecessary = true; } else { UE_LOG(LogBlueprint, Log, TEXT("ValidateTemplates '%s': overriden template is unnecessary - component '%s' from '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *GetPathNameSafe(ComponentKey.GetComponentOwner())); } } else { UE_LOG(LogBlueprint, Warning, TEXT("ValidateTemplates '%s': overriden template is invalid - component '%s' from '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *GetPathNameSafe(ComponentKey.GetComponentOwner())); } } if (bIsValidAndNecessary) { ++Index; } else { Records.RemoveAtSwap(Index); } } }
bool UBlendSpaceBase::AddSample(const FBlendSample& BlendSample) { FBlendSample NewBlendSample = BlendSample; if ( ValidateSampleInput(NewBlendSample) == false ) { return false; } SampleData.Add(NewBlendSample); GridSamples.Empty(); MarkPackageDirty(); return true; }
void USkeleton::UpdateReferencePoseFromMesh(const USkeletalMesh* InSkelMesh) { check (InSkelMesh); for (int32 BoneIndex=0; BoneIndex<ReferenceSkeleton.GetNum(); BoneIndex++) { // find index from ref pose array const int32 MeshBoneIndex = InSkelMesh->RefSkeleton.FindBoneIndex(ReferenceSkeleton.GetBoneName(BoneIndex)); if( MeshBoneIndex != INDEX_NONE ) { ReferenceSkeleton.UpdateRefPoseTransform(BoneIndex, InSkelMesh->RefSkeleton.GetRefBonePose()[MeshBoneIndex]); } } MarkPackageDirty(); }
void USkeleton::HandleSkeletonHierarchyChange() { MarkPackageDirty(); RegenerateGuid(); // Fix up loaded animations (any animations that aren't loaded will be fixed on load) for(TObjectIterator<UAnimationAsset> It; It; ++It) { UAnimationAsset* CurrentAnimation = *It; CurrentAnimation->ValidateSkeleton(); } RefreshAllRetargetSources(); OnSkeletonHierarchyChanged.Broadcast(); }
void UCameraAnim::PostLoad() { if (GIsEditor) { // update existing CameraAnims' bboxes on load, so editor knows they // they need to be resaved if (!BoundingBox.IsValid) { CalcLocalAABB(); if (BoundingBox.IsValid) { MarkPackageDirty(); } } } Super::PostLoad(); }
void AGroupActor::PostRemove() { // If all children have been removed (or only one subgroup remains), this group is no longer active. if( GroupActors.Num() == 0 && SubGroups.Num() <= 1 ) { // Remove any potentially remaining subgroups SubGroups.Empty(); // Destroy the actor and remove it from active groups AGroupActor* ParentGroup = AGroupActor::GetParentForActor(this); if(ParentGroup) { ParentGroup->Modify(); ParentGroup->Remove(*this); } UWorld* MyWorld = GetWorld(); if( MyWorld ) { // Group is no longer active MyWorld->ActiveGroupActors.Remove(this); MyWorld->ModifyLevel(GetLevel()); // Mark the group actor for removal MarkPackageDirty(); // If not currently garbage collecting (changing maps, saving, etc), remove the group immediately if(!GIsGarbageCollecting) { // Refresh all editor browsers after removal FScopedRefreshAllBrowsers LevelRefreshAllBrowsers; // Destroy group and clear references. GEditor->Layers->DisassociateActorFromLayers( this ); MyWorld->EditorDestroyActor( this, false ); LevelRefreshAllBrowsers.Request(); } } } }
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; }
void ULevelSequence::ConvertPersistentBindingsToDefault(UObject* FixupContext) { if (PossessedObjects_DEPRECATED.Num() == 0) { return; } MarkPackageDirty(); for (auto& Pair : PossessedObjects_DEPRECATED) { UObject* Object = Pair.Value.GetObject(); if (Object) { FGuid ObjectId; FGuid::Parse(Pair.Key, ObjectId); ObjectReferences.CreateBinding(ObjectId, Object, FixupContext); } } PossessedObjects_DEPRECATED.Empty(); }
bool UAnimSet::RemoveAnimSequenceFromAnimSet(UAnimSequence* AnimSeq) { #if WITH_EDITORONLY_DATA int32 SequenceIndex = Sequences.Find(AnimSeq); if( SequenceIndex != INDEX_NONE ) { // Handle reference clean up properly AnimSeq->RecycleAnimSequence(); // Remove from array Sequences.RemoveAt(SequenceIndex, 1); if( GIsEditor ) { MarkPackageDirty(); } return true; } #endif // WITH_EDITORONLY_DATA return false; }
bool UBlendSpaceBase::EditSampleAnimation(const FBlendSample& BlendSample, class UAnimSequence* AnimSequence) { int32 NewIndex = SampleData.Find(BlendSample); if (NewIndex!=INDEX_NONE) { FBlendSample NewSample = BlendSample; NewSample.Animation = AnimSequence; if ( ValidateSampleInput(NewSample, NewIndex) == false ) { return false; } SampleData[NewIndex] = NewSample; GridSamples.Empty(); MarkPackageDirty(); ValidateSampleData(); return true; } return false; }
bool UStaticMeshComponent::SetStaticLightingMapping(bool bTextureMapping, int32 ResolutionToUse) { bool bSuccessful = false; if (StaticMesh) { if (bTextureMapping == true) { // Set it to texture mapping! if (ResolutionToUse == 0) { if (bOverrideLightMapRes == true) { // If overriding the static mesh setting, check to set if set to 0 // which will force the component to use vertex mapping if (OverriddenLightMapRes == 0) { // See if the static mesh has a valid setting if (StaticMesh->LightMapResolution != 0) { // Simply uncheck the override... bOverrideLightMapRes = false; bSuccessful = true; } else { // Set it to the default value from the ini int32 TempInt = 0; verify(GConfig->GetInt(TEXT("DevOptions.StaticLighting"), TEXT("DefaultStaticMeshLightingRes"), TempInt, GLightmassIni)); OverriddenLightMapRes = TempInt; bSuccessful = true; } } else { // We should be texture mapped already... } } else { // See if the static mesh has a valid setting if (StaticMesh->LightMapResolution == 0) { // See if the static mesh has a valid setting if (OverriddenLightMapRes != 0) { // Simply check the override... bOverrideLightMapRes = true; bSuccessful = true; } else { // Set it to the default value from the ini int32 TempInt = 0; verify(GConfig->GetInt(TEXT("DevOptions.StaticLighting"), TEXT("DefaultStaticMeshLightingRes"), TempInt, GLightmassIni)); OverriddenLightMapRes = TempInt; bOverrideLightMapRes = true; bSuccessful = true; } } else { // We should be texture mapped already... } } } else { // Use the override - even if it was already set to override at a different value OverriddenLightMapRes = ResolutionToUse; bOverrideLightMapRes = true; bSuccessful = true; } } else { // Set it to vertex mapping... if (bOverrideLightMapRes == true) { if (OverriddenLightMapRes != 0) { // See if the static mesh has a valid setting if (StaticMesh->LightMapResolution == 0) { // Simply uncheck the override... bOverrideLightMapRes = false; bSuccessful = true; } else { // Set it to 0 to force vertex mapping OverriddenLightMapRes = 0; bSuccessful = true; } } else { // We should be vertex mapped already... } } else { // See if the static mesh has a valid setting if (StaticMesh->LightMapResolution != 0) { // Set it to the default value from the ini OverriddenLightMapRes = 0; bOverrideLightMapRes = true; bSuccessful = true; } else { // We should be vertex mapped already... } } } } if (bSuccessful == true) { MarkPackageDirty(); } return bSuccessful; }
bool USkeleton::MergeBonesToBoneTree(USkeletalMesh * InSkeletalMesh, const TArray<int32> & RequiredRefBones) { // see if it needs all animation data to remap - only happens when bone structure CHANGED - added bool bSuccess = false; // clear cache data since it won't work anymore once this is done ClearCacheData(); // if it's first time if( BoneTree.Num() == 0 ) { bSuccess = CreateReferenceSkeletonFromMesh(InSkeletalMesh, RequiredRefBones); } else { // can we play? - hierarchy matches if( IsCompatibleMesh(InSkeletalMesh) ) { // Exclude bones who do not have a parent. TArray<int32> FilteredRequiredBones; FAnimationRuntime::ExcludeBonesWithNoParents(RequiredRefBones, InSkeletalMesh->RefSkeleton, FilteredRequiredBones); for (int32 Index=0; Index<FilteredRequiredBones.Num(); Index++) { const int32& MeshBoneIndex = FilteredRequiredBones[Index]; const int32& SkeletonBoneIndex = ReferenceSkeleton.FindBoneIndex(InSkeletalMesh->RefSkeleton.GetBoneName(MeshBoneIndex)); // Bone doesn't already exist. Add it. if( SkeletonBoneIndex == INDEX_NONE ) { FMeshBoneInfo NewMeshBoneInfo = InSkeletalMesh->RefSkeleton.GetRefBoneInfo()[MeshBoneIndex]; // Fix up ParentIndex for our new Skeleton. if( ReferenceSkeleton.GetNum() == 0 ) { NewMeshBoneInfo.ParentIndex = INDEX_NONE; // root } else { NewMeshBoneInfo.ParentIndex = ReferenceSkeleton.FindBoneIndex(InSkeletalMesh->RefSkeleton.GetBoneName(InSkeletalMesh->RefSkeleton.GetParentIndex(MeshBoneIndex))); } ReferenceSkeleton.Add(NewMeshBoneInfo, InSkeletalMesh->RefSkeleton.GetRefBonePose()[MeshBoneIndex]); BoneTree.AddZeroed(1); MarkPackageDirty(); } } bSuccess = true; } } // if succeed if (bSuccess) { InSkeletalMesh->Skeleton = this; InSkeletalMesh->MarkPackageDirty(); // make sure to refresh all base poses // so that they have same number of bones of ref pose #if WITH_EDITORONLY_DATA RefreshAllRetargetSources(); #endif } return bSuccess; }
void UBlendSpaceBase::ValidateSampleData() { bool bSampleDataChanged=false; AnimLength = 0.f; bool bAllMarkerPatternsMatch = true; FSyncPattern BlendSpacePattern; int32 SampleWithMarkers = INDEX_NONE; for (int32 I=0; I<SampleData.Num(); ++I) { FBlendSample& Sample = SampleData[I]; if (Sample.Animation == nullptr) { SampleData.RemoveAt(I); --I; bSampleDataChanged = true; continue; } // set rotation blend in mesh space bRotationBlendInMeshSpace = IsValidAdditiveInternal(AAT_RotationOffsetMeshSpace); // we need data to be snapped on the border // otherwise, you have this grid area that doesn't have valid // sample points. Usually users will put it there // if the value is around border, snap to border SnapToBorder(Sample); // see if same data exists, by same, same values for (int32 J=I+1; J<SampleData.Num(); ++J) { if (IsSameSamplePoint(Sample.SampleValue, SampleData[J].SampleValue)) { SampleData.RemoveAt(J); --J; bSampleDataChanged = true; } } if (Sample.Animation->SequenceLength > AnimLength) { // @todo : should apply scale? If so, we'll need to apply also when blend AnimLength = Sample.Animation->SequenceLength; } if (Sample.Animation->AuthoredSyncMarkers.Num() > 0) { if (SampleWithMarkers == INDEX_NONE) { SampleWithMarkers = I; } if (BlendSpacePattern.MarkerNames.Num() == 0) { PopulateMarkerNameArray(BlendSpacePattern.MarkerNames, Sample.Animation->AuthoredSyncMarkers); } else { TArray<FName> ThisPattern; PopulateMarkerNameArray(ThisPattern, Sample.Animation->AuthoredSyncMarkers); if (!BlendSpacePattern.DoesPatternMatch(ThisPattern)) { bAllMarkerPatternsMatch = false; } } } } SampleIndexWithMarkers = bAllMarkerPatternsMatch ? SampleWithMarkers : INDEX_NONE; if (bSampleDataChanged) { GridSamples.Empty(); MarkPackageDirty(); } }
void USoundNode::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); MarkPackageDirty(); }
void UWorld::LoadSecondaryLevels(bool bForce, TSet<FString>* CookedPackages) { check( GIsEditor ); // streamingServer // Only load secondary levels in the Editor, and not for commandlets. if( (!IsRunningCommandlet() || bForce) // Don't do any work for world info actors that are part of secondary levels being streamed in! && !IsAsyncLoading()) { for( int32 LevelIndex=0; LevelIndex<StreamingLevels.Num(); LevelIndex++ ) { ULevelStreaming* const StreamingLevel = StreamingLevels[LevelIndex]; if( StreamingLevel ) { bool bAlreadyCooked = false; // If we are cooking don't cook sub levels multiple times if they've already been cooked FString PackageFilename; const FString StreamingLevelWorldAssetPackageName = StreamingLevel->GetWorldAssetPackageName(); if (CookedPackages) { if (FPackageName::DoesPackageExist(StreamingLevelWorldAssetPackageName, NULL, &PackageFilename)) { PackageFilename = FPaths::ConvertRelativePathToFull(PackageFilename); bAlreadyCooked |= CookedPackages->Contains( PackageFilename ); } } bool bAlreadyLoaded = false; UPackage* LevelPackage = FindObject<UPackage>(NULL, *StreamingLevelWorldAssetPackageName,true); // don't need to do any extra work if the level is already loaded if ( LevelPackage && LevelPackage->IsFullyLoaded() ) { bAlreadyLoaded = true; } if ( !bAlreadyCooked && !bAlreadyLoaded ) { bool bLoadedLevelPackage = false; const FName StreamingLevelWorldAssetPackageFName = StreamingLevel->GetWorldAssetPackageFName(); // Load the package and find the world object. if( FPackageName::IsShortPackageName(StreamingLevelWorldAssetPackageFName) == false ) { ULevel::StreamedLevelsOwningWorld.Add(StreamingLevelWorldAssetPackageFName, this); LevelPackage = LoadPackage( NULL, *StreamingLevelWorldAssetPackageName, LOAD_None ); ULevel::StreamedLevelsOwningWorld.Remove(StreamingLevelWorldAssetPackageFName); if( LevelPackage ) { bLoadedLevelPackage = true; // Find the world object in the loaded package. UWorld* LoadedWorld = UWorld::FindWorldInPackage(LevelPackage); // If the world was not found, it could be a redirector to a world. If so, follow it to the destination world. if (!LoadedWorld) { LoadedWorld = UWorld::FollowWorldRedirectorInPackage(LevelPackage); } check(LoadedWorld); if ( !LevelPackage->IsFullyLoaded() ) { // LoadedWorld won't be serialized as there's a BeginLoad on the stack so we manually serialize it here. check( LoadedWorld->GetLinker() ); LoadedWorld->GetLinker()->Preload( LoadedWorld ); } // Keep reference to prevent garbage collection. check( LoadedWorld->PersistentLevel ); ULevel* NewLoadedLevel = LoadedWorld->PersistentLevel; NewLoadedLevel->OwningWorld = this; StreamingLevel->SetLoadedLevel(NewLoadedLevel); } } else { UE_LOG(LogSpawn, Warning, TEXT("Streaming level uses short package name (%s). Level will not be loaded."), *StreamingLevelWorldAssetPackageName); } // Remove this level object if the file couldn't be found. if ( !bLoadedLevelPackage ) { StreamingLevels.RemoveAt( LevelIndex-- ); MarkPackageDirty(); } } } } } }
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 }