예제 #1
0
파일: SceneAsset.cs 프로젝트: joewan/xenko
            protected override void UpgradeAsset(AssetMigrationContext context, PackageVersion currentVersion, PackageVersion targetVersion, dynamic asset, PackageLoadingAssetFile assetFile)
            {
                // SerializedVersion format changed during renaming upgrade. However, before this was merged back in master, some asset upgrader still with older version numbers were developed.
                // As a result, sprite component upgrade is not needed for version 19 and 20, and physics component upgrade is not needed for version 20
                var version19 = PackageVersion.Parse("0.0.19");
                var version20 = PackageVersion.Parse("0.0.20");

                var hierarchy = asset.Hierarchy;
                var entities  = (DynamicYamlArray)hierarchy.Entities;

                foreach (dynamic entity in entities)
                {
                    var components      = entity.Entity.Components;
                    var spriteComponent = components["SpriteComponent.Key"];
                    if (spriteComponent != null && (currentVersion != version19 && currentVersion != version20))
                    {
                        var color = spriteComponent.Color;
                        spriteComponent.Color = DynamicYamlExtensions.ConvertFrom((Color4)DynamicYamlExtensions.ConvertTo <Color>(color));
                    }

                    var physComponent = components["PhysicsComponent.Key"];
                    if (physComponent != null && (currentVersion != version20))
                    {
                        foreach (dynamic element in physComponent.Elements)
                        {
                            if (element.Node.Tag == "!TriggerElement")
                            {
                                element.Node.Tag  = "!StaticColliderElement";
                                element.IsTrigger = true;
                            }
                        }
                    }
                }
            }
예제 #2
0
        public async Task ChangeSelectedPackageRowAsync(PackageRowPresentationModel selected)
        {
            _selectedPackage = selected;
            _loadDetailsCancellationTokenSource?.Cancel();
            _loadDetailsCancellationTokenSource = new CancellationTokenSource();

            var identity = new PackageIdentity(selected.Id, PackageVersion.Parse(selected.Version));

            var    installed     = _localPackagesService.IsPackageInstalled(selected.Id);
            var    installIcon   = RequireInstallOrRemoveIcon(installed);
            Action installAction = RequireInstallOrRemoveAction(installed);

            var assemblies = (await _assembliesService.RequireAllAssembliesAsync())
                             .Select(assembly =>
            {
                var icon = ImageHelper.LoadImageFromResource(Paths.AssemblyDefinitionAssetIconResourceName);
                var installedInAssembly = _assembliesService.IsPackageInstalledInAssembly(selected.Id, assembly.Name);
                var version             = installedInAssembly
            ? _assembliesService.RequireInstalledPackageVersion(selected.Id, assembly.Name)
            : null;
                var buttonIcon = RequireInstallOrRemoveIcon(installedInAssembly);
                // ReSharper disable once ConvertToLocalFunction
                Action buttonAction = RequireInstallOrRemoveAction(installedInAssembly, new[] { assembly.Name });
                return(new AssemblyPackageDetailsPresentationModel(icon, assembly.Name, version, buttonIcon, buttonAction));
            });

            var selectedDetails = new PackageDetailsPresentationModel(selected.Id, selected.IsInstalled, selected.Icon, selected.Version,
                                                                      new[] { selected.Version }, selected.Sources.FirstOrDefault() ?? string.Empty, selected.Sources, null,
                                                                      null, installIcon, installAction, null, assemblies);

            _mainWindow.SelectedPackage = selectedDetails;

            if (!string.IsNullOrWhiteSpace(selectedDetails.SelectedSource))
            {
                // delayed adding versions
                await SetVersionsAsync(selectedDetails, selected, _loadDetailsCancellationTokenSource.Token);

                PackageInfoSourceWrapper?detailInfo;

                try
                {
                    detailInfo = await _remotePackagesService.GetPackageInfoAsync(identity, selectedDetails.SelectedSource,
                                                                                  _loadDetailsCancellationTokenSource.Token);
                }
                catch (TaskCanceledException)
                {
                    return;
                }

                if (!detailInfo.HasValue)
                {
                    LogHelper.LogWarning($"Package {identity.Id} with version {identity.Version} not found in online sources");
                    return;
                }

                // delayed adding dependencies and description
                SetDependencies(selectedDetails, detailInfo.Value);
            }
        }
예제 #3
0
 public static void VerifyPtvsdVersion(PtvsdVersionArguments args, PtvsdVersionResponse response)
 {
     if (PackageVersion.TryParse(response.Debugger.Version, out PackageVersion runningVersion))
     {
         var bundledPtvsdVersion = PackageVersion.Parse(PtvsdVersion.Version);
         if (runningVersion.CompareTo(bundledPtvsdVersion) < 0)
         {
             ShowPtvsdVersionMessage(Strings.InstalledPtvsdOutdatedMessage.FormatUI(response.Debugger.Version, PtvsdVersion.Version));
         }
     }
 }
