예제 #1
0
        /// <summary>
        /// Processes the UPaths on package (but not on assets, use <see cref="ProcessAssets"/> for this)
        /// </summary>
        public void ProcessPackageUPaths()
        {
            if (package.FullPath == null)
            {
                return;
            }

            var packageReferenceLinks = AssetReferenceAnalysis.Visit(package);

            CommonAnalysis.UpdatePaths(package, packageReferenceLinks.Where(link => link.Reference is UPath), Parameters);
        }
예제 #2
0
        public static void Run(AssetItem assetItem, ILogger log, AssetAnalysisParameters parameters)
        {
            if (assetItem == null)
            {
                throw new ArgumentNullException(nameof(assetItem));
            }
            if (log == null)
            {
                throw new ArgumentNullException(nameof(log));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            if (assetItem.Package == null)
            {
                throw new InvalidOperationException("AssetItem must belong to an existing package");
            }

            var package = assetItem.Package;

            // Check that there is no duplicate in assets
            if (package.Session != null)
            {
                var packages = package.FindDependencies();

                foreach (var otherPackage in packages)
                {
                    var existingAsset = otherPackage.Assets.Find(assetItem.Id);

                    if (existingAsset != null)
                    {
                        log.Error($"Assets [{existingAsset.FullPath}] with id [{existingAsset.Id}] from Package [{package.FullPath}] is already loaded from package [{existingAsset.Package.FullPath}]");
                    }
                    else
                    {
                        existingAsset = otherPackage.Assets.Find(assetItem.Location);
                        if (existingAsset != null)
                        {
                            log.Error($"Assets [{existingAsset.FullPath}] with location [{existingAsset.Location}] from Package [{package.FullPath}] is already loaded from package [{existingAsset.Package.FullPath}]");
                        }
                    }
                }
            }

            var assetReferences = AssetReferenceAnalysis.Visit(assetItem.Asset);

            if (package.Session != null && parameters.IsProcessingAssetReferences)
            {
                UpdateAssetReferences(assetItem, assetReferences, log, parameters);
            }
            // Update paths for asset items

            if (parameters.IsProcessingUPaths)
            {
                // Find where this asset item was previously stored (in a different package for example)
                CommonAnalysis.UpdatePaths(assetItem, assetReferences.Where(link => link.Reference is UPath), parameters);
                // Source hashes are not processed by analysis, we need to manually indicate them to update
                SourceHashesHelper.UpdateUPaths(assetItem.Asset, assetItem.FullPath.GetParent(), parameters.ConvertUPathTo);
            }
        }
예제 #3
0
        /// <summary>
        /// Cleans the specified input items.
        /// </summary>
        /// <param name="package">The package to process (optional).</param>
        /// <param name="inputItems">The input items.</param>
        /// <param name="outputItems">The output items.</param>
        /// <param name="assetResolver">The asset resolver.</param>
        /// <param name="cloneInput">if set to <c>true</c> [clone input].</param>
        /// <param name="removeUnloadableObjects">If set to <c>true</c>, assets will be cloned with <see cref="AssetClonerFlags.RemoveUnloadableObjects"/>.</param>
        /// <exception cref="System.ArgumentNullException">
        /// inputItems
        /// or
        /// outputItems
        /// or
        /// assetResolver
        /// </exception>
        /// <exception cref="System.ArgumentException">List cannot contain null items;inputItems</exception>
        public static void Clean(Package package, ICollection <AssetItem> inputItems, ICollection <AssetItem> outputItems, AssetResolver assetResolver, bool cloneInput, bool removeUnloadableObjects)
        {
            if (inputItems == null)
            {
                throw new ArgumentNullException(nameof(inputItems));
            }
            if (outputItems == null)
            {
                throw new ArgumentNullException(nameof(outputItems));
            }
            if (assetResolver == null)
            {
                throw new ArgumentNullException(nameof(assetResolver));
            }

            // Check that all items are non-null
            if (inputItems.Any(item => item == null))
            {
                throw new ArgumentException("List cannot contain null items", nameof(inputItems));
            }

            var items = inputItems;

            if (cloneInput)
            {
                items = inputItems.Select(item => item.Clone(flags: removeUnloadableObjects ? AssetClonerFlags.RemoveUnloadableObjects : AssetClonerFlags.None)).ToList();
            }

            // idRemap should contain only assets that have either 1) their id remapped or 2) their location remapped
            var idRemap   = new Dictionary <AssetId, Tuple <AssetId, UFile> >();
            var itemRemap = new Dictionary <AssetItem, Tuple <AssetId, UFile> >();

            foreach (var item in items)
            {
                if (outputItems.Contains(item))
                {
                    continue;
                }

                outputItems.Add(item);

                bool    changed = false;
                AssetId newId;
                if (assetResolver.RegisterId(item.Id, out newId))
                {
                    changed = true;
                }

                UFile newLocation;
                if (assetResolver.RegisterLocation(item.Location, out newLocation))
                {
                    changed = true;
                }

                var tuple = new Tuple <AssetId, UFile>(newId != AssetId.Empty ? newId : item.Id, newLocation ?? item.Location);
                if (changed)
                {
                    if (!itemRemap.ContainsKey(item))
                    {
                        itemRemap.Add(item, tuple);
                    }
                }

                if (!idRemap.ContainsKey(item.Id))
                {
                    idRemap.Add(item.Id, tuple);
                }
            }

            // Process assets
            foreach (var item in outputItems)
            {
                Tuple <AssetId, UFile> remap;
                if (itemRemap.TryGetValue(item, out remap) && (remap.Item1 != item.Asset.Id || remap.Item2 != item.Location))
                {
                    item.Asset.Id = remap.Item1;
                    item.Location = remap.Item2;
                    item.IsDirty  = true;
                }

                // Fix base parts if there are any remap for them as well
                // This has to be done before the default resolver below because this fix requires to rewrite the base part completely, since the base part asset is immutable
                var assetComposite = item.Asset as IAssetComposite;
                if (assetComposite != null)
                {
                    foreach (var basePart in assetComposite.CollectParts())
                    {
                        if (basePart.Base != null && idRemap.TryGetValue(basePart.Base.BasePartAsset.Id, out remap) && IsNewReference(remap, basePart.Base.BasePartAsset))
                        {
                            var newAssetReference = new AssetReference(remap.Item1, remap.Item2);
                            basePart.UpdateBase(new BasePart(newAssetReference, basePart.Base.BasePartId, basePart.Base.InstanceId));
                            item.IsDirty = true;
                        }
                    }
                }

                // The loop is a one or two-step.
                // - If there is no link to update, and the asset has not been cloned, we can exist immediately
                // - If there is links to update, and the asset has not been cloned, we need to clone it and re-enter the loop
                //   to perform the update of the clone asset
                var links = AssetReferenceAnalysis.Visit(item.Asset).Where(link => link.Reference is IReference).ToList();

                foreach (var assetLink in links)
                {
                    var assetReference = (IReference)assetLink.Reference;

                    var newId = assetReference.Id;
                    if (idRemap.TryGetValue(newId, out remap) && IsNewReference(remap, assetReference))
                    {
                        assetLink.UpdateReference(remap.Item1, remap.Item2);
                        item.IsDirty = true;
                    }
                }
            }

            // Process roots (until references in package are handled in general)
            if (package != null)
            {
                UpdateRootAssets(package.RootAssets, idRemap);
            }
        }