public void TestIsDirectoryOnly() { Assert.False(new UFile("/a/b/c.txt").IsDirectoryOnly); var dirPath = new UDirectory("/a/b/c"); Assert.True(dirPath.IsDirectoryOnly); Assert.AreEqual("/a/b/c", dirPath.GetDirectory()); var filePath = new UFile("/test.txt"); Assert.AreEqual("/", filePath.GetDirectory()); Assert.AreEqual("test.txt", filePath.GetFileNameWithExtension()); }
public static SolutionProject GenerateTemplate(TemplateGeneratorParameters parameters, ICollection <SelectedSolutionPlatform> platforms, UFile templateRelativePath, string projectName, PlatformType platformType, GraphicsPlatform?graphicsPlatform, ProjectType projectType, DisplayOrientation orientation, Guid?projectGuid = null) { AddOption(parameters, "Platforms", platforms.Select(x => x.Platform).ToList()); AddOption(parameters, "CurrentPlatform", platformType); AddOption(parameters, "Orientation", orientation); List <string> generatedFiles; var project = GenerateTemplate(parameters, templateRelativePath, projectName, platformType, graphicsPlatform, projectType, out generatedFiles, projectGuid); // Special case for sdfx files foreach (var file in generatedFiles) { if (file.EndsWith(".sdfx")) { ConvertXkfxToCSharp(file); } } return(project); }
public static ProjectTemplate PrepareTemplate(TemplateGeneratorParameters parameters, Package package, UFile templateRelativePath, PlatformType platformType, GraphicsPlatform?graphicsPlatform, ProjectType projectType) { if (platformType != PlatformType.Shared && !graphicsPlatform.HasValue) { throw new ArgumentException(@"Expecting a value for GraphicsPlatform when platformType is specified", nameof(graphicsPlatform)); } var rootTemplateDir = parameters.Description.TemplateDirectory; var templateFilePath = UPath.Combine(rootTemplateDir, templateRelativePath); var projectTemplate = ProjectTemplate.Load(templateFilePath); // TODO assemblies are not configurable from the outside projectTemplate.Assemblies.Add(typeof(ProjectType).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(StrideConfig).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(GraphicsPlatform).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(DisplayOrientation).Assembly.FullName); AddOption(parameters, "Package", package); AddOption(parameters, "PackageName", package.Meta.Name); // PackageNameCode, same as PackageName without '.' and ' '. AddOption(parameters, "PackageNameCode", package.Meta.Name.Replace(" ", string.Empty).Replace(".", string.Empty)); AddOption(parameters, "PackageDisplayName", package.Meta.Title ?? package.Meta.Name); // Escape illegal characters for the short name AddOption(parameters, "PackageNameShort", Utilities.BuildValidClassName(package.Meta.Name.Replace(" ", string.Empty))); AddOption(parameters, "CurrentPlatform", platformType); if (platformType != PlatformType.Shared) { AddOption(parameters, "CurrentGraphicsPlatform", graphicsPlatform); } AddOption(parameters, "ProjectType", projectType); AddOption(parameters, "Namespace", parameters.Namespace ?? Utilities.BuildValidNamespaceName(package.Meta.Name)); if (platformType == PlatformType.Windows) { var isNETCore = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); AddOption(parameters, "TargetFramework", isNETCore ? "netcoreapp3.1" : "net461"); } return(projectTemplate); }
public abstract IEnumerable <AssetItem> Import(UFile rawAssetPath, AssetImporterParameters importParameters);
/// <summary> /// Initializes a new instance of the <see cref="ProjectReference"/> class. /// </summary> /// <param name="id">The project's unique identifier.</param> /// <param name="location">The project file location.</param> /// <param name="type">The project type.</param> public ProjectReference(Guid id, UFile location, ProjectType type) { Id = id; Location = location; Type = type; }
public void TestMakeRelative() { UPath assetPath2 = null; UPath newAssetPath2 = null; var dir1 = new UDirectory("/a/b/c"); var assetDir2 = new UDirectory("/a/b/c"); newAssetPath2 = dir1.MakeRelative(assetDir2); Assert.AreEqual(".", newAssetPath2.FullPath); var assetDir3 = new UDirectory("/a/b"); newAssetPath2 = dir1.MakeRelative(assetDir3); Assert.AreEqual("c", newAssetPath2.FullPath); var assetDir4 = new UDirectory("/a/b/c/d"); newAssetPath2 = dir1.MakeRelative(assetDir4); Assert.AreEqual("..", newAssetPath2.FullPath); // Test direct relative assetPath2 = new UFile("/a/b/c/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("test.txt", newAssetPath2.FullPath); // Test direct relative + subdir assetPath2 = new UFile("/a/b/c/test/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("test/test.txt", newAssetPath2.FullPath); // Test relative 1 assetPath2 = new UFile("/a/b/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../test.txt", newAssetPath2.FullPath); // Test relative 2 assetPath2 = new UFile("/a/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../test.txt", newAssetPath2.FullPath); // Test relative 3 assetPath2 = new UFile("/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../../test.txt", newAssetPath2.FullPath); // Test already relative assetPath2 = new UFile("../test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../test.txt", newAssetPath2.FullPath); // Test only root path in common assetPath2 = new UFile("/e/f/g/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../../e/f/g/test.txt", newAssetPath2.FullPath); // Test only root path in common with single file assetPath2 = new UFile("/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../../test.txt", newAssetPath2.FullPath); }
public static void UpdateDependencies(SolutionProject project, bool directDependencies, bool flattenedDependencies) { if (flattenedDependencies) { project.FlattenedDependencies.Clear(); } if (directDependencies) { project.DirectDependencies.Clear(); } var projectAssetsJsonPath = Path.Combine(project.FullPath.GetFullDirectory(), @"obj", LockFileFormat.AssetsFileName); if (File.Exists(projectAssetsJsonPath)) { var format = new LockFileFormat(); var projectAssets = format.Read(projectAssetsJsonPath); // Update dependencies if (flattenedDependencies) { var libPaths = new Dictionary <ValueTuple <string, NuGet.Versioning.NuGetVersion>, LockFileLibrary>(); foreach (var lib in projectAssets.Libraries) { libPaths.Add(ValueTuple.Create(lib.Name, lib.Version), lib); } foreach (var targetLibrary in projectAssets.Targets.Last().Libraries) { if (!libPaths.TryGetValue(ValueTuple.Create(targetLibrary.Name, targetLibrary.Version), out var library)) { continue; } var projectDependency = new Dependency(library.Name, library.Version.ToPackageVersion(), library.Type == "project" ? DependencyType.Project : DependencyType.Package) { MSBuildProject = library.Type == "project" ? library.MSBuildProject : null }; if (library.Type == "package") { // Find library path by testing with each PackageFolders var libraryPath = projectAssets.PackageFolders .Select(packageFolder => Path.Combine(packageFolder.Path, library.Path.Replace('/', Path.DirectorySeparatorChar))) .FirstOrDefault(x => Directory.Exists(x)); if (libraryPath != null) { // Build list of assemblies foreach (var a in targetLibrary.RuntimeAssemblies) { if (!a.Path.EndsWith("_._")) { var assemblyFile = Path.Combine(libraryPath, a.Path.Replace('/', Path.DirectorySeparatorChar)); projectDependency.Assemblies.Add(assemblyFile); } } foreach (var a in targetLibrary.RuntimeTargets) { if (!a.Path.EndsWith("_._")) { var assemblyFile = Path.Combine(libraryPath, a.Path.Replace('/', Path.DirectorySeparatorChar)); projectDependency.Assemblies.Add(assemblyFile); } } } } project.FlattenedDependencies.Add(projectDependency); // Try to resolve package if already loaded projectDependency.Package = project.Session.Packages.Find(projectDependency); } } if (directDependencies) { foreach (var projectReference in projectAssets.PackageSpec.RestoreMetadata.TargetFrameworks.First().ProjectReferences) { var projectName = new UFile(projectReference.ProjectUniqueName).GetFileNameWithoutExtension(); project.DirectDependencies.Add(new DependencyRange(projectName, null, DependencyType.Project) { MSBuildProject = projectReference.ProjectPath }); } foreach (var dependency in projectAssets.PackageSpec.TargetFrameworks.First().Dependencies) { if (dependency.AutoReferenced) { continue; } project.DirectDependencies.Add(new DependencyRange(dependency.Name, dependency.LibraryRange.VersionRange.ToPackageVersionRange(), DependencyType.Package)); } } } }
private async Task GeneratePrecompiledFont() { var font = (SpriteFontAsset)AssetItem.Asset; var dialogService = ServiceProvider.Get <IDialogService>(); // Dynamic font cannot be precompiled if (font.FontType is RuntimeRasterizedSpriteFontType) { // Note: Markdown (**, _) are used to format the text. await dialogService.MessageBox(Tr._p("Message", "**Only static fonts can be precompiled.**\r\n\r\nClear the _Is Dynamic_ property on this font and try again."), MessageBoxButton.OK, MessageBoxImage.Error); return; } // Compute unique name var precompiledName = NamingHelper.ComputeNewName($"{AssetItem.Location.GetFileNameWithoutExtension()} (Precompiled)", Directory.Assets, x => x.Name); // Ask location for generated texture var folderDialog = dialogService.CreateFolderOpenModalDialog(); folderDialog.InitialDirectory = (Session.CurrentProject?.Package?.RootDirectory ?? Session.SolutionPath.GetFullDirectory()).ToWindowsPath() + "\\Resources"; var dialogResult = await folderDialog.ShowModal(); if (dialogResult != DialogResult.Ok) { return; } bool srgb; var gameSettings = Session.CurrentProject?.Package.GetGameSettingsAsset(); if (gameSettings == null) { var buttons = DialogHelper.CreateButtons(new[] { ColorSpace.Linear.ToString(), ColorSpace.Gamma.ToString(), Tr._p("Button", "Cancel") }, 1, 3); var result = await dialogService.MessageBox(Tr._p("Message", "Which color space do you want to use?"), buttons, MessageBoxImage.Question); // Close without clicking a button or Cancel if (result == 0 || result == 3) { return; } srgb = result == 2; } else { srgb = gameSettings.GetOrCreate <RenderingSettings>().ColorSpace == ColorSpace.Linear; } var precompiledFontAsset = (font.FontType is SignedDistanceFieldSpriteFontType) ? font.GeneratePrecompiledSDFSpriteFont(AssetItem, UFile.Combine(folderDialog.Directory, precompiledName)) : font.GeneratePrecompiledSpriteFont(AssetItem, UFile.Combine(folderDialog.Directory, precompiledName), srgb); // NOTE: following code could be factorized with AssetFactoryViewModel var defaultLocation = UFile.Combine(Directory.Path, precompiledName); var assetItem = new AssetItem(defaultLocation, precompiledFontAsset); AssetViewModel assetViewModel; using (var transaction = UndoRedoService.CreateTransaction()) { // FIXME: do we need to delete the generated file upon undo? assetViewModel = Directory.Package.CreateAsset(Directory, assetItem, true, null); UndoRedoService.SetName(transaction, $"Create Asset '{precompiledName}'"); } Session.CheckConsistency(); if (assetViewModel != null) { Session.ActiveAssetView.SelectAssetCommand.Execute(assetViewModel); } }
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, RenderFrameAsset asset, AssetCompilerResult result) { result.BuildSteps = new ListBuildStep { new RenderFrameCompileCommand(urlInStorage, asset) }; }
protected void WriteGitIgnore(SessionTemplateGeneratorParameters parameters) { var fileName = UFile.Combine(parameters.OutputDirectory, ".gitignore"); File.WriteAllText(fileName.ToWindowsPath(), GitIgnore); }
protected SingleFileImportCommand(UFile location, UFile sourcePath) { Location = location; SourcePath = sourcePath; }
public AssetSerializableLogMessage(AssetId assetId, UFile assetUrl, LogMessageType type, string text, ExceptionInfo exceptionInfo = null) : base("", type, text, exceptionInfo) { AssetId = assetId; AssetUrl = assetUrl; }
/// <summary> /// Initializes a new instance of the <see cref="SettingsFileLoadedEventArgs"/> class. /// </summary> /// <param name="path"></param> public SettingsFileLoadedEventArgs(UFile path) { FilePath = path; }
private bool RemoveFilePrivate(UFile filePath) { return(mruList.RemoveWhere(x => string.Equals(x.FilePath, filePath, StringComparison.OrdinalIgnoreCase)) > 0); }
public void TestWithNormalization() { var assetPath = new UFile("/a/b/.././././//c.txt"); Assert.AreEqual("/a", assetPath.GetDirectory()); Assert.AreEqual("c", assetPath.GetFileName()); Assert.AreEqual(".txt", assetPath.GetFileExtension()); Assert.AreEqual("/a/c", assetPath.GetDirectoryAndFileName()); Assert.AreEqual("/a/c.txt", assetPath.FullPath); assetPath = new UFile("../.././././//c.txt"); Assert.AreEqual("../..", assetPath.GetDirectory()); Assert.AreEqual("c", assetPath.GetFileName()); Assert.AreEqual(".txt", assetPath.GetFileExtension()); Assert.AreEqual("../../c", assetPath.GetDirectoryAndFileName()); Assert.AreEqual("../../c.txt", assetPath.FullPath); assetPath = new UFile("a/../../../c.txt"); Assert.AreEqual("../../c.txt", assetPath.FullPath); }
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, ModelAsset asset, AssetCompilerResult result) { if (!EnsureSourcesExist(result, asset, assetAbsolutePath)) { return; } // Get absolute path of asset source on disk var assetDirectory = assetAbsolutePath.GetParent(); var assetSource = UPath.Combine(assetDirectory, asset.Source); var gameSettingsAsset = context.GetGameSettingsAsset(); var renderingSettings = gameSettingsAsset.Get <RenderingSettings>(); var allow32BitIndex = renderingSettings.DefaultGraphicsProfile >= GraphicsProfile.Level_9_2; var allowUnsignedBlendIndices = context.GetGraphicsPlatform(AssetItem.Package) != GraphicsPlatform.OpenGLES; var extension = asset.Source.GetFileExtension(); // Find skeleton asset, if any AssetItem skeleton = null; if (asset.Skeleton != null) { skeleton = AssetItem.Package.FindAssetFromAttachedReference(asset.Skeleton); } var importModelCommand = ImportModelCommand.Create(extension); if (importModelCommand == null) { result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", extension, assetSource); return; } importModelCommand.Mode = ImportModelCommand.ExportMode.Model; importModelCommand.SourcePath = assetSource; importModelCommand.Location = urlInStorage; importModelCommand.Allow32BitIndex = allow32BitIndex; importModelCommand.AllowUnsignedBlendIndices = allowUnsignedBlendIndices; importModelCommand.Materials = asset.Materials; importModelCommand.ScaleImport = asset.ScaleImport; importModelCommand.PivotPosition = asset.PivotPosition; importModelCommand.SkeletonUrl = skeleton?.Location; result.BuildSteps = new AssetBuildStep(AssetItem) { importModelCommand }; }
public void TestMixedSlash() { var assetPath1 = new UFile("/a\\b/c\\d.txt"); var assetPath2 = new UFile("/a/b/c/d.txt"); Assert.AreEqual(assetPath1.ToString(), assetPath2.ToString()); }
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, UIImageGroupAsset asset, AssetCompilerResult result) { var imageToTextureIndex = CompileGroup(context, urlInStorage, assetAbsolutePath, asset, result); if (!result.HasErrors) { result.BuildSteps.Add(new UIImageGroupCommand(urlInStorage, new ImageGroupParameters <UIImageGroupAsset>(asset, context.Platform), imageToTextureIndex)); } }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); var description = (TemplateSampleDescription)parameters.Description; var log = parameters.Logger; // The package might depend on other packages which need to be copied together when instanciating it. // However some of these packages might be in a parent folder, which can result in undesired behavior when copied. // Setting this to true will enforce all package dependencies to be moved to a folder local to the project bool doMoveParentDependencies = true; var regexes = new List <Tuple <Regex, MatchEvaluator> >(); var patternName = description.PatternName ?? description.DefaultOutputName; // Samples don't support spaces and dot in name (we would need to separate package name, package short name and namespace renaming for that). var parametersName = parameters.Name.Replace(" ", string.Empty).Replace(".", string.Empty); if (patternName != parametersName) { // Make sure the target name is a safe for use everywhere, since both an asset or script might reference a filename // in which case they should match and be valid in that context string validNamespaceName = Utilities.BuildValidNamespaceName(parametersName); // Rename for general occurences of template name regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}\b"), match => validNamespaceName)); // Rename App as well (used in code) -- this is the only pattern of "package short name" that we have so far in Windows samples regexes.Add(new Tuple <Regex, MatchEvaluator>(new Regex($@"\b{patternName}App\b"), match => validNamespaceName)); } var outputDirectory = parameters.OutputDirectory; if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } //write gitignore WriteGitIgnore(parameters); WriteGlobalJson(parameters); UFile projectOutputFile = null; UFile projectInputFile = null; // Process files foreach (var directory in FileUtility.EnumerateDirectories(description.TemplateDirectory, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { // If the file is ending with the Template extension or a directory with the sample extension, don;t copy it if (file.FullName.EndsWith(TemplateDescription.FileExtension) || string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0) { continue; } var relativeFile = new UFile(file.FullName).MakeRelative(description.TemplateDirectory); // Replace the name in the files if necessary foreach (var nameRegex in regexes) { relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2); } // Create the output directory if needed var outputFile = UPath.Combine(outputDirectory, relativeFile); var outputFileDirectory = outputFile.GetParent(); // Determine if we are processing the main game project var isPackageFile = (projectOutputFile == null && Path.GetExtension(file.FullName).ToLowerInvariant() == ".csproj" && !Path.GetFileNameWithoutExtension(file.FullName).EndsWith(".Windows")); if (isPackageFile) { projectInputFile = file.FullName; projectOutputFile = outputFile; } if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } if (IsBinaryFile(file.FullName)) { File.Copy(file.FullName, outputFile, true); } else { ProcessTextFile(file.FullName, outputFile, regexes, (isPackageFile && doMoveParentDependencies)); } } } if (projectOutputFile != null) { var inputProject = (SolutionProject)Package.LoadProject(log, projectInputFile); var outputProject = (SolutionProject)Package.LoadProject(log, projectOutputFile); var msbuildProject = VSProjectHelper.LoadProject(outputProject.FullPath, platform: "NoPlatform"); // If requested, add reference to Stride.Games.Testing if (parameters.TryGetTag(AddGamesTestingKey)) { var items = msbuildProject.AddItem("PackageReference", "Stride.Games.Testing", new[] { new KeyValuePair <string, string>("Version", StrideVersion.NuGetVersion), new KeyValuePair <string, string>("PrivateAssets", "contentfiles;analyzers") }); foreach (var item in items) { foreach (var metadata in item.Metadata) { metadata.Xml.ExpressedAsAttribute = true; } } } // Copy dependency files locally // We only want to copy the asset files. The raw files are in Resources and the game assets are in Assets. // If we copy each file locally they will be included in the package and we can then delete the dependency packages. foreach (var projectReference in msbuildProject.GetItems("ProjectReference").ToList()) { var packageDirectory = UPath.Combine(inputProject.FullPath.GetFullDirectory(), (UFile)projectReference.EvaluatedInclude).GetFullDirectory(); foreach (var directory in FileUtility.EnumerateDirectories(packageDirectory, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { // If the file is ending with the Template extension or a directory with the sample extension, don`t copy it if (file.FullName.EndsWith(TemplateDescription.FileExtension) || string.Compare(directory.Name, TemplateDescription.FileExtension, StringComparison.OrdinalIgnoreCase) == 0) { continue; } var relativeFile = new UFile(file.FullName).MakeRelative(packageDirectory); var relativeFilename = relativeFile.ToString(); bool isAsset = relativeFilename.Contains("Assets"); bool isResource = relativeFilename.Contains("Resources"); if (!isAsset && !isResource) { continue; } // Replace the name in the files if necessary foreach (var nameRegex in regexes) { relativeFile = nameRegex.Item1.Replace(relativeFile, nameRegex.Item2); } var outputFile = UPath.Combine(outputDirectory, relativeFile); { // Create the output directory if needed var outputFileDirectory = outputFile.GetParent(); if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } } if (IsBinaryFile(file.FullName)) { File.Copy(file.FullName, outputFile, true); } else { ProcessTextFile(file.FullName, outputFile, regexes); } } } msbuildProject.RemoveItem(projectReference); } // Save csproj without ProjectReferences msbuildProject.Save(); msbuildProject.ProjectCollection.UnloadAllProjects(); msbuildProject.ProjectCollection.Dispose(); // Add package to session var loadParams = PackageLoadParameters.Default(); loadParams.GenerateNewAssetIds = true; loadParams.LoadMissingDependencies = false; var session = parameters.Session; // We should switch to loading .csproj once all samples are upgraded var loadedProject = session.AddExistingProject(projectOutputFile, log, loadParams); RemoveUnusedAssets(loadedProject.Package, session); parameters.Tags.Add(GeneratedPackageKey, loadedProject.Package); } else { log.Error("Unable to find generated package for this template"); } // Make sure we transfer overrides, etc. from what we deserialized to the asset graphs that we are going to save right after. ApplyMetadata(parameters); return(true); }
private string GetPath(UFile imagePath) { return(UPath.Combine(Template.FullPath.GetFullDirectory(), imagePath)); }
private async Task PreLoadPackageDependencies(ILogger log, SolutionProject project, PackageLoadParameters loadParameters) { if (log == null) { throw new ArgumentNullException(nameof(log)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } if (loadParameters == null) { throw new ArgumentNullException(nameof(loadParameters)); } bool packageDependencyErrors = false; var package = project.Package; // TODO: Remove and recheck Dependencies Ready if some secondary packages are removed? if (package.State >= PackageState.DependenciesReady) { return; } log.Verbose($"Process dependencies for {project.Name}..."); var packageReferences = new Dictionary <string, PackageVersionRange>(); // Check if there is any package upgrade to do var pendingPackageUpgrades = new List <PendingPackageUpgrade>(); pendingPackageUpgradesPerPackage.Add(package, pendingPackageUpgrades); // Load some informations about the project try { var extraProperties = new Dictionary <string, string>(); if (loadParameters.ExtraCompileProperties != null) { foreach (var extraProperty in loadParameters.ExtraCompileProperties) { extraProperties.Add(extraProperty.Key, extraProperty.Value); } } extraProperties.Add("SkipInvalidConfigurations", "true"); var msProject = VSProjectHelper.LoadProject(project.FullPath, loadParameters.BuildConfiguration, extraProperties: extraProperties); try { var packageVersion = msProject.GetPropertyValue("PackageVersion"); if (!string.IsNullOrEmpty(packageVersion)) { package.Meta.Version = new PackageVersion(packageVersion); } project.TargetPath = msProject.GetPropertyValue("TargetPath"); project.AssemblyProcessorSerializationHashFile = msProject.GetProperty("StrideAssemblyProcessorSerializationHashFile")?.EvaluatedValue; if (project.AssemblyProcessorSerializationHashFile != null) { project.AssemblyProcessorSerializationHashFile = Path.Combine(Path.GetDirectoryName(project.FullPath), project.AssemblyProcessorSerializationHashFile); } package.Meta.Name = (msProject.GetProperty("PackageId") ?? msProject.GetProperty("AssemblyName"))?.EvaluatedValue ?? package.Meta.Name; var outputType = msProject.GetPropertyValue("OutputType"); project.Type = outputType.ToLowerInvariant() == "winexe" || outputType.ToLowerInvariant() == "exe" || outputType.ToLowerInvariant() == "appcontainerexe" || // UWP msProject.GetPropertyValue("AndroidApplication").ToLowerInvariant() == "true" // Android ? ProjectType.Executable : ProjectType.Library; // Note: Platform might be incorrect if Stride is not restored yet (it won't include Stride targets) // Also, if already set, don't try to query it again if (project.Type == ProjectType.Executable && project.Platform == PlatformType.Shared) { project.Platform = VSProjectHelper.GetPlatformTypeFromProject(msProject) ?? PlatformType.Shared; } foreach (var packageReference in msProject.GetItems("PackageReference").ToList()) { if (packageReference.HasMetadata("Version") && PackageVersionRange.TryParse(packageReference.GetMetadataValue("Version"), out var packageRange)) { packageReferences[packageReference.EvaluatedInclude] = packageRange; } } // Need to go recursively foreach (var projectReference in msProject.GetItems("ProjectReference").ToList()) { var projectFile = new UFile(Path.Combine(Path.GetDirectoryName(project.FullPath), projectReference.EvaluatedInclude)); if (File.Exists(projectFile)) { var referencedProject = Projects.OfType <SolutionProject>().FirstOrDefault(x => x.FullPath == new UFile(projectFile)); if (referencedProject != null) { await PreLoadPackageDependencies(log, referencedProject, loadParameters); // Get package upgrader from dependency (a project might depend on another project rather than referencing Stride directly) // A better system would be to evaluate nuget flattened dependencies WITHOUT doing the actual restore (dry-run). // However I am not sure it's easy/possible to do it (using API) without doing a full restore/download, which we don't want to do // with old version (it might be uninstalled already and we want to avoid re-downloading it again) if (pendingPackageUpgradesPerPackage.TryGetValue(referencedProject.Package, out var dependencyPackageUpgraders)) { foreach (var dependencyPackageUpgrader in dependencyPackageUpgraders) { // Make sure this upgrader is not already added if (!pendingPackageUpgrades.Any(x => x.DependencyPackage == dependencyPackageUpgrader.DependencyPackage)) { // Note: it's important to clone because once upgraded, each instance will have its Dependency.Version tested/updated pendingPackageUpgrades.Add(dependencyPackageUpgrader.Clone()); } } } } } } } finally { msProject.ProjectCollection.UnloadAllProjects(); msProject.ProjectCollection.Dispose(); } } catch (Exception ex) { log.Error($"Unexpected exception while loading project [{project.FullPath.ToWindowsPath()}]", ex); } foreach (var packageReference in packageReferences) { var dependencyName = packageReference.Key; var dependencyVersion = packageReference.Value; var packageUpgrader = AssetRegistry.GetPackageUpgrader(dependencyName); if (packageUpgrader != null) { // Check if this upgrader has already been added due to another package reference if (pendingPackageUpgrades.Any(pendingPackageUpgrade => pendingPackageUpgrade.PackageUpgrader == packageUpgrader)) { continue; } // Check if upgrade is necessary if (dependencyVersion.MinVersion >= packageUpgrader.Attribute.UpdatedVersionRange.MinVersion) { continue; } // Check if upgrade is allowed if (dependencyVersion.MinVersion < packageUpgrader.Attribute.PackageMinimumVersion) { // Throw an exception, because the package update is not allowed and can't be done throw new InvalidOperationException($"Upgrading project [{project.Name}] to use [{dependencyName}] from version [{dependencyVersion}] to [{packageUpgrader.Attribute.UpdatedVersionRange.MinVersion}] is not supported (supported only from version [{packageUpgrader.Attribute.PackageMinimumVersion}]"); } log.Info($"Upgrading project [{project.Name}] to use [{dependencyName}] from version [{dependencyVersion}] to [{packageUpgrader.Attribute.UpdatedVersionRange.MinVersion}] will be required"); pendingPackageUpgrades.Add(new PendingPackageUpgrade(packageUpgrader, new PackageDependency(dependencyName, dependencyVersion), null)); } } if (pendingPackageUpgrades.Count > 0) { var upgradeAllowed = packageUpgradeAllowed != false ? PackageUpgradeRequestedAnswer.Upgrade : PackageUpgradeRequestedAnswer.DoNotUpgrade; // Need upgrades, let's ask user confirmation if (loadParameters.PackageUpgradeRequested != null && !packageUpgradeAllowed.HasValue) { upgradeAllowed = loadParameters.PackageUpgradeRequested(package, pendingPackageUpgrades); if (upgradeAllowed == PackageUpgradeRequestedAnswer.UpgradeAll) { packageUpgradeAllowed = true; } if (upgradeAllowed == PackageUpgradeRequestedAnswer.DoNotUpgradeAny) { packageUpgradeAllowed = false; } } if (!PackageLoadParameters.ShouldUpgrade(upgradeAllowed)) { log.Error($"Necessary package migration for [{package.Meta.Name}] has not been allowed"); return; } // Perform pre assembly load upgrade foreach (var pendingPackageUpgrade in pendingPackageUpgrades) { var expectedVersion = pendingPackageUpgrade.PackageUpgrader.Attribute.UpdatedVersionRange.MinVersion.ToString(); // Update NuGet references try { var projectFile = project.FullPath; var msbuildProject = VSProjectHelper.LoadProject(projectFile.ToWindowsPath()); var isProjectDirty = false; foreach (var packageReference in msbuildProject.GetItems("PackageReference").ToList()) { if (packageReference.EvaluatedInclude == pendingPackageUpgrade.Dependency.Name && packageReference.GetMetadataValue("Version") != expectedVersion) { packageReference.SetMetadataValue("Version", expectedVersion); isProjectDirty = true; } } if (isProjectDirty) { msbuildProject.Save(); } msbuildProject.ProjectCollection.UnloadAllProjects(); msbuildProject.ProjectCollection.Dispose(); } catch (Exception e) { log.Warning($"Unable to load project [{project.FullPath.GetFileName()}]", e); } var packageUpgrader = pendingPackageUpgrade.PackageUpgrader; var dependencyPackage = pendingPackageUpgrade.DependencyPackage; if (!packageUpgrader.UpgradeBeforeAssembliesLoaded(loadParameters, package.Session, log, package, pendingPackageUpgrade.Dependency, dependencyPackage)) { log.Error($"Error while upgrading package [{package.Meta.Name}] for [{dependencyPackage.Meta.Name}] from version [{pendingPackageUpgrade.Dependency.Version}] to [{dependencyPackage.Meta.Version}]"); return; } } } // Now that our references are upgraded, let's do a real nuget restore (download files) log.Verbose($"Restore NuGet packages for {project.Name}..."); if (loadParameters.AutoCompileProjects) { await VSProjectHelper.RestoreNugetPackages(log, project.FullPath); } // If platform was unknown (due to missing nuget packages during first pass), check it again if (project.Type == ProjectType.Executable && project.Platform == PlatformType.Shared) { try { var msProject = VSProjectHelper.LoadProject(project.FullPath, extraProperties: new Dictionary <string, string> { { "SkipInvalidConfigurations", "true" } }); try { project.Platform = VSProjectHelper.GetPlatformTypeFromProject(msProject) ?? PlatformType.Shared; } finally { msProject.ProjectCollection.UnloadAllProjects(); msProject.ProjectCollection.Dispose(); } } catch (Exception ex) { log.Error($"Unexpected exception while loading project [{project.FullPath.ToWindowsPath()}]", ex); } } UpdateDependencies(project, true, true); // 1. Load store package foreach (var projectDependency in project.FlattenedDependencies) { // Make all the assemblies known to the container to ensure that later assembly loads succeed foreach (var assembly in projectDependency.Assemblies) { AssemblyContainer.RegisterDependency(assembly); } var loadedPackage = packages.Find(projectDependency); if (loadedPackage == null) { string file = null; switch (projectDependency.Type) { case DependencyType.Project: if (Path.GetExtension(projectDependency.MSBuildProject).ToLowerInvariant() == ".csproj") { file = UPath.Combine(project.FullPath.GetFullDirectory(), (UFile)projectDependency.MSBuildProject); } break; case DependencyType.Package: file = PackageStore.Instance.GetPackageFileName(projectDependency.Name, new PackageVersionRange(projectDependency.Version), constraintProvider); break; } if (file != null && File.Exists(file)) { // Load package var loadedProject = LoadProject(log, file, loadParameters); loadedProject.Package.Meta.Name = projectDependency.Name; loadedProject.Package.Meta.Version = projectDependency.Version; Projects.Add(loadedProject); if (loadedProject is StandalonePackage standalonePackage) { standalonePackage.Assemblies.AddRange(projectDependency.Assemblies); } loadedPackage = loadedProject.Package; } } if (loadedPackage != null) { projectDependency.Package = loadedPackage; } } // 2. Load local packages /*foreach (var packageReference in package.LocalDependencies) * { * // Check that the package was not already loaded, otherwise return the same instance * if (Packages.ContainsById(packageReference.Id)) * { * continue; * } * * // Expand the string of the location * var newLocation = packageReference.Location; * * var subPackageFilePath = package.RootDirectory != null ? UPath.Combine(package.RootDirectory, newLocation) : newLocation; * * // Recursive load * var loadedPackage = PreLoadPackage(log, subPackageFilePath.FullPath, false, loadedPackages, loadParameters); * * if (loadedPackage == null || loadedPackage.State < PackageState.DependenciesReady) * packageDependencyErrors = true; * }*/ // 3. Update package state if (!packageDependencyErrors) { package.State = PackageState.DependenciesReady; } }
protected abstract Task RestartAndOpenSession(UFile sessionPath);
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, AnimationAsset asset, AssetCompilerResult result) { if (!EnsureSourceExists(result, asset, assetAbsolutePath)) { return; } // Get absolute path of asset source on disk var assetDirectory = assetAbsolutePath.GetParent(); var assetSource = GetAbsolutePath(assetAbsolutePath, asset.Source); var extension = assetSource.GetFileExtension(); var buildStep = new AssetBuildStep(AssetItem); var additiveAnimationAsset = asset as AdditiveAnimationAsset; if (additiveAnimationAsset != null) { var baseUrlInStorage = urlInStorage + "_animation_base"; var sourceUrlInStorage = urlInStorage + "_animation_source"; var baseAssetSource = UPath.Combine(assetDirectory, additiveAnimationAsset.BaseSource); // Import base and main animation if (ImportFbxCommand.IsSupportingExtensions(extension)) { buildStep.Add(new ImportFbxCommand { SourcePath = assetSource, Location = sourceUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); buildStep.Add(new ImportFbxCommand { SourcePath = baseAssetSource, Location = baseUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); } else if (ImportAssimpCommand.IsSupportingExtensions(extension)) { buildStep.Add(new ImportAssimpCommand { SourcePath = assetSource, Location = sourceUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); buildStep.Add(new ImportAssimpCommand { SourcePath = baseAssetSource, Location = baseUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); } // Wait for both import fbx commands to be completed buildStep.Add(new WaitBuildStep()); // Generate the diff of those two animations buildStep.Add(new AdditiveAnimationCommand(urlInStorage, new AdditiveAnimationParameters(baseUrlInStorage, sourceUrlInStorage, additiveAnimationAsset.Mode))); } else { // Import the main animation if (ImportFbxCommand.IsSupportingExtensions(extension)) { buildStep.Add(new ImportFbxCommand { SourcePath = assetSource, Location = urlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); } else if (ImportAssimpCommand.IsSupportingExtensions(extension)) { buildStep.Add(new ImportAssimpCommand { SourcePath = assetSource, Location = urlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport }); } } result.BuildSteps = buildStep; }
public PackageLoadingAssetFile(UFile filePath, UDirectory sourceFolder, UFile projectFile) { FilePath = filePath; SourceFolder = sourceFolder; ProjectFile = projectFile; }
void RegisterItem(UFile targetFilePath) { generatedItems.Add((targetFilePath.ToWindowsPath(), UPath.Combine("stride", targetFilePath.MakeRelative(outputPath)).ToWindowsPath())); }
public static string GenerateColorTextureURL(UFile originalLocation) { return(GenerateSeparateTextureURL(originalLocation, SplittedColorTextureNameSuffix)); }
public static SolutionProject GenerateTemplate(TemplateGeneratorParameters parameters, UFile templateRelativePath, string projectName, PlatformType platformType, GraphicsPlatform?graphicsPlatform, ProjectType projectType, out List <string> generatedFiles, Guid?projectGuidArg = null) { var options = GetOptions(parameters); var outputDirectoryPath = UPath.Combine(parameters.OutputDirectory, (UDirectory)projectName); Directory.CreateDirectory(outputDirectoryPath); generatedFiles = new List <string>(); parameters.Logger.Verbose($"Generating {projectName}..."); var projectGuid = projectGuidArg ?? Guid.NewGuid(); var packagePath = UPath.Combine(outputDirectoryPath, (UFile)(projectName + Package.PackageFileExtension)); var projectFullPath = UPath.Combine(outputDirectoryPath, (UFile)(projectName + ".csproj")); var package = new Package { Meta = { Name = projectName, Version = new PackageVersion("1.0.0.0") }, FullPath = packagePath, IsDirty = true, }; package.AssetFolders.Add(new AssetFolder("Assets")); package.ResourceFolders.Add("Resources"); var projectTemplate = PrepareTemplate(parameters, package, templateRelativePath, platformType, graphicsPlatform, projectType); projectTemplate.Generate(outputDirectoryPath, projectName, projectGuid, parameters.Logger, options, generatedFiles); var project = new SolutionProject(package, projectGuid, projectFullPath); project.Type = projectType; project.Platform = platformType; return(project); }
private static string GenerateSeparateTextureURL(UFile originalLocation, string suffixName) { return(originalLocation.GetDirectory() + "/" + SplittedTextureNamePrefix + originalLocation.GetFileName() + suffixName); }
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, SpriteFontAsset asset, AssetCompilerResult result) { var colorSpace = context.GetColorSpace(); if (asset.FontType is SignedDistanceFieldSpriteFontType) { var fontTypeSDF = asset.FontType as SignedDistanceFieldSpriteFontType; // copy the asset and transform the source and character set file path to absolute paths var assetClone = (SpriteFontAsset)AssetCloner.Clone(asset); var assetDirectory = assetAbsolutePath.GetParent(); assetClone.FontSource = asset.FontSource; fontTypeSDF.CharacterSet = !string.IsNullOrEmpty(fontTypeSDF.CharacterSet) ? UPath.Combine(assetDirectory, fontTypeSDF.CharacterSet) : null; result.BuildSteps = new AssetBuildStep(AssetItem) { new SignedDistanceFieldFontCommand(urlInStorage, assetClone) }; } else if (asset.FontType is RuntimeRasterizedSpriteFontType) { UFile fontPathOnDisk = asset.FontSource.GetFontPath(result); if (fontPathOnDisk == null) { result.Error("Runtime rasterized font compilation failed. Font {0} was not found on this machine.", asset.FontSource.GetFontName()); result.BuildSteps = new AssetBuildStep(AssetItem) { new FailedFontCommand() }; return; } var fontImportLocation = FontHelper.GetFontPath(asset.FontSource.GetFontName(), asset.FontSource.Style); result.BuildSteps = new AssetBuildStep(AssetItem) { new ImportStreamCommand { SourcePath = fontPathOnDisk, Location = fontImportLocation }, new RuntimeRasterizedFontCommand(urlInStorage, asset) }; } else { var fontTypeStatic = asset.FontType as OfflineRasterizedSpriteFontType; if (fontTypeStatic == null) { throw new ArgumentException("Tried to compile a non-offline rasterized sprite font with the compiler for offline resterized fonts!"); } // copy the asset and transform the source and character set file path to absolute paths var assetClone = (SpriteFontAsset)AssetCloner.Clone(asset); var assetDirectory = assetAbsolutePath.GetParent(); assetClone.FontSource = asset.FontSource; fontTypeStatic.CharacterSet = !string.IsNullOrEmpty(fontTypeStatic.CharacterSet) ? UPath.Combine(assetDirectory, fontTypeStatic.CharacterSet): null; result.BuildSteps = new AssetBuildStep(AssetItem) { new OfflineRasterizedFontCommand(urlInStorage, assetClone, colorSpace) }; } }
/// <summary> /// Initializes a new instance of the <see cref="AdditiveAnimationAsset"/> class. /// </summary> public AdditiveAnimationAsset() { BaseSource = new UFile(""); }
public void TestWithSimplePathWithExtension() { var assetPath = new UFile("/a/b/c.txt"); Assert.AreEqual("/a/b", assetPath.GetDirectory()); Assert.AreEqual("c", assetPath.GetFileName()); Assert.AreEqual(".txt", assetPath.GetFileExtension()); Assert.AreEqual("/a/b/c", assetPath.GetDirectoryAndFileName()); Assert.AreEqual("/a/b/c.txt", assetPath.FullPath); }
private static async void Startup(UFile initialSessionPath) { try { InitializeLanguageSettings(); var serviceProvider = InitializeServiceProvider(); try { PackageSessionPublicHelper.FindAndSetMSBuildVersion(); } catch (Exception e) { var message = "Could not find a compatible version of MSBuild.\r\n\r\n" + "Check that you have a valid installation with the required workloads, or go to [www.visualstudio.com/downloads](https://www.visualstudio.com/downloads) to install a new one.\r\n\r\n" + e; await serviceProvider.Get <IEditorDialogService>().MessageBox(message, Core.Presentation.Services.MessageBoxButton.OK, Core.Presentation.Services.MessageBoxImage.Error); app.Shutdown(); return; } // We use a MRU that contains the older version projects to display in the editor var mru = new MostRecentlyUsedFileCollection(InternalSettings.LoadProfileCopy, InternalSettings.MostRecentlyUsedSessions, InternalSettings.WriteFile); mru.LoadFromSettings(); var editor = new GameStudioViewModel(serviceProvider, mru); AssetsPlugin.RegisterPlugin(typeof(XenkoDefaultAssetsPlugin)); AssetsPlugin.RegisterPlugin(typeof(XenkoEditorPlugin)); // Attempt to load the startup session, if available if (!UPath.IsNullOrEmpty(initialSessionPath)) { var sessionLoaded = await editor.OpenInitialSession(initialSessionPath); if (sessionLoaded == true) { var mainWindow = new GameStudioWindow(editor); Application.Current.MainWindow = mainWindow; WindowManager.ShowMainWindow(mainWindow); return; } } // No session successfully loaded, open the new/open project window bool?completed; // The user might cancel after chosing a template to instantiate, in this case we'll reopen the window var startupWindow = new ProjectSelectionWindow { WindowStartupLocation = WindowStartupLocation.CenterScreen, ShowInTaskbar = true, }; var viewModel = new NewOrOpenSessionTemplateCollectionViewModel(serviceProvider, startupWindow); startupWindow.Templates = viewModel; startupWindow.ShowDialog(); // The user selected a template to instantiate if (startupWindow.NewSessionParameters != null) { // Clean existing entry in the MRU data var directory = startupWindow.NewSessionParameters.OutputDirectory; var name = startupWindow.NewSessionParameters.OutputName; var mruData = new MRUAdditionalDataCollection(InternalSettings.LoadProfileCopy, GameStudioInternalSettings.MostRecentlyUsedSessionsData, InternalSettings.WriteFile); mruData.RemoveFile(UFile.Combine(UDirectory.Combine(directory, name), new UFile(name + SessionViewModel.SolutionExtension))); completed = await editor.NewSession(startupWindow.NewSessionParameters); } // The user selected a path to open else if (startupWindow.ExistingSessionPath != null) { completed = await editor.OpenSession(startupWindow.ExistingSessionPath); } // The user cancelled from the new/open project window, so exit the application else { completed = true; } if (completed != true) { var windowsClosed = new List <Task>(); foreach (var window in Application.Current.Windows.Cast <Window>().Where(x => x.IsLoaded)) { var tcs = new TaskCompletionSource <int>(); window.Unloaded += (s, e) => tcs.SetResult(0); windowsClosed.Add(tcs.Task); } await Task.WhenAll(windowsClosed); // When a project has been partially loaded, it might already have initialized some plugin that could conflict with // the next attempt to start something. Better start the application again. var commandLine = string.Join(" ", Environment.GetCommandLineArgs().Skip(1).Select(x => $"\"{x}\"")); var process = new Process { StartInfo = new ProcessStartInfo(typeof(Program).Assembly.Location, commandLine) }; process.Start(); app.Shutdown(); return; } if (editor.Session != null) { // If a session was correctly loaded, show the main window var mainWindow = new GameStudioWindow(editor); Application.Current.MainWindow = mainWindow; WindowManager.ShowMainWindow(mainWindow); } else { // Otherwise, exit. app.Shutdown(); } } catch (Exception) { app.Shutdown(); } }
public void TestEquals() { var assetPath1 = new UFile(null); var assetPath2 = new UFile(null); Assert.AreEqual(assetPath1, assetPath2); assetPath1 = new UFile("/a/b/c.txt"); assetPath2 = new UFile("/a/b/d/../c.txt"); Assert.AreEqual(assetPath1, assetPath2); // Test is not done on Extensions assetPath1 = new UFile("/a/b/c.txt"); assetPath2 = new UFile("/a/b/d/../c.png"); Assert.AreNotEqual(assetPath1, assetPath2); Assert.AreEqual(assetPath1.GetDirectoryAndFileName(), assetPath2.GetDirectoryAndFileName()); }
private bool TextureFileIsValid(UFile file) { return(file != null && File.Exists(file)); }
public void TestGetParent() { var dirPath1 = new UDirectory(@"E:\a\b"); var dirPathParent1 = dirPath1.GetParent(); Assert.AreEqual(@"E:/a", dirPathParent1.FullPath); dirPathParent1 = dirPathParent1.GetParent(); Assert.AreEqual(@"E:", dirPathParent1.FullPath); dirPathParent1 = dirPathParent1.GetParent(); Assert.AreEqual(UDirectory.Empty, dirPathParent1); dirPath1 = new UDirectory(@"/a/b"); dirPathParent1 = dirPath1.GetParent(); Assert.AreEqual(@"/a", dirPathParent1.FullPath); dirPathParent1 = dirPathParent1.GetParent(); Assert.AreEqual(@"/", dirPathParent1.FullPath); dirPathParent1 = dirPathParent1.GetParent(); Assert.AreEqual(UDirectory.Empty, dirPathParent1); // Test on file var filePath1 = new UFile(@"/a/b.txt"); dirPathParent1 = filePath1.GetParent(); Assert.AreEqual(@"/a", dirPathParent1.FullPath); }
protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, SpriteSheetAsset asset, AssetCompilerResult result) { var gameSettingsAsset = context.GetGameSettingsAsset(); var renderingSettings = gameSettingsAsset.Get <RenderingSettings>(context.Platform); result.BuildSteps = new ListBuildStep(); // create the registry containing the sprite assets texture index association var imageToTextureUrl = new Dictionary <SpriteInfo, string>(); var colorSpace = context.GetColorSpace(); // create and add import texture commands if (asset.Sprites != null && !asset.Packing.Enabled) { // sort sprites by referenced texture. var spriteByTextures = asset.Sprites.GroupBy(x => x.Source).ToArray(); for (int i = 0; i < spriteByTextures.Length; i++) { // skip the texture if the file is not valid. var textureFile = spriteByTextures[i].Key; if (!TextureFileIsValid(textureFile)) { continue; } var textureUrl = SpriteSheetAsset.BuildTextureUrl(urlInStorage, i); var spriteAssetArray = spriteByTextures[i].ToArray(); foreach (var spriteAsset in spriteAssetArray) { imageToTextureUrl[spriteAsset] = textureUrl; } // create an texture asset. var textureAsset = new TextureAsset { Id = Guid.Empty, // CAUTION: It is important to use an empty GUID here, as we don't want the command to be rebuilt (by default, a new asset is creating a new guid) Alpha = asset.Alpha, Format = asset.Format, GenerateMipmaps = asset.GenerateMipmaps, PremultiplyAlpha = asset.PremultiplyAlpha, ColorKeyColor = asset.ColorKeyColor, ColorKeyEnabled = asset.ColorKeyEnabled, ColorSpace = asset.ColorSpace, Hint = TextureHint.Color }; // Get absolute path of asset source on disk var assetDirectory = assetAbsolutePath.GetParent(); var assetSource = UPath.Combine(assetDirectory, spriteAssetArray[0].Source); // add the texture build command. result.BuildSteps.Add(new AssetBuildStep(new AssetItem(textureUrl, textureAsset)) { new TextureAssetCompiler.TextureConvertCommand( textureUrl, new TextureConvertParameters(assetSource, textureAsset, context.Platform, context.GetGraphicsPlatform(AssetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.Get <TextureSettings>().TextureQuality, colorSpace)) }); } } if (!result.HasErrors) { var parameters = new SpriteSheetParameters(asset, imageToTextureUrl, context.Platform, context.GetGraphicsPlatform(AssetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.Get <TextureSettings>().TextureQuality, colorSpace); result.BuildSteps.Add(new AssetBuildStep(AssetItem) { new SpriteSheetCommand(urlInStorage, parameters) }); } }
public void TestMakeRelativeWithDrive() { UPath assetPath2 = null; UPath newAssetPath2 = null; var dir1 = new UDirectory("C:/a/b/c"); // Test direct relative assetPath2 = new UFile("C:/a/b/c/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("test.txt", newAssetPath2.FullPath); // Test direct relative + subdir assetPath2 = new UFile("C:/a/b/c/test/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("test/test.txt", newAssetPath2.FullPath); // Test relative 1 assetPath2 = new UFile("C:/a/b/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../test.txt", newAssetPath2.FullPath); // Test relative 2 assetPath2 = new UFile("C:/a/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../test.txt", newAssetPath2.FullPath); // Test relative 3 assetPath2 = new UFile("C:/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../../../test.txt", newAssetPath2.FullPath); // Test already relative assetPath2 = new UFile("../test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("../test.txt", newAssetPath2.FullPath); // Test no path in common assetPath2 = new UFile("E:/e/f/g/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("E:/e/f/g/test.txt", newAssetPath2.FullPath); // Test no root path single file assetPath2 = new UFile("E:/test.txt"); newAssetPath2 = assetPath2.MakeRelative(dir1); Assert.AreEqual("E:/test.txt", newAssetPath2.FullPath); }