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; } } } } }
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); } }
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)); } } }
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 ); } } }
/// <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)); }
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; } }
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; }
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; } }
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); } } }
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; } } }
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); }
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); } }
/// <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"); }
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); }
public MyUpgradedAsset(int version) { SerializedVersion["TestPackage"] = PackageVersion.Parse("0.0." + version); }
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); }