/** * Debug spew for components * @param Object object to dump component spew for */ void DumpComponents(UObject *Object) { for ( FObjectIterator It; It; ++It ) { It->UnMark(EObjectMark(OBJECTMARK_TagImp | OBJECTMARK_TagExp)); } if (FPlatformMisc::IsDebuggerPresent() ) { // if we have a debugger attached, the watch window won't be able to display the full output if we attempt to log it as a single string // so pass in GLog instead so that each line is sent separately; this causes the output to have an extra line break between each log statement, // but at least we'll be able to see the full output in the debugger's watch window UE_LOG(LogExporter, Log, TEXT("Components for '%s':"), *Object->GetFullName()); ExportProperties( NULL, *GLog, Object->GetClass(), (uint8*)Object, 0, NULL, NULL, Object, PPF_SubobjectsOnly ); UE_LOG(LogExporter, Log, TEXT("<--- DONE!")); } else { FStringOutputDevice Output; Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName()); ExportProperties( NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly ); Output.Logf(TEXT("<--- DONE!\r\n")); UE_LOG(LogExporter, Log, TEXT("%s"), *Output); } }
/** * Removes marks from and object * * @param Object Object to remove marks from * @param Marks Logical OR of OBJECTMARK_'s to remove */ void UnMarkObject(const class UObjectBase* Object, EObjectMark Marks) { FObjectMark Annotation = MarkAnnotation.GetAnnotation(Object); if(Annotation.Marks & Marks) { MarkAnnotation.AddAnnotation(Object,FObjectMark(EObjectMark(Annotation.Marks & ~Marks))); } }
FString DumpObjectToString(UObject* Object) { UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); FStringOutputDevice Archive; const FExportObjectInnerContext Context; UExporter::ExportToOutputDevice(&Context, Object, NULL, Archive, TEXT("copy"), 0, PPF_Copy | PPF_DebugDump, false); return Archive; }
FString DumpComponentsToString(UObject *Object) { UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); FStringOutputDevice Output; Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName()); ExportProperties(NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly); Output.Logf(TEXT("<--- DONE!\r\n")); return Output; }
void DumpObject(const TCHAR *Label, UObject* Object) { UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); FStringOutputDevice Archive; const FExportObjectInnerContext Context; UExporter::ExportToOutputDevice(&Context, Object, NULL, Archive, TEXT("copy"), 0, PPF_Copy | PPF_DebugDump, false); FString ExportedText; ExportedText = Archive; UE_LOG(LogExporter, Display, TEXT("%s"), Label); UE_LOG(LogExporter, Display, TEXT("%s"), *ExportedText); }
void UnMarkAllObjects(EObjectMark Marks) { if (Marks == OBJECTMARK_ALLMARKS) { MarkAnnotation.RemoveAllAnnotations(); } else { const TMap<const UObjectBase *, FObjectMark>& Map = MarkAnnotation.GetAnnotationMap(); for (TMap<const UObjectBase *, FObjectMark>::TConstIterator It(Map); It; ++It) { if(It.Value().Marks & Marks) { MarkAnnotation.AddAnnotation((UObject*)It.Key(),FObjectMark(EObjectMark(It.Value().Marks & ~Marks))); } } } }
// Exports a set of nodes to text void FEdGraphUtilities::ExportNodesToText(TSet<UObject*> NodesToExport, /*out*/ FString& ExportedText) { // Clear the mark state for saving. UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); FStringOutputDevice Archive; const FExportObjectInnerContext Context; // Export each of the selected nodes UObject* LastOuter = NULL; for (TSet<UObject*>::TConstIterator NodeIt(NodesToExport); NodeIt; ++NodeIt) { UObject* Node = *NodeIt; // The nodes should all be from the same scope UObject* ThisOuter = Node->GetOuter(); check((LastOuter == ThisOuter) || (LastOuter == NULL)); LastOuter = ThisOuter; UExporter::ExportToOutputDevice(&Context, Node, NULL, Archive, TEXT("copy"), 0, PPF_ExportsNotFullyQualified|PPF_Copy|PPF_Delimited, false, ThisOuter); } ExportedText = Archive; }
void FComponentEditorUtils::CopyComponents(const TArray<UActorComponent*>& ComponentsToCopy) { FStringOutputDevice Archive; const FExportObjectInnerContext Context; // Clear the mark state for saving. UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); // Duplicate the selected component templates into temporary objects that we can modify TMap<FName, FName> ParentMap; TMap<FName, UActorComponent*> ObjectMap; for (UActorComponent* Component : ComponentsToCopy) { // Duplicate the component into a temporary object UObject* DuplicatedComponent = StaticDuplicateObject(Component, GetTransientPackage(), Component->GetFName(), RF_AllFlags & ~RF_ArchetypeObject); if (DuplicatedComponent) { // If the duplicated component is a scene component, wipe its attach parent (to prevent log warnings for referencing a private object in an external package) if (auto DuplicatedCompAsSceneComp = Cast<USceneComponent>(DuplicatedComponent)) { DuplicatedCompAsSceneComp->AttachParent = nullptr; } // Find the closest parent component of the current component within the list of components to copy USceneComponent* ClosestSelectedParent = FindClosestParentInList(Component, ComponentsToCopy); if (ClosestSelectedParent) { // If the parent is included in the list, record it into the node->parent map ParentMap.Add(Component->GetFName(), ClosestSelectedParent->GetFName()); } // Record the temporary object into the name->object map ObjectMap.Add(Component->GetFName(), CastChecked<UActorComponent>(DuplicatedComponent)); } } // Export the component object(s) to text for copying for (auto ObjectIt = ObjectMap.CreateIterator(); ObjectIt; ++ObjectIt) { // Get the component object to be copied UActorComponent* ComponentToCopy = ObjectIt->Value; check(ComponentToCopy); // If this component object had a parent within the selected set if (ParentMap.Contains(ComponentToCopy->GetFName())) { // Get the name of the parent component FName ParentName = ParentMap[ComponentToCopy->GetFName()]; if (ObjectMap.Contains(ParentName)) { // Ensure that this component is a scene component USceneComponent* SceneComponent = Cast<USceneComponent>(ComponentToCopy); if (SceneComponent) { // Set the attach parent to the matching parent object in the temporary set. This allows us to preserve hierarchy in the copied set. SceneComponent->AttachParent = Cast<USceneComponent>(ObjectMap[ParentName]); } } } // Export the component object to the given string UExporter::ExportToOutputDevice(&Context, ComponentToCopy, NULL, Archive, TEXT("copy"), 0, PPF_ExportsNotFullyQualified | PPF_Copy | PPF_Delimited, false, ComponentToCopy->GetOuter()); } // Copy text to clipboard FString ExportedText = Archive; FPlatformMisc::ClipboardCopy(*ExportedText); }
/** * Adds marks to an object * * @param Object Object to add marks to * @param Marks Logical OR of OBJECTMARK_'s to apply */ void MarkObject(const class UObjectBase* Object, EObjectMark Marks) { MarkAnnotation.AddAnnotation(Object,FObjectMark(EObjectMark(MarkAnnotation.GetAnnotation(Object).Marks | Marks))); }