예제 #4
0
 public static void VerifyDebugPyVersion(DebugPyVersionArguments args, DebugPyVersionResponse response)
 {
     if (PackageVersion.TryParse(response.Debugger.Version, out PackageVersion runningVersion))
     {
         var bundledDebugPyVersion = PackageVersion.Parse(DebugPyVersion.Version);
         if (runningVersion.CompareTo(bundledDebugPyVersion) < 0)
         {
             ShowDebuggingErrorMessage(
                 Strings.InstalledDebugPyOutdatedTitle,
                 Strings.InstalledDebugPyOutdatedMessage.FormatUI(response.Debugger.Version, DebugPyVersion.Version),
                 isError: false
                 );
         }
     }
 }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AssetUpgraderAttribute"/> with a range of supported initial version numbers.
        /// </summary>
        /// <param name="name">The dependency name.</param>
        /// <param name="startMinVersion">The minimal initial version number this upgrader can work on.</param>
        /// <param name="targetVersion">The target version number of this upgrader.</param>
        /// <param name="assetUpgraderType">The type of upgrader to instantiate to upgrade the asset.</param>
        public AssetUpgraderAttribute(string name, string startMinVersion, string targetVersion, Type assetUpgraderType)
        {
            Name          = name;
            StartVersion  = PackageVersion.Parse(startMinVersion);
            TargetVersion = PackageVersion.Parse(targetVersion);

            if (!typeof(IAssetUpgrader).IsAssignableFrom(assetUpgraderType))
            {
                throw new ArgumentException(@"The assetUpgraderType must implement IAssetUpgrader interface", nameof(assetUpgraderType));
            }
            if (TargetVersion <= StartVersion)
            {
                throw new ArgumentException(@"The target version is lower or equal to the start version.", nameof(targetVersion));
            }
            AssetUpgraderType = assetUpgraderType;
        }
        private async Task <PackageInfo> ParseNuspecFileAsync(string nuspecFile)
        {
            var xml = (await _fileService.ReadFromFileAsync(nuspecFile, CancellationToken.None)) !;

            xml = xml.RemoveUTF8Preamble();
            var xDoc             = XDocument.Parse(xml);
            var root             = xDoc.Root !;
            var xNamespace       = root.GetDefaultNamespace().NamespaceName;
            var meta             = root.Element(XName.Get("metadata", xNamespace)) !;
            var id               = meta.Element(XName.Get("id", xNamespace)) !.Value !;
            var version          = meta.Element(XName.Get("version", xNamespace)) !.Value !;
            var authors          = meta.Element(XName.Get("authors", xNamespace)) !.Value !;
            var owners           = meta.Element(XName.Get("owners", xNamespace))?.Value;
            var iconPath         = (meta.Element(XName.Get("iconUrl", xNamespace)) ?? meta.Element(XName.Get("icon", xNamespace)))?.Value;
            var description      = meta.Element(XName.Get("description", xNamespace))?.Value;
            var title            = meta.Element(XName.Get("title", xNamespace))?.Value;
            var dependenciesNode = meta.Element(XName.Get("dependencies", xNamespace));
            List <FrameworkGroup>?dependencies = null;

            if (dependenciesNode != null)
            {
                dependencies = new List <FrameworkGroup>();
                var groups = dependenciesNode.Elements(XName.Get("group", xNamespace));

                foreach (var group in groups)
                {
                    var deps = group.Elements(XName.Get("dependency", xNamespace))
                               .Select(e =>
                    {
                        // attribute name without namespace
                        var depId  = e.Attribute("id") !.Value !;
                        var depVer = e.Attribute("version") !.Value !;
                        return(new PackageIdentity(depId, PackageVersion.Parse(depVer)));
                    });

                    // attribute name without namespace
                    var framework = group.Attribute("targetFramework") !.Value;
                    dependencies.Add(new FrameworkGroup(new Framework(framework), deps));
                }
            }

            return(new PackageInfo(title, authors, description, iconPath, owners, null,
                                   new PackageIdentity(id, PackageVersion.Parse(version)), dependencies));
        }
예제 #7
0
                public void Upgrade(AssetMigrationContext context, string dependencyName, PackageVersion currentVersion, PackageVersion targetVersion, YamlMappingNode yamlAssetNode, PackageLoadingAssetFile assetFile)
                {
                    dynamic asset = new DynamicYamlMapping(yamlAssetNode);

                    AssetUpgraderBase.SetSerializableVersion(asset, dependencyName, targetVersion);

                    // Move Test2 to Test4
                    if (currentVersion == PackageVersion.Parse("0.0.2"))
                    {
                        asset.Test4 = asset.Test2;
                        asset.Test2 = DynamicYamlEmpty.Default;
                    }
                    // Move Test3 to Test4
                    else if (currentVersion == PackageVersion.Parse("0.0.3"))
                    {
                        asset.Test4 = asset.Test3;
                        asset.Test3 = DynamicYamlEmpty.Default;
                    }
                }
예제 #8
0
        public ManifestPackage(string location)
        {
            var progress = LiteManagedHttpDownload.Downloader.DownloadToTextAsync(location);

            progress.Wait();
            var          content      = progress.Result;
            StringReader stringReader = new StringReader(content);
            string       line;

            while ((line = stringReader.ReadLine()) != null)
            {
                if (line.StartsWith("FriendlyName="))
                {
                    PackageInformation.FriendlyName = line.Substring("FriendlyName=".Length);
                }
                else if (line.StartsWith("PackageVersion="))
                {
                    PackageInformation.PackageVersion = PackageVersion.Parse(line.Substring("PackageVersion=".Length));
                }
                else if (line.StartsWith("PackageHomePage="))
                {
                    PackageInformation.PackageHomePage = line.Substring("PackageHomePage=".Length);
                }
                else if (line.StartsWith("PackageID="))
                {
                    PackageInformation.PackageID = Guid.Parse(line.Substring("PackageID=".Length));
                }
                else if (line.StartsWith("PackageType="))
                {
                    PackageInformation.PackageType = (PackageType)Enum.Parse(typeof(PackageType), line.Substring("PackageType=".Length));
                }
                else if (line.StartsWith("LicenseURL="))
                {
                    PackageInformation.LicenseURL = line.Substring("LicenseURL=".Length);
                }
                else if (line.StartsWith("InstallationScript="))
                {
                    InstallationScript = line.Substring("InstallationScript=".Length).Replace("{Platform}", SystemEnvironment.currentSystem.ToString());
                }
                //Process...
            }
            PackageInformation.UpdateOrigin = location;
        }
예제 #9
0
            protected override void UpgradeAsset(AssetMigrationContext context, PackageVersion currentVersion, PackageVersion targetVersion, dynamic asset, PackageLoadingAssetFile assetFile)
            {
                // SerializedVersion format changed during renaming upgrade. However, before this was merged back in master, some asset upgrader still with older version numbers were developed.
                // As a result, upgrade is not needed for version 3
                var sprites = asset.Sprites;

                if (sprites == null || currentVersion == PackageVersion.Parse("0.0.3"))
                {
                    return;
                }

                foreach (var sprite in asset.Sprites)
                {
                    if (sprite.Borders == null)
                    {
                        continue;
                    }
                    var y = sprite.Borders.Y ?? 0.0f;
                    sprite.Borders.Y = sprite.Borders.Z ?? 0.0f;
                    sprite.Borders.Z = y;
                }
            }
