/** * Enacts the transaction. */ void FTransaction::Apply() { checkSlow(Inc==1||Inc==-1); // Figure out direction. const int32 Start = Inc==1 ? 0 : Records.Num()-1; const int32 End = Inc==1 ? Records.Num() : -1; // Init objects. TArray<UObject*> ChangedObjects; for( int32 i=Start; i!=End; i+=Inc ) { Records[i].bRestored = false; if(ChangedObjects.Find(Records[i].Object) == INDEX_NONE) { Records[i].Object->CheckDefaultSubobjects(); Records[i].Object->PreEditUndo(); ChangedObjects.Add(Records[i].Object); } } for( int32 i=Start; i!=End; i+=Inc ) { Records[i].Restore( this ); } NumModelsModified = 0; // Count the number of UModels that were changed. for(int32 ObjectIndex = 0;ObjectIndex < ChangedObjects.Num();ObjectIndex++) { UObject* ChangedObject = ChangedObjects[ObjectIndex]; UModel* Model = Cast<UModel>(ChangedObject); if( Model && Model->Nodes.Num() ) { FBSPOps::bspBuildBounds( Model ); ++NumModelsModified; } ChangedObject->PostEditUndo(); } // Rebuild BSP here instead of waiting for the next tick since // multiple transaction events can occur in a single tick if (ABrush::NeedsRebuild()) { GEditor->RebuildAlteredBSP(); } // Flip it. if( bFlip ) { Inc *= -1; } for(int32 ObjectIndex = 0;ObjectIndex < ChangedObjects.Num();ObjectIndex++) { UObject* ChangedObject = ChangedObjects[ObjectIndex]; ChangedObject->CheckDefaultSubobjects(); } }
/** * Enacts the transaction. */ void FTransaction::Apply() { checkSlow(Inc==1||Inc==-1); // Figure out direction. const int32 Start = Inc==1 ? 0 : Records.Num()-1; const int32 End = Inc==1 ? Records.Num() : -1; // Init objects. for( int32 i=Start; i!=End; i+=Inc ) { FObjectRecord& Record = Records[i]; Record.bRestored = false; UObject* Object = Record.Object.Get(); if (Object) { if (!ChangedObjects.Contains(Object)) { Object->CheckDefaultSubobjects(); Object->PreEditUndo(); } ChangedObjects.Add(Object, Record.ObjectAnnotation); } } if (bFlip) { for (int32 i = Start; i != End; i += Inc) { Records[i].Save(this); } for (int32 i = Start; i != End; i += Inc) { Records[i].Load(this); } } else { for (int32 i = Start; i != End; i += Inc) { Records[i].Restore(this); } } // An Actor's components must always get its PostEditUndo before the owning Actor so do a quick sort ChangedObjects.KeySort([](UObject& A, UObject& B) { UActorComponent* BAsComponent = Cast<UActorComponent>(&B); return (BAsComponent ? (BAsComponent->GetOwner() != &A) : true); }); TArray<ULevel*> LevelsToCommitModelSurface; NumModelsModified = 0; // Count the number of UModels that were changed. for (auto ChangedObjectIt : ChangedObjects) { UObject* ChangedObject = ChangedObjectIt.Key; UModel* Model = Cast<UModel>(ChangedObject); if (Model && Model->Nodes.Num()) { FBSPOps::bspBuildBounds(Model); ++NumModelsModified; } if (UModelComponent* ModelComponent = Cast<UModelComponent>(ChangedObject)) { ULevel* Level = ModelComponent->GetTypedOuter<ULevel>(); check(Level); LevelsToCommitModelSurface.AddUnique(Level); } TSharedPtr<ITransactionObjectAnnotation> ChangedObjectTransactionAnnotation = ChangedObjectIt.Value; if (ChangedObjectTransactionAnnotation.IsValid()) { ChangedObject->PostEditUndo(ChangedObjectTransactionAnnotation); } else { ChangedObject->PostEditUndo(); } } // Commit model surfaces for unique levels within the transaction for (ULevel* Level : LevelsToCommitModelSurface) { Level->CommitModelSurfaces(); } // Flip it. if (bFlip) { Inc *= -1; } for (auto ChangedObjectIt : ChangedObjects) { UObject* ChangedObject = ChangedObjectIt.Key; ChangedObject->CheckDefaultSubobjects(); } ChangedObjects.Empty(); }