void UExporter::ExportComponentDefinitions(const FExportObjectInnerContext* Context, const TArray<UObject*>& Components, FOutputDevice& Ar, uint32 PortFlags)
{
	PortFlags |= PPF_ExportsNotFullyQualified;

	if (!(PortFlags & PPF_SeparateDefine))
	{
		// export forward declarations
		// technically we only need to do this if there are circular references but it doesn't seem worth it
		// to complicate this code for a minor speed improvement in the text import path
		for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
		{
			UObject* Component = Components[ComponentIndex];
			FName ComponentName = Component->GetFName();
			if (!Component->HasAnyMarks(OBJECTMARK_TagImp) && !Component->HasAnyFlags(RF_TextExportTransient))
			{
				if (Component->HasAnyFlags(RF_ClassDefaultObject) || Component->GetArchetype()->HasAllFlags(RF_ClassDefaultObject))
				{
					Ar.Logf(TEXT("%sBegin Object Class=%s Name=%s ObjName=%s%s"), FCString::Spc(TextIndent), *Component->GetClass()->GetName(), *ComponentName.ToString(), *Component->GetName(), LINE_TERMINATOR);
				}
				else
				{
					Ar.Logf(TEXT("%sBegin Object Class=%s Name=%s ObjName=%s Archetype=%s'%s'%s"),FCString::Spc(TextIndent),*Component->GetClass()->GetName(), *ComponentName.ToString(), *Component->GetName(), *Component->GetArchetype()->GetClass()->GetName(), *Component->GetArchetype()->GetPathName(), LINE_TERMINATOR);
				}
				if (PortFlags & PPF_SeparateDeclare)
				{
					ExportObjectInner(Context, Component, Ar, PortFlags, false);
				}
				Ar.Logf(TEXT("%sEnd Object%s"), FCString::Spc(TextIndent), LINE_TERMINATOR);
			}
		}
	}

	if (!(PortFlags & PPF_SeparateDeclare))
	{
		// export property definitions
		for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
		{
			UObject* Component = Components[ComponentIndex];
			FName ComponentName = Component->GetFName();
			if (!Component->HasAnyMarks(OBJECTMARK_TagImp) && !Component->HasAnyFlags(RF_TextExportTransient))
			{
				Ar.Logf(TEXT("%sBegin Object Name=%s%s"), FCString::Spc(TextIndent), *ComponentName.ToString(), LINE_TERMINATOR);

				uint32 OldPortFlags = PortFlags;

				if (!(Component->HasAnyFlags(RF_ClassDefaultObject) || Component->GetArchetype()->HasAllFlags(RF_ClassDefaultObject)))
				{
					// we created this thing with an archetype (see archetype=, above), so we don't want to list the archetype because it is unqualified and will clash, resetting the archetype pointer to something silly
					PortFlags |= PPF_NoInternalArcheType;
				}
				ExportObjectInner(Context, Component, Ar, PortFlags, false);

				PortFlags = OldPortFlags;
				Ar.Logf(TEXT("%sEnd Object%s"), FCString::Spc(TextIndent), LINE_TERMINATOR);

				Component->Mark(OBJECTMARK_TagImp);
			}
		}
	}
}
示例#2
0
bool FFrontendFilter_InUseByLoadedLevels::PassesFilter(FAssetFilterType InItem) const
{
	bool bObjectInUse = false;
	
	if ( InItem.IsAssetLoaded() )
	{
		UObject* Asset = InItem.GetAsset();

		const bool bUnreferenced = !Asset->HasAnyMarks( OBJECTMARK_TagExp );
		const bool bIndirectlyReferencedObject = Asset->HasAnyMarks( OBJECTMARK_TagImp );
		const bool bRejectObject =
			Asset->GetOuter() == NULL || // Skip objects with null outers
			Asset->HasAnyFlags( RF_Transient ) || // Skip transient objects (these shouldn't show up in the CB anyway)
			Asset->IsPendingKill() || // Objects that will be garbage collected 
			bUnreferenced || // Unreferenced objects 
			bIndirectlyReferencedObject; // Indirectly referenced objects

		if( !bRejectObject && Asset->HasAnyFlags( RF_Public ) )
		{
			// The object is in use 
			bObjectInUse = true;
		}
	}

	return bObjectInUse;
}
示例#3
0
/**
 * Exports the property values for the specified object as text to the output device.
 *
 * @param	Context			Context from which the set of 'inner' objects is extracted.  If NULL, an object iterator will be used.
 * @param	Out				the output device to send the exported text to
 * @param	ObjectClass		the class of the object to dump properties for
 * @param	Object			the address of the object to dump properties for
 * @param	Indent			number of spaces to prepend to each line of output
 * @param	DiffClass		the class to use for comparing property values when delta export is desired.
 * @param	Diff			the address of the object to use for determining whether a property value should be exported.  If the value in Object matches the corresponding
 *							value in Diff, it is not exported.  Specify NULL to export all properties.
 * @param	Parent			the UObject corresponding to Object
 * @param	PortFlags		flags used for modifying the output and/or behavior of the export
 */