예제 #10
0
            protected override void UpgradeAsset(AssetMigrationContext context, PackageVersion currentVersion, PackageVersion targetVersion, dynamic asset, PackageLoadingAssetFile assetFile, OverrideUpgraderHint overrideHint)
            {
                // SerializedVersion format changed during renaming upgrade. However, before this was merged back in master, some asset upgrader still with older version numbers were developed.
                var proceduralType = asset.Type;

                if (proceduralType.Node.Tag == "!ConeProceduralModel" && currentVersion != PackageVersion.Parse("0.0.6"))
                {
                    if (proceduralType.LocalOffset == null)
                    {
                        dynamic offset = new DynamicYamlMapping(new YamlMappingNode());
                        offset.AddChild("X", 0.0f);
                        offset.AddChild("Y", 0.5f);
                        offset.AddChild("Z", 0.0f);
                        proceduralType.AddChild("LocalOffset", offset);
                    }
                }
            }
예제 #11
0
            protected override void UpgradeAsset(AssetMigrationContext context, PackageVersion currentVersion, PackageVersion targetVersion, dynamic asset, PackageLoadingAssetFile assetFile, OverrideUpgraderHint overrideHint)
            {
                // SerializedVersion format changed during renaming upgrade. However, before this was merged back in master, some asset upgrader still with older version numbers were developed.
                // However since this upgrader can be reapplied, it is not a problem
                var proceduralType = asset.Type;

                if (proceduralType.Node.Tag == "!CapsuleProceduralModel" && currentVersion != PackageVersion.Parse("0.0.6"))
                {
                    if (proceduralType.Radius == null)
                    {
                        proceduralType.Radius = 0.25f;
                    }
                }
            }
