Exemple #1
0
/**
 * Return the path name of the UObject represented by the specified export.
 * (can be used with StaticFindObject)
 * 
 * @param	ExportIndex				index into the ExportMap for the resource to get the name for
 * @param	FakeRoot				Optional name to replace use as the root package of this object instead of the linker
 * @param	bResolveForcedExports	if true, the package name part of the return value will be the export's original package,
 *									not the name of the package it's currently contained within.
 *
 * @return	the path name of the UObject represented by the resource at ExportIndex
 */
FString ULinker::GetExportPathName(int32 ExportIndex, const TCHAR* FakeRoot,bool bResolveForcedExports/*=false*/)
{
	FString Result;
	ULinkerLoad* Loader = dynamic_cast<ULinkerLoad*>(this);

	bool bForcedExport = false;
	for ( FPackageIndex LinkerIndex = FPackageIndex::FromExport(ExportIndex); !LinkerIndex.IsNull(); LinkerIndex = Exp(LinkerIndex).OuterIndex )
	{ 
		const FObjectExport Export = Exp(LinkerIndex);

		// don't append a dot in the first iteration
		if ( Result.Len() > 0 )
		{
			// if this export is not a UPackage but this export's Outer is a UPackage, we need to use subobject notation
			if (Loader != NULL
			&&	(	Export.OuterIndex.IsNull()
				||	Loader->GetExportClassName(Export.OuterIndex) == NAME_Package)
			&&	Loader->GetExportClassName(LinkerIndex) != NAME_Package)
			{
				Result = FString(SUBOBJECT_DELIMITER) + Result;
			}
			else
			{
				Result = FString(TEXT(".")) + Result;
			}
		}
		Result = Export.ObjectName.ToString() + Result;
		bForcedExport = bForcedExport || Export.bForcedExport;
	}

	if ( bForcedExport && FakeRoot == NULL && bResolveForcedExports )
	{
		// Result already contains the correct path name for this export
		return Result;
	}

	return (FakeRoot ? FakeRoot : LinkerRoot->GetPathName()) + TEXT(".") + Result;
}
void FPackageDependencyInfo::RecursiveDeterminePackageDependentTimeStamp(const TCHAR* InPackageName, FDateTime& OutNewestTime, bool& bOutHadCircularReferences)
{
    // Find the package info...
    FPackageDependencyTrackingInfo** pPkgInfo = PackageInformation.Find(InPackageName);
    if ((pPkgInfo != NULL) && (*pPkgInfo != NULL))
    {
        FPackageDependencyTrackingInfo* PkgInfo = *pPkgInfo;
        if (PkgInfo->bBeingProcessed == true)
        {
            // Circular reference??
            bOutHadCircularReferences = true;
            return;
        }

        checkf((PkgInfo->DependentTimeStamp == FDateTime::MinValue()), TEXT("RecursiveDeterminePackageDependentTimeStamp: Package already processed: %s"), InPackageName);

        // We have the package info, so process the actual package.
        BeginLoad();
        ULinkerLoad* Linker = GetPackageLinker(NULL, InPackageName, LOAD_NoVerify, NULL, NULL);
        EndLoad();
        if (Linker != NULL)
        {
            PkgInfo->bBeingProcessed = true;

            // Start off with setting the dependent time to the package itself
            PkgInfo->DependentTimeStamp = PkgInfo->TimeStamp;

            // Map? Code (ie blueprint)?
            PkgInfo->bContainsMap = Linker->ContainsMap();
            PkgInfo->bContainsBlueprints = Linker->ContainsCode();

            FName CheckMaterial = FName(TEXT("Material"));
            FName CheckMIC = FName(TEXT("MaterialInstanceConstant"));
            FName CheckMID = FName(TEXT("MaterialInstanceDynamic"));
            FName CheckLMIC = FName(TEXT("LandscapeMaterialInstanceConstant"));
            FName CheckWorld = FName(TEXT("World"));
            FName CheckBlueprint = FName(TEXT("Blueprint"));
            FName CheckAnimBlueprint = FName(TEXT("AnimBlueprint"));


            // Check the export map for material interfaces
            for (int32 ExpIdx = 0; ExpIdx < Linker->ExportMap.Num(); ExpIdx++)
            {
                FObjectExport& ObjExp = Linker->ExportMap[ExpIdx];
                FName ExpClassName = Linker->GetExportClassName(ExpIdx);
                if ((ExpClassName == CheckMaterial) ||
                        (ExpClassName == CheckMIC) ||
                        (ExpClassName == CheckMID) ||
                        (ExpClassName == CheckLMIC))
                {
                    PkgInfo->bContainsShaders = true;
                    if (PkgInfo->DependentTimeStamp < ShaderSourceTimeStamp)
                    {
                        PkgInfo->DependentTimeStamp = ShaderSourceTimeStamp;
                    }
                    PkgInfo->DependentPackages.Add(ShaderSourcePkgName, ShaderSourcePkgInfo);
                    AllPackages.Add(ShaderSourcePkgInfo);
                }
                else if (ExpClassName == CheckWorld)
                {
                    PkgInfo->bContainsMap = true;
                }
                else if ((ExpClassName == CheckBlueprint) ||
                         (ExpClassName == CheckAnimBlueprint))
                {
                    PkgInfo->bContainsBlueprints = true;
                    if (PkgInfo->DependentTimeStamp < ScriptSourceTimeStamp)
                    {
                        PkgInfo->DependentTimeStamp = ScriptSourceTimeStamp;
                    }
                    PkgInfo->DependentPackages.Add(ScriptSourcePkgName, ScriptSourcePkgInfo);
                    AllPackages.Add(ScriptSourcePkgInfo);
                }
            }

            // Check the dependencies
            //@todo. Make this a function of the linker? Almost the exact same code is used in PkgInfo commandlet...
            FName LinkerName = Linker->LinkerRoot->GetFName();
            TArray<FName> DependentPackages;
            for (int32 ImpIdx = 0; ImpIdx < Linker->ImportMap.Num(); ImpIdx++)
            {
                FObjectImport& ObjImp = Linker->ImportMap[ImpIdx];

                FName PackageName = NAME_None;
                FName OuterName = NAME_None;
                if (!ObjImp.OuterIndex.IsNull())
                {
                    // Find the package which contains this import.  import.SourceLinker is cleared in EndLoad, so we'll need to do this manually now.
                    FPackageIndex OutermostLinkerIndex = ObjImp.OuterIndex;
                    for (FPackageIndex LinkerIndex = ObjImp.OuterIndex; !LinkerIndex.IsNull();)
                    {
                        OutermostLinkerIndex = LinkerIndex;
                        LinkerIndex = Linker->ImpExp(LinkerIndex).OuterIndex;
                    }
                    PackageName = Linker->ImpExp(OutermostLinkerIndex).ObjectName;
                }

                if (PackageName == NAME_None && ObjImp.ClassName == NAME_Package)
                {
                    PackageName = ObjImp.ObjectName;
                }

                if ((PackageName != NAME_None) && (PackageName != LinkerName))
                {
                    DependentPackages.AddUnique(PackageName);
                }

                if ((ObjImp.ClassPackage != NAME_None) && (ObjImp.ClassPackage != LinkerName))
                {
                    DependentPackages.AddUnique(ObjImp.ClassPackage);
                }
            }

            for (int32 DependentIdx = 0; DependentIdx < DependentPackages.Num(); DependentIdx++)
            {
                FString PkgName = DependentPackages[DependentIdx].ToString();
                FText Reason;
                if (!FPackageName::IsValidLongPackageName(PkgName, true, &Reason))
                {
                    //UE_LOG(LogPackageDependencyInfo, Display, TEXT("%s --> %s"), *PkgName, *Reason.ToString());
                    continue;
                }
                FString LongName = FPackageName::LongPackageNameToFilename(PkgName);
                //UE_LOG(LogPackageDependencyInfo, Display, TEXT("%s --> %s"), *PkgName, *LongName);
                // Is it already in the list
                FPackageDependencyTrackingInfo** pDepPkgInfo = PackageInformation.Find(LongName);
                if ((pDepPkgInfo == NULL) || (*pDepPkgInfo == NULL))
                {
                    continue;
                }

                FPackageDependencyTrackingInfo* DepPkgInfo = *pDepPkgInfo;
                if (DepPkgInfo->bBeingProcessed == true)
                {
                    bOutHadCircularReferences = true;
                    // Circular reference
                    // For now, store it off and we will resolve when completed
                    PkgInfo->DependentPackages.Add(LongName, DepPkgInfo);
                    PkgInfo->bHasCircularReferences = true;
                    AllPackages.Add(PkgInfo);
                    continue;
                }

                if (DepPkgInfo->DependentTimeStamp == FDateTime::MinValue())
                {
                    FDateTime TempTime;
                    RecursiveDeterminePackageDependentTimeStamp(*LongName, TempTime, bOutHadCircularReferences);
                }

                PkgInfo->DependentPackages.Add(LongName, DepPkgInfo);
                AllPackages.Add(DepPkgInfo);

                if (DepPkgInfo->DependentTimeStamp != FDateTime::MinValue())
                {
                    if (PkgInfo->DependentTimeStamp < DepPkgInfo->DependentTimeStamp)
                    {
                        PkgInfo->DependentTimeStamp = DepPkgInfo->DependentTimeStamp;
                    }
                }
            }

            PkgInfo->bBeingProcessed = false;
            OutNewestTime = PkgInfo->DependentTimeStamp;
        }
        else
        {
            UE_LOG(LogPackageDependencyInfo, Display, TEXT("RecursiveDeterminePackageDependentTimeStamp: Failed to find linker for %s"), InPackageName);
        }
    }
    else
    {
        UE_LOG(LogPackageDependencyInfo, Display, TEXT("RecursiveDeterminePackageDependentTimeStamp: Failed to find package info for %s"), InPackageName);
    }
}