void UExporter::ExportObjectInner(const FExportObjectInnerContext* Context, UObject* Object, FOutputDevice& Ar, uint32 PortFlags) { // indent all the text in here TextIndent += 3; FExportObjectInnerContext::InnerList TempInners; const FExportObjectInnerContext::InnerList* ContextInners = NULL; if (Context) { ContextInners = Context->ObjectToInnerMap.Find(Object); } else { // NOTE: We ignore inner objects that have been tagged for death GetObjectsWithOuter(Object, TempInners, false, RF_PendingKill); } FExportObjectInnerContext::InnerList const& UnsortedObjectInners = ContextInners ? *ContextInners : TempInners; FExportObjectInnerContext::InnerList SortedObjectInners; if (PortFlags & PPF_DebugDump) { SortedObjectInners = UnsortedObjectInners; // optionally sort inners, which can be useful when comparing/diffing debug dumps SortedObjectInners.Sort([](const UObject& A, const UObject& B) -> bool { return A.GetName() < B.GetName(); }); } FExportObjectInnerContext::InnerList const& ObjectInners = (PortFlags & PPF_DebugDump) ? SortedObjectInners : UnsortedObjectInners; if (!(PortFlags & PPF_SeparateDefine)) { for (UObject* Obj : ObjectInners) { if (!Obj->HasAnyFlags(RF_TextExportTransient) && Obj->GetClass() != UModel::StaticClass()) { // export the object UExporter::ExportToOutputDevice( Context, Obj, NULL, Ar, (PortFlags & PPF_Copy) ? TEXT("Copy") : TEXT("T3D"), TextIndent, PortFlags | PPF_SeparateDeclare, false, ExportRootScope ); } } } if (!(PortFlags & PPF_SeparateDeclare)) { for (UObject* Obj : ObjectInners) { if (!Obj->HasAnyFlags(RF_TextExportTransient) && Obj->GetClass() != UModel::StaticClass()) { // export the object UExporter::ExportToOutputDevice( Context, Obj, NULL, Ar, (PortFlags & PPF_Copy) ? TEXT("Copy") : TEXT("T3D"), TextIndent, PortFlags | PPF_SeparateDefine, false, ExportRootScope ); // don't reexport below in ExportProperties Obj->Mark(OBJECTMARK_TagImp); } } // export the object's properties // Note: we use archetype as the object to diff properties against before they exported. When object is created, they should create from archetype // and using this system, it should recover all properties it needs to copy uint8 *CompareObject; if (Object->HasAnyFlags(RF_ClassDefaultObject)) { CompareObject = (uint8*)Object; } else { CompareObject = (uint8*)Object->GetArchetype(); } ExportProperties( Context, Ar, Object->GetClass(), (uint8*)Object, TextIndent, Object->GetClass(), CompareObject, Object, PortFlags, ExportRootScope ); if (AActor* Actor = Cast<AActor>(Object)) { // Export anything extra for the components. Used for instanced foliage. // This is done after the actor properties so these are set when regenerating the extra data objects. TArray<UActorComponent*> Components; Actor->GetComponents<UActorComponent, FDefaultAllocator>(Components); ExportComponentExtra(Context, Components, Ar, PortFlags); } } // remove indent TextIndent -= 3; }
void UExporter::ExportObjectInner(const FExportObjectInnerContext* Context, UObject* Object, FOutputDevice& Ar, uint32 PortFlags, bool bSkipComponents) { // indent all the text in here TextIndent += 3; FExportObjectInnerContext::InnerList ObjectInners; if ( Context ) { const FExportObjectInnerContext::InnerList* Inners = Context->ObjectToInnerMap.Find( Object ); if ( Inners ) { ObjectInners = *Inners; } } else { for (TObjectIterator<UObject> It; It; ++It) { if ( It->GetOuter() == Object ) { ObjectInners.Add( *It ); } } } TArray<UObject*> Components; if (!bSkipComponents) { // first export the components Object->CollectDefaultSubobjects(Components, false); } if (!(PortFlags & PPF_SeparateDefine)) { for ( int32 ObjIndex = 0 ; ObjIndex < ObjectInners.Num() ; ++ObjIndex ) { // NOTE: We ignore inner objects that have been tagged for death UObject* Obj = ObjectInners[ObjIndex]; if ( !Obj->IsPendingKill() && !Obj->IsDefaultSubobject() && !Obj->HasAnyFlags(RF_TextExportTransient) && FCString::Stricmp(*Obj->GetClass()->GetName(), TEXT("Model")) != 0) { // export the object UExporter::ExportToOutputDevice( Context, Obj, NULL, Ar, (PortFlags & PPF_Copy) ? TEXT("Copy") : TEXT("T3D"), TextIndent, PortFlags | PPF_SeparateDeclare, false, ExportRootScope ); } } if (!bSkipComponents) { ExportComponentDefinitions(Context, Components, Ar, PortFlags | PPF_SeparateDeclare); } } if (!(PortFlags & PPF_SeparateDeclare)) { for ( int32 ObjIndex = 0 ; ObjIndex < ObjectInners.Num() ; ++ObjIndex ) { // NOTE: We ignore inner objects that have been tagged for death UObject* Obj = ObjectInners[ObjIndex]; if ( !Obj->IsPendingKill() && !Obj->IsDefaultSubobject() && !Obj->HasAnyFlags(RF_TextExportTransient) && FCString::Stricmp(*Obj->GetClass()->GetName(), TEXT("Model")) != 0) { // export the object UExporter::ExportToOutputDevice( Context, Obj, NULL, Ar, (PortFlags & PPF_Copy) ? TEXT("Copy") : TEXT("T3D"), TextIndent, PortFlags | PPF_SeparateDefine, false, ExportRootScope ); // don't reexport below in ExportProperties Obj->Mark(OBJECTMARK_TagImp); } } if (!bSkipComponents) { ExportComponentDefinitions(Context, Components, Ar, PortFlags | PPF_SeparateDefine); } // export the object's properties // Note: we use archetype as the object to diff properties against before they exported. When object is created, they should create from archetype // and using this system, it should recover all properties it needs to copy uint8 *CompareObject; if (Object->HasAnyFlags(RF_ClassDefaultObject)) { CompareObject = (uint8*)Object; } else { CompareObject = (uint8*)Object->GetArchetype(); } ExportProperties( Context, Ar, Object->GetClass(), (uint8*)Object, TextIndent, Object->GetClass(), CompareObject, Object, PortFlags, ExportRootScope ); if (!bSkipComponents) { // Export anything extra for the components. Used for instanced foliage. // This is done after the actor properties so these are set when regenerating the extra data objects. ExportComponentExtra( Context, Components, Ar, PortFlags ); } } // remove indent TextIndent -= 3; }