public void AssetIdRoundTripping() { var failed = new List <(AssetId, string, string)>(); foreach (var assetType in Enum.GetValues(typeof(AssetType)).OfType <AssetType>()) { foreach (var id in AssetMapping.Global.EnumerateAssetsOfType(assetType)) { var asString = id.ToString(); try { var roundTripped = AssetId.Parse(asString); if (roundTripped != id) { failed.Add((id, asString, roundTripped.ToString())); } } catch (Exception e) { failed.Add((id, asString, e.ToString())); } } } Assert.Empty(failed); Assert.Equal("Gold.0", new AssetId(AssetType.Gold).ToString()); Assert.Equal("Rations.0", new AssetId(AssetType.Rations).ToString()); Assert.Equal(new AssetId(AssetType.Gold), AssetId.Parse("Gold.0")); Assert.Equal(new AssetId(AssetType.Rations), AssetId.Parse("Rations.0")); }
public static AssetId PropId(ITiledPropertySource source, string key, bool required = false) { var id = AssetId.Parse(PropString(source, key)); if (required && id.IsNone) { throw new FormatException($"Property \"{key}\" was invalid or not found"); } return(id); }
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); }
static AssetId PropId(Map map, string key) => AssetId.Parse(PropString(map, key));
public void ExecuteFile(string path, bool require = true) { ExecuteFile(AssetId.Parse(path), require); }