/** * 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. TMap<UObject*, TSharedPtr<ITransactionObjectAnnotation>> ChangedObjects; for( int32 i=Start; i!=End; i+=Inc ) { FObjectRecord& Record = Records[i]; Record.bRestored = false; UObject* Object = Record.Object.Get(); if (!ChangedObjects.Contains(Object)) { Object->CheckDefaultSubobjects(); Object->PreEditUndo(); } ChangedObjects.Add(Object, Record.ObjectAnnotation); } 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); }); 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; } TSharedPtr<ITransactionObjectAnnotation> ChangedObjectTransactionAnnotation = ChangedObjectIt.Value; if (ChangedObjectTransactionAnnotation.IsValid()) { ChangedObject->PostEditUndo(ChangedObjectTransactionAnnotation); } else { ChangedObject->PostEditUndo(); } } // Flip it. if (bFlip) { Inc *= -1; } for (auto ChangedObjectIt : ChangedObjects) { UObject* ChangedObject = ChangedObjectIt.Key; ChangedObject->CheckDefaultSubobjects(); } }