Beispiel #1
0
        public static void Run(AssetItem assetItem, ILogger log, AssetAnalysisParameters parameters)
        {
            if (assetItem == null)
            {
                throw new ArgumentNullException("assetItem");
            }
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("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 [{0}] with id [{1}] from Package [{2}] is already loaded from package [{3}]", existingAsset.FullPath, existingAsset.Id, package.FullPath, existingAsset.Package.FullPath);
                    }
                    else
                    {
                        existingAsset = otherPackage.Assets.Find(assetItem.Location);
                        if (existingAsset != null)
                        {
                            log.Error("Assets [{0}] with location [{1}] from Package [{2}] is already loaded from package [{3}]", existingAsset.FullPath, existingAsset.Location, package.FullPath, 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);
            }
        }
Beispiel #2
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);
        }
Beispiel #3
0
        /// <summary>
        /// Cleans the specified input items.
        /// </summary>
        /// <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>
        /// <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(ICollection <AssetItem> inputItems, ICollection <AssetItem> outputItems, AssetResolver assetResolver, bool cloneInput)
        {
            if (inputItems == null)
            {
                throw new ArgumentNullException("inputItems");
            }
            if (outputItems == null)
            {
                throw new ArgumentNullException("outputItems");
            }
            if (assetResolver == null)
            {
                throw new ArgumentNullException("assetResolver");
            }

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

            var items = inputItems;

            if (cloneInput)
            {
                items = inputItems.Select(item => item.Clone()).ToList();
            }

            // Check if locations are conflicting
            var locationConflicts = new Dictionary <AssetItem, UFile>();

            foreach (var item in items)
            {
                UFile newLocation;
                if (assetResolver.RegisterLocation(item.Location, out newLocation))
                {
                    locationConflicts[item] = newLocation;
                }
            }

            // Check if ids are conflicting
            var idConflicts = new Dictionary <AssetItem, Guid>();

            foreach (var item in items)
            {
                Guid newGuid;
                if (assetResolver.RegisterId(item.Id, out newGuid))
                {
                    idConflicts[item] = newGuid;
                }
            }

            // Calculate final guid => guid remapping
            // Because several asset items can have the same id, we are only using the first one for remapping
            var idRemap       = new Dictionary <Guid, Tuple <Guid, UFile> >();
            var locationRemap = new Dictionary <UFile, UFile>();

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

                outputItems.Add(item);

                Guid newGuid;
                if (!idConflicts.TryGetValue(item, out newGuid))
                {
                    newGuid = item.Id;
                }

                UFile newLocation;
                if (locationConflicts.TryGetValue(item, out newLocation) && !locationRemap.ContainsKey(item.Location))
                {
                    locationRemap.Add(item.Location, newLocation);
                }

                if (!idRemap.ContainsKey(item.Id))
                {
                    idRemap.Add(item.Id, new Tuple <Guid, UFile>(newGuid, newLocation ?? item.Location));
                }
            }

            // Process assets
            foreach (var item in outputItems)
            {
                // Replace Id
                Guid newGuid;
                if (idConflicts.TryGetValue(item, out newGuid))
                {
                    item.Asset.Id = newGuid;
                    item.IsDirty  = true;
                }

                // Replace location
                if (locationConflicts.ContainsKey(item))
                {
                    item.Location = locationConflicts[item];
                    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 IContentReference).ToList();

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

                    var newId       = assetReference.Id;
                    var newLocation = assetReference.Location;

                    bool requireUpdate = false;

                    Tuple <Guid, UFile> newRemap;
                    if (idRemap.TryGetValue(newId, out newRemap) && (newId != newRemap.Item1 || newLocation != newRemap.Item2))
                    {
                        newId         = newRemap.Item1;
                        newLocation   = newRemap.Item2;
                        requireUpdate = true;
                    }

                    UFile remapLocation;
                    if (!requireUpdate && locationRemap.TryGetValue(newLocation, out remapLocation))
                    {
                        newLocation   = remapLocation;
                        requireUpdate = true;
                    }

                    if (requireUpdate)
                    {
                        assetLink.UpdateReference(newId, newLocation);
                        item.IsDirty = true;
                    }
                }
            }
        }
Beispiel #4
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>
        /// <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)
        {
            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()).ToList();
            }

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

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

                outputItems.Add(item);

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

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

                var tuple = new Tuple <Guid, UFile>(newGuid != Guid.Empty ? newGuid : 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 <Guid, 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;
                }

                // 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;
                    }
                }

                // Fix base if there are any
                if (item.Asset.Base != null && idRemap.TryGetValue(item.Asset.Base.Id, out remap) && IsNewReference(remap, item.Asset.Base))
                {
                    item.Asset.Base.Asset.Id = remap.Item1;
                    item.Asset.Base          = new AssetBase(remap.Item2, item.Asset.Base.Asset);
                    item.IsDirty             = true;
                }

                // Fix base parts if there are any remap for them as well
                if (item.Asset.BaseParts != null)
                {
                    for (int i = 0; i < item.Asset.BaseParts.Count; i++)
                    {
                        var basePart = item.Asset.BaseParts[i];
                        if (idRemap.TryGetValue(basePart.Id, out remap) && IsNewReference(remap, basePart))
                        {
                            basePart.Asset.Id       = remap.Item1;
                            item.Asset.BaseParts[i] = new AssetBase(remap.Item2, basePart.Asset);
                            item.IsDirty            = true;
                        }
                    }
                }
            }

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

                // We check dependencies to be consistent with other places, but nothing should be changed in there
                // (except if we were to instantiate multiple packages referencing each other at once?)
                foreach (var dependency in package.LocalDependencies)
                {
                    if (dependency.RootAssets != null)
                    {
                        UpdateRootAssets(dependency.RootAssets, idRemap);
                    }
                }
                foreach (var dependency in package.Meta.Dependencies)
                {
                    if (dependency.RootAssets != null)
                    {
                        UpdateRootAssets(dependency.RootAssets, idRemap);
                    }
                }
            }
        }
Beispiel #5
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);
            }
        }