void ExportProperties
(
    const FExportObjectInnerContext* Context,
    FOutputDevice&	Out,
    UClass*			ObjectClass,
    uint8*			Object,
    int32				Indent,
    UClass*			DiffClass,
    uint8*			Diff,
    UObject*		Parent,
    uint32			PortFlags,
    UObject*		ExportRootScope
)
{
    FString ThisName = TEXT("(none)");
    check(ObjectClass != NULL);

    for( UProperty* Property = ObjectClass->PropertyLink; Property; Property = Property->PropertyLinkNext )
    {
        if (!Property->ShouldPort(PortFlags))
            continue;

        ThisName = Property->GetName();
        UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property);
        UObjectPropertyBase* ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(Property) : NULL;
        const uint32 ExportFlags = PortFlags | PPF_Delimited;

        if ( ArrayProperty != NULL )
        {
            // Export dynamic array.
            UProperty* InnerProp = ArrayProperty->Inner;
            ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(InnerProp) : NULL;
            // This is used as the default value in the case of an array property that has
            // fewer elements than the exported object.
            uint8* StructDefaults = NULL;
            UStructProperty* StructProperty = Cast<UStructProperty>(InnerProp);
            if ( StructProperty != NULL )
            {
                checkSlow(StructProperty->Struct);
                StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize());
                StructProperty->InitializeValue(StructDefaults);
            }

            for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ )
            {
                void* Arr = Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex);
                FScriptArrayHelper ArrayHelper(ArrayProperty, Arr);

                void*	DiffArr = NULL;
                if( DiffClass )
                {
                    DiffArr = Property->ContainerPtrToValuePtrForDefaults<void>(DiffClass, Diff, PropertyArrayIndex);
                }
                // we won't use this if DiffArr is NULL, but we have to set it up to something
                FScriptArrayHelper DiffArrayHelper(ArrayProperty, DiffArr);

                bool bAnyElementDiffered = false;
                for( int32 DynamicArrayIndex=0; DynamicArrayIndex<ArrayHelper.Num(); DynamicArrayIndex++ )
                {
                    FString	Value;

                    // compare each element's value manually so that elements which match the NULL value for the array's inner property type
                    // but aren't in the diff array are still exported
                    uint8* SourceData = ArrayHelper.GetRawPtr(DynamicArrayIndex);
                    uint8* DiffData = DiffArr && DynamicArrayIndex < DiffArrayHelper.Num()
                                      ? DiffArrayHelper.GetRawPtr(DynamicArrayIndex)
                                      : StructDefaults;

                    bool bExportItem = DiffData == NULL || (DiffData != SourceData && !InnerProp->Identical(SourceData, DiffData, ExportFlags));
                    if ( bExportItem )
                    {
                        bAnyElementDiffered = true;
                        InnerProp->ExportTextItem(Value, SourceData, DiffData, Parent, ExportFlags, ExportRootScope);
                        if(ExportObjectProp)
                        {
                            UObject* Obj = ExportObjectProp->GetObjectPropertyValue(ArrayHelper.GetRawPtr(DynamicArrayIndex));
                            check(!Obj || Obj->IsValidLowLevel());
                            if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) )
                            {
                                // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions,
                                // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be
                                // used as the Outer to create the component

                                // Is this an array of components?
                                if ( InnerProp->HasAnyPropertyFlags(CPF_InstancedReference) )
                                {
                                    if ( Obj->GetOuter() == Parent )
                                    {
                                        // Don't export more than once.
                                        Obj->Mark(OBJECTMARK_TagImp);
                                        UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                    }
                                    else
                                    {
                                        // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object
                                        Obj->Mark(OBJECTMARK_TagExp);
                                    }
                                }
                                else
                                {
                                    // Don't export more than once.
                                    Obj->Mark(OBJECTMARK_TagImp);
                                    UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                }
                            }
                        }

                        Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex, *Value );
                    }
                    // if some other element has already been determined to differ from the defaults, then export this item with no data so that
                    // the different array's size is maintained on import (this item will get the default values for that index, if any)
                    // however, if no elements of the array have changed, we still don't want to export anything
                    // so that the array size will also be taken from the defaults, which won't be the case if any element is exported
                    else if (bAnyElementDiffered)
                    {
                        Out.Logf( TEXT("%s%s(%i)=()\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex );
                    }
                }
            }
            if (StructDefaults)
            {
                StructProperty->DestroyValue(StructDefaults);
                FMemory::Free(StructDefaults);
            }
        }
        else
        {
            for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ )
            {
                FString	Value;
                // Export single element.

                uint8* DiffData = (DiffClass && Property->IsInContainer(DiffClass->GetPropertiesSize())) ? Diff : NULL;
                if( Property->ExportText_InContainer( PropertyArrayIndex, Value, Object, DiffData, Parent, ExportFlags, ExportRootScope ) )
                {
                    if ( ExportObjectProp )
                    {
                        UObject* Obj = ExportObjectProp->GetObjectPropertyValue(Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex));
                        if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) )
                        {
                            // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions,
                            // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be
                            // used as the Outer to create the component
                            if ( Property->HasAnyPropertyFlags(CPF_InstancedReference) )
                            {
                                if ( Obj->GetOuter() == Parent )
                                {
                                    // Don't export more than once.
                                    Obj->Mark(OBJECTMARK_TagImp);
                                    UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                }
                                else
                                {
                                    // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object
                                    Obj->Mark(OBJECTMARK_TagExp);
                                }
                            }
                            else
                            {
                                // Don't export more than once.
                                Obj->Mark(OBJECTMARK_TagImp);
                                UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                            }
                        }
                    }

                    if( Property->ArrayDim == 1 )
                    {
                        Out.Logf( TEXT("%s%s=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), *Value );
                    }
                    else
                    {
                        Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), PropertyArrayIndex, *Value );
                    }
                }
            }
        }
    }

    // Allows to import/export C++ properties in case the automatic unreal script mesh wouldn't work.
    Parent->ExportCustomProperties(Out, Indent);
}
/**
 * Manually serializes the class and archetype for the specified object so that assets which are referenced
 * through the object's class/archetype can be differentiated.
 */