예제 #12
0
        public static bool MigrateAssetIfNeeded(AssetMigrationContext context, PackageLoadingAssetFile loadAsset, string dependencyName, PackageVersion untilVersion = null)
        {
            var assetFullPath = loadAsset.FilePath.FullPath;

            // Determine if asset was Yaml or not
            var assetFileExtension = Path.GetExtension(assetFullPath);

            if (assetFileExtension == null)
            {
                return(false);
            }

            assetFileExtension = assetFileExtension.ToLowerInvariant();

            var serializer = AssetFileSerializer.FindSerializer(assetFileExtension);

            if (!(serializer is YamlAssetSerializer))
            {
                return(false);
            }

            // We've got a Yaml asset, let's get expected and serialized versions
            var            serializedVersion = PackageVersion.Zero;
            PackageVersion expectedVersion;
            Type           assetType;

            // Read from Yaml file the asset version and its type (to get expected version)
            // Note: It tries to read as few as possible (SerializedVersion is expected to be right after Id, so it shouldn't try to read further than that)
            using (var assetStream = loadAsset.OpenStream())
                using (var streamReader = new StreamReader(assetStream))
                {
                    var yamlEventReader = new EventReader(new Parser(streamReader));

                    // Skip header
                    yamlEventReader.Expect <StreamStart>();
                    yamlEventReader.Expect <DocumentStart>();
                    var mappingStart = yamlEventReader.Expect <MappingStart>();

                    var  tagTypeRegistry = AssetYamlSerializer.Default.GetSerializerSettings().TagTypeRegistry;
                    bool typeAliased;
                    assetType = tagTypeRegistry.TypeFromTag(mappingStart.Tag, out typeAliased);

                    var expectedVersions = AssetRegistry.GetCurrentFormatVersions(assetType);
                    expectedVersion = expectedVersions?.FirstOrDefault(x => x.Key == dependencyName).Value ?? PackageVersion.Zero;

                    Scalar assetKey;
                    while ((assetKey = yamlEventReader.Allow <Scalar>()) != null)
                    {
                        // Only allow Id before SerializedVersion
                        if (assetKey.Value == nameof(Asset.Id))
                        {
                            yamlEventReader.Skip();
                        }
                        else if (assetKey.Value == nameof(Asset.SerializedVersion))
                        {
                            // Check for old format: only a scalar
                            var scalarVersion = yamlEventReader.Allow <Scalar>();
                            if (scalarVersion != null)
                            {
                                serializedVersion = PackageVersion.Parse("0.0." + Convert.ToInt32(scalarVersion.Value, CultureInfo.InvariantCulture));

                                // Let's update to new format
                                using (var yamlAsset = loadAsset.AsYamlAsset())
                                {
                                    yamlAsset.DynamicRootNode.RemoveChild(nameof(Asset.SerializedVersion));
                                    AssetUpgraderBase.SetSerializableVersion(yamlAsset.DynamicRootNode, dependencyName, serializedVersion);

                                    var baseBranch = yamlAsset.DynamicRootNode["~Base"];
                                    if (baseBranch != null)
                                    {
                                        var baseAsset = baseBranch["Asset"];
                                        if (baseAsset != null)
                                        {
                                            baseAsset.RemoveChild(nameof(Asset.SerializedVersion));
                                            AssetUpgraderBase.SetSerializableVersion(baseAsset, dependencyName, serializedVersion);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                // New format: package => version mapping
                                yamlEventReader.Expect <MappingStart>();

                                while (!yamlEventReader.Accept <MappingEnd>())
                                {
                                    var packageName    = yamlEventReader.Expect <Scalar>().Value;
                                    var packageVersion = PackageVersion.Parse(yamlEventReader.Expect <Scalar>().Value);

                                    // For now, we handle only one dependency at a time
                                    if (packageName == dependencyName)
                                    {
                                        serializedVersion = packageVersion;
                                    }
                                }

                                yamlEventReader.Expect <MappingEnd>();
                            }
                            break;
                        }
                        else
                        {
                            // If anything else than Id or SerializedVersion, let's stop
                            break;
                        }
                    }
                }

            if (serializedVersion > expectedVersion)
            {
                // Try to open an asset newer than what we support (probably generated by a newer Stride)
                throw new InvalidOperationException($"Asset of type {assetType} has been serialized with newer version {serializedVersion}, but only version {expectedVersion} is supported. Was this asset created with a newer version of Stride?");
            }

            if (serializedVersion < expectedVersion)
            {
                // Perform asset upgrade
                context.Log.Verbose($"{Path.GetFullPath(assetFullPath)} needs update, from version {serializedVersion} to version {expectedVersion}");

                using (var yamlAsset = loadAsset.AsYamlAsset())
                {
                    var yamlRootNode = yamlAsset.RootNode;

                    // Check if there is any asset updater
                    var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType, dependencyName);
                    if (assetUpgraders == null)
                    {
                        throw new InvalidOperationException($"Asset of type {assetType} should be updated from version {serializedVersion} to {expectedVersion}, but no asset migration path was found");
                    }

                    // Instantiate asset updaters
                    var currentVersion = serializedVersion;
                    while (currentVersion != expectedVersion)
                    {
                        PackageVersion targetVersion;
                        // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error.
                        var upgrader = assetUpgraders.GetUpgrader(currentVersion, out targetVersion);

                        // Stop if the next version would be higher than what is expected
                        if (untilVersion != null && targetVersion > untilVersion)
                        {
                            break;
                        }

                        upgrader.Upgrade(context, dependencyName, currentVersion, targetVersion, yamlRootNode, loadAsset);
                        currentVersion = targetVersion;
                    }

                    // Make sure asset is updated to latest version
                    YamlNode       serializedVersionNode;
                    PackageVersion newSerializedVersion = null;
                    if (yamlRootNode.Children.TryGetValue(new YamlScalarNode(nameof(Asset.SerializedVersion)), out serializedVersionNode))
                    {
                        var newSerializedVersionForDefaultPackage = ((YamlMappingNode)serializedVersionNode).Children[new YamlScalarNode(dependencyName)];
                        newSerializedVersion = PackageVersion.Parse(((YamlScalarNode)newSerializedVersionForDefaultPackage).Value);
                    }

                    if (untilVersion == null && newSerializedVersion != expectedVersion)
                    {
                        throw new InvalidOperationException($"Asset of type {assetType} was migrated, but still its new version {newSerializedVersion} doesn't match expected version {expectedVersion}.");
                    }

                    context.Log.Verbose($"{Path.GetFullPath(assetFullPath)} updated from version {serializedVersion} to version {expectedVersion}");
                }

                return(true);
            }

            return(false);
        }
예제 #13
0
        private static async Task UpdateLauncherFiles(IDispatcherService dispatcher, IDialogService dialogService, NugetStore store, CancellationToken cancellationToken)
        {
            var version          = new PackageVersion(Version);
            var productAttribute = (typeof(SelfUpdater).Assembly).GetCustomAttribute <AssemblyProductAttribute>();
            var packageId        = productAttribute.Product;
            var packages         = (await store.GetUpdates(new PackageName(packageId, version), true, true, cancellationToken)).OrderBy(x => x.Version);

            try
            {
                // First, check if there is a package forcing us to download new installer
                const string ReinstallUrlPattern = @"force-reinstall:\s*(\S+)\s*(\S+)";
                var          reinstallPackage    = packages.LastOrDefault(x => x.Version > version && Regex.IsMatch(x.Description, ReinstallUrlPattern));
                if (reinstallPackage != null)
                {
                    var regexMatch     = Regex.Match(reinstallPackage.Description, ReinstallUrlPattern);
                    var minimumVersion = PackageVersion.Parse(regexMatch.Groups[1].Value);
                    if (version < minimumVersion)
                    {
                        var installerDownloadUrl = regexMatch.Groups[2].Value;
                        await DownloadAndInstallNewVersion(dispatcher, dialogService, installerDownloadUrl);

                        return;
                    }
                }
            }
            catch (Exception e)
            {
                await dialogService.MessageBox(string.Format(Strings.NewVersionDownloadError, e.Message), MessageBoxButton.OK, MessageBoxImage.Error);
            }

            // If there is a mandatory intermediate upgrade, take it, otherwise update straight to latest version
            var package = (packages.FirstOrDefault(x => x.Version > version && x.Version.SpecialVersion == "req") ?? packages.LastOrDefault());

            // Check to see if an update is needed
            if (package != null && version < new PackageVersion(package.Version.Version, package.Version.SpecialVersion))
            {
                var windowCreated = new TaskCompletionSource <SelfUpdateWindow>();
                var mainWindow    = dispatcher.Invoke(() => Application.Current.MainWindow as LauncherWindow);
                if (mainWindow == null)
                {
                    throw new ApplicationException("Update requested without a Launcher Window. Cannot continue!");
                }

                dispatcher.InvokeAsync(() =>
                {
                    selfUpdateWindow = new SelfUpdateWindow {
                        Owner = mainWindow
                    };
                    windowCreated.SetResult(selfUpdateWindow);
                    selfUpdateWindow.ShowDialog();
                }).Forget();

                var movedFiles = new List <string>();

                // Download package
                var installedPackage = await store.InstallPackage(package.Id, package.Version, null);

                // Copy files from tools\ to the current directory
                var inputFiles = installedPackage.GetFiles();

                var window = windowCreated.Task.Result;
                dispatcher.Invoke(window.LockWindow);

                // TODO: We should get list of previous files from nuspec (store it as a resource and open it with NuGet API maybe?)
                // TODO: For now, we deal only with the App.config file since we won't be able to fix it afterward.
                var          exeLocation   = Launcher.GetExecutablePath();
                var          exeDirectory  = Path.GetDirectoryName(exeLocation);
                const string directoryRoot = "tools/"; // Important!: this is matching where files are store in the nuspec
                try
                {
                    if (File.Exists(exeLocation))
                    {
                        Move(exeLocation, exeLocation + ".old");
                        movedFiles.Add(exeLocation);
                    }
                    var configLocation = exeLocation + ".config";
                    if (File.Exists(configLocation))
                    {
                        Move(configLocation, configLocation + ".old");
                        movedFiles.Add(configLocation);
                    }
                    foreach (var file in inputFiles.Where(file => file.Path.StartsWith(directoryRoot) && !file.Path.EndsWith("/")))
                    {
                        var fileName = Path.Combine(exeDirectory, file.Path.Substring(directoryRoot.Length));

                        // Move previous files to .old
                        if (File.Exists(fileName))
                        {
                            Move(fileName, fileName + ".old");
                            movedFiles.Add(fileName);
                        }

                        // Update the file
                        UpdateFile(fileName, file);
                    }
                }
                catch (Exception)
                {
                    // Revert all olds files if a file didn't work well
                    foreach (var oldFile in movedFiles)
                    {
                        Move(oldFile + ".old", oldFile);
                    }
                    throw;
                }


                // Remove .old files
                foreach (var oldFile in movedFiles)
                {
                    try
                    {
                        var renamedPath = oldFile + ".old";

                        if (File.Exists(renamedPath))
                        {
                            File.Delete(renamedPath);
                        }
                    }
                    catch (Exception)
                    {
                        // All the files have been replaced, we let it go even if we cannot remove all the old files.
                    }
                }

                // Clean cache from files obtain via package.GetFiles above.
                store.PurgeCache();

                dispatcher.Invoke(RestartApplication);
            }
        }
예제 #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AssetFormatVersionAttribute"/> class.
 /// </summary>
 /// <param name="name">The dependency name.</param>
 /// <param name="version">The current format version of this asset.</param>
 /// <param name="minUpgradableVersion">The minimum format version that supports upgrade for this asset.</param>
 public AssetFormatVersionAttribute(string name, string version, string minUpgradableVersion = null)
 {
     Name    = name;
     Version = PackageVersion.Parse(version);
     MinUpgradableVersion = PackageVersion.Parse(minUpgradableVersion ?? "0");
 }
예제 #15
0
        public override bool Upgrade(PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, IList <PackageLoadingAssetFile> assetFiles)
        {
            if (dependency.Version.MinVersion < new PackageVersion("1.5.0-alpha01"))
            {
                RunAssetUpgradersUntilVersion(log, dependentPackage, XenkoConfig.PackageName, assetFiles, PackageVersion.Parse("1.5.0-alpha01"));
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.5.0-alpha02"))
            {
                // Ideally, this should be part of asset upgrader but we can't upgrade multiple assets at once yet

                var modelAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkm3d").Select(x => x.AsYamlAsset()).ToArray();
                var animAssets  = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkanim").Select(x => x.AsYamlAsset()).ToArray();
                var sceneAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkscene").Select(x => x.AsYamlAsset()).ToArray();

                // Select models with at least two nodes
                var modelAssetsWithSekeleton = modelAssets
                                               .Where(model => ((IEnumerable)model.DynamicRootNode.Nodes).Cast <object>().Count() > 1).ToArray();

                var animToModelMapping = new Dictionary <PackageLoadingAssetFile.YamlAsset, PackageLoadingAssetFile.YamlAsset>();

                // Find associations in scene
                foreach (var sceneAsset in sceneAssets)
                {
                    var hierarchy = sceneAsset.DynamicRootNode.Hierarchy;
                    foreach (dynamic entity in hierarchy.Entities)
                    {
                        var components         = entity.Entity.Components;
                        var animationComponent = components["AnimationComponent.Key"];
                        var model = components["ModelComponent.Key"]?.Model;
                        if (animationComponent != null && model != null)
                        {
                            var modelReference = DynamicYamlExtensions.ConvertTo <AssetReference>(model);
                            var modelAsset     = modelAssetsWithSekeleton.FirstOrDefault(x => x.Asset.AssetPath == modelReference.Location);

                            foreach (var animation in animationComponent.Animations)
                            {
                                var animationReference = DynamicYamlExtensions.ConvertTo <AssetReference>(animation.Value);
                                var animationAsset     = animAssets.FirstOrDefault(x => x.Asset.AssetPath == animationReference.Location);

                                if (modelAsset != null && animationAsset != null)
                                {
                                    animToModelMapping[animationAsset] = modelAsset;
                                }
                            }
                        }
                    }
                }

                // Find associations when sharing same source file
                foreach (var animationAsset in animAssets)
                {
                    // Comparing absolute path of assets
                    var modelAsset = modelAssetsWithSekeleton.FirstOrDefault(
                        x => UPath.Combine(animationAsset.Asset.AssetPath.GetParent(), new UFile((string)animationAsset.DynamicRootNode.Source))
                        == UPath.Combine(x.Asset.AssetPath.GetParent(), new UFile((string)x.DynamicRootNode.Source)));
                    if (modelAsset != null)
                    {
                        animToModelMapping[animationAsset] = modelAsset;
                    }
                }

                var modelToSkeletonMapping = new Dictionary <PackageLoadingAssetFile.YamlAsset, PackageLoadingAssetFile.YamlAsset>();

                // For each model asset, create skeleton assets
                foreach (var modelAsset in modelAssetsWithSekeleton)
                {
                    var skeletonAsset = new PackageLoadingAssetFile(modelAsset.Asset.FilePath.GetFullPathWithoutExtension() + " Skeleton.xkskel", modelAsset.Asset.SourceFolder)
                    {
                        AssetContent = System.Text.Encoding.UTF8.GetBytes("!Skeleton\r\nId: " + Guid.NewGuid())
                    };

                    using (var skeletonAssetYaml = skeletonAsset.AsYamlAsset())
                    {
                        // Set source
                        skeletonAssetYaml.DynamicRootNode.Source     = modelAsset.DynamicRootNode.Source;
                        skeletonAssetYaml.DynamicRootNode.SourceHash = modelAsset.DynamicRootNode.SourceHash;

                        // To be on the safe side, mark everything as preserved
                        var nodes = modelAsset.DynamicRootNode.Nodes;
                        foreach (var node in nodes)
                        {
                            node.Preserve = true;
                        }

                        skeletonAssetYaml.DynamicRootNode.Nodes       = nodes;
                        skeletonAssetYaml.DynamicRootNode.ScaleImport = modelAsset.DynamicRootNode.ScaleImport;

                        // Update model to point to this skeleton
                        modelAsset.DynamicRootNode.Skeleton = new AssetReference(AssetId.Parse((string)skeletonAssetYaml.DynamicRootNode.Id), skeletonAsset.AssetPath.MakeRelative(modelAsset.Asset.AssetPath.GetParent()));
                        modelToSkeletonMapping.Add(modelAsset, skeletonAssetYaml);
                    }

                    assetFiles.Add(skeletonAsset);
                }

                // Update animation to point to skeleton, and set preview default model
                foreach (var animToModelEntry in animToModelMapping)
                {
                    var animationAsset = animToModelEntry.Key;
                    var modelAsset     = animToModelEntry.Value;

                    var skeletonAsset = modelToSkeletonMapping[modelAsset];
                    animationAsset.DynamicRootNode.Skeleton     = new AssetReference(AssetId.Parse((string)skeletonAsset.DynamicRootNode.Id), skeletonAsset.Asset.AssetPath.MakeRelative(animationAsset.Asset.AssetPath.GetParent()));
                    animationAsset.DynamicRootNode.PreviewModel = new AssetReference(AssetId.Parse((string)modelAsset.DynamicRootNode.Id), modelAsset.Asset.AssetPath.MakeRelative(animationAsset.Asset.AssetPath.GetParent()));
                }

                // Remove Nodes from models
                foreach (var modelAsset in modelAssets)
                {
                    modelAsset.DynamicRootNode.Nodes = DynamicYamlEmpty.Default;
                    modelAsset.DynamicRootNode["~Base"].Asset.Nodes = DynamicYamlEmpty.Default;
                }

                // Save back
                foreach (var modelAsset in modelAssets)
                {
                    modelAsset.Dispose();
                }
                foreach (var animAsset in animAssets)
                {
                    animAsset.Dispose();
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.6.0-beta"))
            {
                // Delete EffectLogAsset
                foreach (var assetFile in assetFiles)
                {
                    if (assetFile.FilePath.GetFileName() == EffectLogAsset.DefaultFile)
                    {
                        assetFile.Deleted = true;
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.7.0-alpha02"))
            {
                foreach (var assetFile in assetFiles)
                {
                    if (!IsYamlAsset(assetFile))
                    {
                        continue;
                    }

                    using (var assetYaml = assetFile.AsYamlAsset())
                    {
                        if (assetYaml == null)
                        {
                            continue;
                        }

                        var sourceNode     = assetYaml.DynamicRootNode.Source;
                        var sourceHashNode = assetYaml.DynamicRootNode.SourceHash;
                        if (sourceHashNode != null)
                        {
                            var source     = DynamicYamlExtensions.ConvertTo <UFile>(sourceNode);
                            var sourceHash = DynamicYamlExtensions.ConvertTo <ObjectId>(sourceHashNode);
                            var dictionary = new Dictionary <UFile, ObjectId> {
                                { source, sourceHash }
                            };
                            var yamlDic = DynamicYamlExtensions.ConvertFrom(dictionary);
                            yamlDic.Node.Tag = null;
                            assetYaml.DynamicRootNode["~SourceHashes"] = yamlDic;
                            assetYaml.DynamicRootNode.SourceHash       = DynamicYamlEmpty.Default;
                        }
                        assetYaml.DynamicRootNode.ImporterId           = DynamicYamlEmpty.Default;
                        assetYaml.DynamicRootNode.SourceKeepSideBySide = DynamicYamlEmpty.Default;

                        var assetBase = assetYaml.DynamicRootNode["~Base"];
                        if (assetBase != null)
                        {
                            if (assetBase.Location == "--import--")
                            {
                                assetYaml.DynamicRootNode["~Base"] = DynamicYamlEmpty.Default;
                            }
                        }
                    }
                }
            }

            //Audio refactor
            if (dependency.Version.MinVersion < new PackageVersion("1.7.0-alpha03"))
            {
                var audioAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xksnd").Select(x => x.AsYamlAsset()).ToArray();
                foreach (var assetFile in audioAssets)
                {
                    //dispose will save back
                    using (var assetYaml = assetFile)
                    {
                        if (assetYaml == null)
                        {
                            continue;
                        }

                        if (assetYaml.RootNode.Tag == "!SoundMusic")
                        {
                            assetYaml.RootNode.Tag = "!Sound";
                            assetYaml.DynamicRootNode.Spatialized    = false;
                            assetYaml.DynamicRootNode.StreamFromDisk = true;
                        }
                        else
                        {
                            assetYaml.RootNode.Tag = "!Sound";
                            assetYaml.DynamicRootNode.Spatialized    = true;
                            assetYaml.DynamicRootNode.StreamFromDisk = false;
                        }
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.7.0-alpha03"))
            {
                // Delete EffectLogAsset (now, most of it is auto generated automatically by drawing one frame of the game)
                foreach (var assetFile in assetFiles)
                {
                    if (assetFile.FilePath.GetFileName() == EffectLogAsset.DefaultFile)
                    {
                        assetFile.Deleted = true;
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.8.4-beta"))
            {
                // Add new generic parameter of MaterialSurfaceNormalMap to effect logs
                var regex = new Regex(@"(?<=ClassName:\s+MaterialSurfaceNormalMap\s+GenericArguments:\s+\[[^\]]*)(?=\])");
                foreach (var assetFile in assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkeffectlog"))
                {
                    var filePath = assetFile.FilePath;

                    // Load asset data, so the renamed file will have it's AssetContent set
                    if (assetFile.AssetContent == null)
                    {
                        assetFile.AssetContent = File.ReadAllBytes(filePath);
                    }

                    var sourceText      = System.Text.Encoding.UTF8.GetString(assetFile.AssetContent);
                    var newSourceText   = regex.Replace(sourceText, ", true");
                    var newAssetContent = System.Text.Encoding.UTF8.GetBytes(newSourceText);

                    if (newSourceText != sourceText)
                    {
                        assetFile.AssetContent = newAssetContent;
                    }

                    //File.WriteAllBytes(newFileName, newAssetContent);
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.9.0-beta"))
            {
                foreach (var assetFile in assetFiles)
                {
                    if (!IsYamlAsset(assetFile))
                    {
                        continue;
                    }

                    // This upgrader will also mark every yaml asset as dirty. We want to re-save everything with the new serialization system
                    using (var assetYaml = assetFile.AsYamlAsset())
                    {
                        if (assetYaml == null)
                        {
                            continue;
                        }

                        try
                        {
                            if (assetYaml.DynamicRootNode["~Base"] != null)
                            {
                                var location = ((YamlScalarNode)assetYaml.DynamicRootNode["~Base"].Location.Node).Value;
                                if (location != "--import--")
                                {
                                    var id       = ((YamlScalarNode)assetYaml.DynamicRootNode["~Base"].Asset.Id.Node).Value;
                                    var assetUrl = $"{id}:{location}";
                                    assetYaml.DynamicRootNode["Archetype"] = assetUrl;
                                }
                                assetYaml.DynamicRootNode["~Base"] = DynamicYamlEmpty.Default;
                            }
                        }
                        catch
                        (Exception e)
                        {
                            e.Ignore();
                        }
                    }
                }
            }

            return(true);
        }
예제 #16
0
 public MyUpgradedAsset(int version)
 {
     SerializedVersion["TestPackage"] = PackageVersion.Parse("0.0." + version);
 }
예제 #17
0
        public override bool Upgrade(PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, IList <PackageLoadingAssetFile> assetFiles)
        {
            // Paradox 1.1 projects didn't have their dependency properly updated (they might have been marked as 1.0).
            // We know they are 1.1 only because there is a .props file.
            // This check shouldn't be necessary from 1.2.
            var packagePath   = dependentPackage.FullPath;
            var propsFilePath = UPath.Combine(packagePath.GetParent(), (UFile)(packagePath.GetFileName() + ".props"));

            if (!File.Exists(propsFilePath) && dependency.Version.MinVersion < new PackageVersion("1.1.0-beta"))
            {
                log.Error("Can't upgrade old projects from {0} 1.0 to 1.1", dependency.Name);
                return(false);
            }

            // Nothing to do for now, most of the work is already done by individual asset upgraders
            // We can later add logic here for package-wide upgrades (i.e. GameSettingsAsset)
            if (dependency.Version.MinVersion < new PackageVersion("1.2.0-beta"))
            {
                // UIImageGroups and SpriteGroups asset have been merged into a single SpriteSheet => rename the assets and modify the tag
                var uiImageGroups = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".pdxuiimage");
                var spritesGroups = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".pdxsprite");
                RenameAndChangeTag(assetFiles, uiImageGroups, "!UIImageGroup");
                RenameAndChangeTag(assetFiles, spritesGroups, "!SpriteGroup");
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.3.0-alpha01"))
            {
                // Create GameSettingsAsset
                GameSettingsAsset.UpgraderVersion130.Upgrade(session, log, dependentPackage, dependency, dependencyPackage, assetFiles);
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.3.0-alpha02"))
            {
                // Delete EffectLogAsset
                foreach (var assetFile in assetFiles)
                {
                    if (assetFile.FilePath.GetFileName() == EffectLogAsset.DefaultFile)
                    {
                        assetFile.Deleted = true;
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.4.0-beta"))
            {
                // Update file extensions with Xenko prefix
                var legacyAssets = from assetFile in assetFiles
                                   where !assetFile.Deleted
                                   let extension = assetFile.FilePath.GetFileExtension()
                                                   where extension.StartsWith(".pdx")
                                                   select new { AssetFile = assetFile, NewExtension = ".xk" + extension.Substring(4) };

                foreach (var legacyAsset in legacyAssets.ToArray())
                {
                    var assetFile = legacyAsset.AssetFile;
                    var filePath  = assetFile.FilePath;

                    // Load asset data, so the renamed file will have it's AssetContent set
                    if (assetFile.AssetContent == null)
                    {
                        assetFile.AssetContent = File.ReadAllBytes(filePath);
                    }

                    // Change legacy namespaces and default effect names in all shader source files
                    // TODO: Use syntax analysis? What about shaders referenced in other assets?
                    if (legacyAsset.NewExtension == ".xksl" || legacyAsset.NewExtension == ".xkfx" || legacyAsset.NewExtension == ".xkeffectlog")
                    {
                        var sourceText      = System.Text.Encoding.UTF8.GetString(assetFile.AssetContent);
                        var newSourceText   = sourceText.Replace("Paradox", "Xenko");
                        var newAssetContent = System.Text.Encoding.UTF8.GetBytes(newSourceText);

                        if (newSourceText != sourceText)
                        {
                            assetFile.AssetContent = newAssetContent;
                        }

                        // Write SourceCodeAssets to new file, as they are serialized differently
                        // TODO: Handle SourceCodeAssets properly (should probably force saving)
                        var newFileName = new UFile(filePath.FullPath.Replace(filePath.GetFileExtension(), legacyAsset.NewExtension));
                        File.WriteAllBytes(newFileName, newAssetContent);
                    }

                    // Create asset copy with new extension
                    ChangeFileExtension(assetFiles, assetFile, legacyAsset.NewExtension);
                }

                // Force loading of user settings with old extension
                var userSettings = dependentPackage.UserSettings;

                // Change package extension
                dependentPackage.FullPath = new UFile(dependentPackage.FullPath.GetFullPathWithoutExtension(), Package.PackageFileExtension);

                // Make sure all assets are upgraded
                RunAssetUpgradersUntilVersion(log, dependentPackage, XenkoConfig.PackageName, assetFiles, PackageVersion.Parse("1.4.0-beta"));
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.5.0-alpha01"))
            {
                RunAssetUpgradersUntilVersion(log, dependentPackage, XenkoConfig.PackageName, assetFiles, PackageVersion.Parse("1.5.0-alpha01"));
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.5.0-alpha02"))
            {
                // Ideally, this should be part of asset upgrader but we can't upgrade multiple assets at once yet

                var modelAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkm3d").Select(x => x.AsYamlAsset()).ToArray();
                var animAssets  = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkanim").Select(x => x.AsYamlAsset()).ToArray();
                var sceneAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkscene").Select(x => x.AsYamlAsset()).ToArray();

                // Select models with at least two nodes
                var modelAssetsWithSekeleton = modelAssets
                                               .Where(model => ((IEnumerable)model.DynamicRootNode.Nodes).Cast <object>().Count() > 1).ToArray();

                var animToModelMapping = new Dictionary <PackageLoadingAssetFile.YamlAsset, PackageLoadingAssetFile.YamlAsset>();

                // Find associations in scene
                foreach (var sceneAsset in sceneAssets)
                {
                    var hierarchy = sceneAsset.DynamicRootNode.Hierarchy;
                    foreach (dynamic entity in hierarchy.Entities)
                    {
                        var components         = entity.Entity.Components;
                        var animationComponent = components["AnimationComponent.Key"];
                        var model = components["ModelComponent.Key"]?.Model;
                        if (animationComponent != null && model != null)
                        {
                            var modelReference = DynamicYamlExtensions.ConvertTo <AssetReference <Asset> >(model);
                            var modelAsset     = modelAssetsWithSekeleton.FirstOrDefault(x => x.Asset.AssetPath == modelReference.Location);

                            foreach (var animation in animationComponent.Animations)
                            {
                                var animationReference = DynamicYamlExtensions.ConvertTo <AssetReference <Asset> >(animation.Value);
                                var animationAsset     = animAssets.FirstOrDefault(x => x.Asset.AssetPath == animationReference.Location);

                                if (modelAsset != null && animationAsset != null)
                                {
                                    animToModelMapping[animationAsset] = modelAsset;
                                }
                            }
                        }
                    }
                }

                // Find associations when sharing same source file
                foreach (var animationAsset in animAssets)
                {
                    // Comparing absolute path of assets
                    var modelAsset = modelAssetsWithSekeleton.FirstOrDefault(
                        x => UPath.Combine(animationAsset.Asset.AssetPath.GetParent(), new UFile((string)animationAsset.DynamicRootNode.Source))
                        == UPath.Combine(x.Asset.AssetPath.GetParent(), new UFile((string)x.DynamicRootNode.Source)));
                    if (modelAsset != null)
                    {
                        animToModelMapping[animationAsset] = modelAsset;
                    }
                }

                var modelToSkeletonMapping = new Dictionary <PackageLoadingAssetFile.YamlAsset, PackageLoadingAssetFile.YamlAsset>();

                // For each model asset, create skeleton assets
                foreach (var modelAsset in modelAssetsWithSekeleton)
                {
                    var skeletonAsset = new PackageLoadingAssetFile(modelAsset.Asset.FilePath.GetFullPathWithoutExtension() + " Skeleton.xkskel", modelAsset.Asset.SourceFolder)
                    {
                        AssetContent = System.Text.Encoding.UTF8.GetBytes("!Skeleton\r\nId: " + Guid.NewGuid())
                    };

                    using (var skeletonAssetYaml = skeletonAsset.AsYamlAsset())
                    {
                        // Set source
                        skeletonAssetYaml.DynamicRootNode.Source     = modelAsset.DynamicRootNode.Source;
                        skeletonAssetYaml.DynamicRootNode.SourceHash = modelAsset.DynamicRootNode.SourceHash;

                        // To be on the safe side, mark everything as preserved
                        var nodes = modelAsset.DynamicRootNode.Nodes;
                        foreach (var node in nodes)
                        {
                            node.Preserve = true;
                        }

                        skeletonAssetYaml.DynamicRootNode.Nodes       = nodes;
                        skeletonAssetYaml.DynamicRootNode.ScaleImport = modelAsset.DynamicRootNode.ScaleImport;

                        // Update model to point to this skeleton
                        modelAsset.DynamicRootNode.Skeleton = new AssetReference <Asset>(Guid.Parse((string)skeletonAssetYaml.DynamicRootNode.Id), skeletonAsset.AssetPath.MakeRelative(modelAsset.Asset.AssetPath.GetParent()));
                        modelToSkeletonMapping.Add(modelAsset, skeletonAssetYaml);
                    }

                    assetFiles.Add(skeletonAsset);
                }

                // Update animation to point to skeleton, and set preview default model
                foreach (var animToModelEntry in animToModelMapping)
                {
                    var animationAsset = animToModelEntry.Key;
                    var modelAsset     = animToModelEntry.Value;

                    var skeletonAsset = modelToSkeletonMapping[modelAsset];
                    animationAsset.DynamicRootNode.Skeleton     = new AssetReference <Asset>(Guid.Parse((string)skeletonAsset.DynamicRootNode.Id), skeletonAsset.Asset.AssetPath.MakeRelative(animationAsset.Asset.AssetPath.GetParent()));
                    animationAsset.DynamicRootNode.PreviewModel = new AssetReference <Asset>(Guid.Parse((string)modelAsset.DynamicRootNode.Id), modelAsset.Asset.AssetPath.MakeRelative(animationAsset.Asset.AssetPath.GetParent()));
                }

                // Remove Nodes from models
                foreach (var modelAsset in modelAssets)
                {
                    modelAsset.DynamicRootNode.Nodes = DynamicYamlEmpty.Default;
                    modelAsset.DynamicRootNode[Asset.BaseProperty].Asset.Nodes = DynamicYamlEmpty.Default;
                }

                // Save back
                foreach (var modelAsset in modelAssets)
                {
                    modelAsset.Dispose();
                }
                foreach (var animAsset in animAssets)
                {
                    animAsset.Dispose();
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.6.0-beta"))
            {
                // Delete EffectLogAsset
                foreach (var assetFile in assetFiles)
                {
                    if (assetFile.FilePath.GetFileName() == EffectLogAsset.DefaultFile)
                    {
                        assetFile.Deleted = true;
                    }
                }
            }

            return(true);
        }