void FFindAssetsArchive::HandleReferencedObject(UObject* Obj )
{
	if ( CurrentReferenceGraph != NULL )
	{
		// here we allow recursion if the current depth is less-than-equal (as opposed to less-than) because the archetype and class are treated as transparent objects
		// serialization of the class and object are controlled by the "show class refs" and "show default refs" buttons
		if ( MaxRecursionDepth == 0 || CurrentDepth < MaxRecursionDepth )
		{
			// now change the current reference list to the one for this object
			if ( bIncludeDefaultRefs == true )
			{
				UObject* ObjectArc = Obj->GetArchetype();
				UObject* Key = bUseReverseReferenceGraph? ObjectArc: Obj;
				UObject* Value = bUseReverseReferenceGraph? Obj: ObjectArc;
				TSet<UObject*>* ReferencedAssets = GetAssetList(Key);

				// @see the comment for the bIncludeScriptRefs block
				ReferencedAssets->Add(Value);

				UObject* PreviousObject = CurrentObject;
				CurrentObject = ObjectArc;

				if ( ObjectArc->HasAnyMarks(OBJECTMARK_TagExp) )
				{
					// temporarily disable serialization of the class, as we need to specially handle that as well
					bool bSkipClassSerialization = ArIgnoreClassRef;
					ArIgnoreClassRef = true;

					ObjectArc->UnMark(OBJECTMARK_TagExp);
					ObjectArc->Serialize(*this);

					ArIgnoreClassRef = bSkipClassSerialization;
				}

				CurrentObject = PreviousObject;
			}

			if ( bIncludeScriptRefs == true )
			{
				UClass* ObjectClass = Obj->GetClass();
				UObject* Key = bUseReverseReferenceGraph? ObjectClass: Obj;
				UObject* Value = bUseReverseReferenceGraph? Obj: ObjectClass;
				TSet<UObject*>* ReferencedAssets = GetAssetList(Key);

				// we want to see assets referenced by this object's class, but classes don't have associated thumbnail rendering info
				// so we'll need to serialize the class manually in order to get the object references encountered through the class to fal
				// under the appropriate tree item

				// serializing the class will result in serializing the class default object; but we need to do this manually (for the same reason
				// that we do it for the class), so temporarily prevent the CDO from being serialized by this archive
				ReferencedAssets->Add(Value);

				UObject* PreviousObject = CurrentObject;
				CurrentObject = ObjectClass;

				if ( ObjectClass->HasAnyMarks(OBJECTMARK_TagExp) )
				{
					ObjectClass->UnMark(OBJECTMARK_TagExp);
					ObjectClass->Serialize(*this);
				}

				CurrentObject = PreviousObject;
			}
		}
	}
}
/**
 * Serializes an FTextureAllocations struct
 */
FArchive& operator<<( FArchive& Ar, FTextureAllocations& TextureAllocations )
{
	int32 NumSummaryTextures = 0;
	int32 NumExportTexturesTotal = 0;
	int32 NumExportTexturesAdded = 0;

	#if UE4_TODO
		// Are we cooking a package?
		if ( Ar.IsSaving() && !Ar.IsTransacting() )
		{
			FLinker* Linker = Ar.GetLinker();

			// Do we need to build the texture allocation data?
			if ( TextureAllocations.TextureTypes.Num() == 0 )
			{
				TArray<UObject*> TagExpObjects;
				GetObjectsWithAnyMarks(TagExpObjects, OBJECTMARK_TagExp);
				for(int32 Index = 0; Index < TagExpObjects.Num(); Index++)
				{
					UObject* Object = TagExpObjects(Index);
					check(Object->HasAnyMarks(OBJECTMARK_TagExp));
					if ( !Object->HasAnyFlags(RF_ClassDefaultObject) )
					{
						if (UTexture2D* Texture2D = dynamic_cast<UTexture2D*>(Object))
						{
							int32 PreAllocateSizeX = 0;
							int32 PreAllocateSizeY = 0;
							int32 PreAllocateNumMips = 0;
							uint32 TexCreateFlags = 0;
							if ( Texture2D->GetResourceMemSettings(Texture2D->FirstResourceMemMip, PreAllocateSizeX, PreAllocateSizeY, PreAllocateNumMips, TexCreateFlags ) )
							{
								TextureAllocations.AddResourceMemInfo(PreAllocateSizeX, PreAllocateSizeY, PreAllocateNumMips, Texture2D->Format, TexCreateFlags );
							}
						}
					}
				}
			}
			// Do we need to fixup the export indices?
			else if ( Ar.GetLinker() )
			{
				NumSummaryTextures = 0;
				FLinker* Linker = Ar.GetLinker();
				for ( int32 TypeIndex=0; TypeIndex < TextureAllocations.TextureTypes.Num(); ++TypeIndex )
				{
					FTextureAllocations::FTextureType& TextureType = TextureAllocations.TextureTypes( TypeIndex );
					NumSummaryTextures += TextureType.ExportIndices.Num();
					TextureType.ExportIndices.Empty();
				}

				NumExportTexturesTotal = 0;
				NumExportTexturesAdded = 0;
				for ( int32 ExportIndex=0; ExportIndex < Linker->ExportMap.Num(); ++ExportIndex )
				{
					UTexture2D* Texture2D = dynamic_cast<UTexture2D*>(Linker->ExportMap(ExportIndex).Object);
					if ( Texture2D && !Texture2D->HasAnyFlags(RF_ClassDefaultObject) )
					{
						NumExportTexturesTotal++;
						int32 PreAllocateSizeX = 0;
						int32 PreAllocateSizeY = 0;
						int32 PreAllocateNumMips = 0;
						uint32 TexCreateFlags = 0;
						if ( Texture2D->GetResourceMemSettings(Texture2D->FirstResourceMemMip, PreAllocateSizeX, PreAllocateSizeY, PreAllocateNumMips, TexCreateFlags ) )
						{
							FTextureAllocations::FTextureType* TextureType = TextureAllocations.FindTextureType(PreAllocateSizeX, PreAllocateSizeY, PreAllocateNumMips, Texture2D->Format, TexCreateFlags);
							check( TextureType );
							TextureType->ExportIndices.Add( ExportIndex );
							NumExportTexturesAdded++;
						}
					}
				}
				check( NumSummaryTextures == NumExportTexturesAdded );
			}
		}
	#endif

	Ar << TextureAllocations.TextureTypes;

	TextureAllocations.PendingAllocationSize = 0;
	TextureAllocations.PendingAllocationCount.Reset();

	return Ar;
}