private void CreateCameraScript(SessionTemplateGeneratorParameters parameters, Package package, string projectGameName, Entity cameraEntity, AssetItem sceneAssetItem) { var logger = parameters.Logger; // Create the Camera script in Camera entity // Since we rely on lot of string check, added some null checking and try/catch to not crash the apps in case something went wrong // We only emit warnings rather than errors, so that the user could continue try { var gameAssembly = package.LoadedAssemblies.FirstOrDefault()?.Assembly; if (gameAssembly == null) { logger.Warning("Can't load Game assembly"); return; } var cameraScriptType = gameAssembly.GetType($"{parameters.Namespace}.{CameraScriptDefaultOutputName}"); if (cameraScriptType == null) { logger.Warning($"Could not find script '{CameraScriptDefaultOutputName}' in Game assembly"); return; } cameraEntity.Add((EntityComponent)Activator.CreateInstance(cameraScriptType)); sceneAssetItem.IsDirty = true; } catch (Exception e) { logger.Warning($"Could not instantiate {CameraScriptDefaultOutputName} script", e); } }
public override async Task <bool> PrepareForRun(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); var defaultNamespace = Utilities.BuildValidNamespaceName(parameters.Name); if (!parameters.Unattended) { var window = new GameTemplateWindow(AssetRegistry.SupportedPlatforms, defaultNamespace); await window.ShowModal(); if (window.Result == DialogResult.Cancel) { return(false); } parameters.Namespace = Utilities.BuildValidNamespaceName(window.Namespace); SetParameters(parameters, window.SelectedPlatforms, window.SelectedGraphicsProfile, window.IsHDR, window.Orientation, window.SelectedPackages); } return(true); }
public static Package GeneratePackage(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); var name = Utilities.BuildValidNamespaceName(parameters.Name); var outputDirectory = parameters.OutputDirectory; // Creates the package var package = NewPackage(name); // Setup the default namespace package.Meta.RootNamespace = parameters.Namespace; // Setup the path to save it package.FullPath = UPath.Combine(outputDirectory, new UFile(name + Package.PackageFileExtension)); // Add it to the current session var session = parameters.Session; session.Packages.Add(package); // Load missing references session.LoadMissingReferences(parameters.Logger); return(package); }
public override async Task <bool> PrepareForRun(SessionTemplateGeneratorParameters parameters) { if (parameters is null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); if (!parameters.Unattended) { var window = new UpdatePlatformsWindow(new[] { PlatformType.Windows }) { ForcePlatformRegenerationVisible = false }; await window.ShowModal(); if (window.Result == DialogResult.Cancel) { return(false); } parameters.SetTag(PlatformsKey, new List <SelectedSolutionPlatform>(window.SelectedPlatforms)); } return(true); }
private static PackageSession GenerateNewGame(string outputFolder) { // Find the game template description for a new game var template = TemplateManager.FindTemplates().FirstOrDefault(matchTemplate => matchTemplate.Id == NewGameTemplateGenerator.TemplateId); Assert.NotNull(template); var result = new LoggerResult(); var session = new PackageSession(); session.SolutionPath = Path.Combine(outputFolder, @"NewGame.sln"); var parameters = new SessionTemplateGeneratorParameters { Description = template, Logger = result, Name = "NewGame", OutputDirectory = outputFolder, Session = session, Unattended = true, }; NewGameTemplateGenerator.SetParameters(parameters, AssetRegistry.SupportedPlatforms.Where(x => x.Type == Core.PlatformType.Windows).Select(x => new SelectedSolutionPlatform(x, null))); var templateGenerator = TemplateManager.FindTemplateGenerator(parameters); templateGenerator.PrepareForRun(parameters); templateGenerator.Run(parameters); return(session); }
public override async Task <bool> PrepareForRun(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); var initialName = parameters.Name; var existingNames = ExtractReferencesList(parameters); initialName = NamingHelper.ComputeNewName(initialName, (Core.IO.UFile uf) => IsNameColliding(existingNames, uf), "{0}{1}"); var window = new ProjectLibraryWindow(initialName); window.LibNameInputValidator = (name) => IsNameColliding(existingNames, name); await window.ShowModal(); if (window.Result == DialogResult.Cancel) { return(false); } parameters.Name = Utilities.BuildValidProjectName(window.LibraryName); parameters.Namespace = Utilities.BuildValidNamespaceName(window.Namespace); var collision = IsNameColliding(existingNames, parameters.Name); return(!collision); // we cannot allow to flow the creation request in case of name collision, because the underlying viewmodel system does not have protection against it. }
protected sealed override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); var logger = parameters.Logger; var name = parameters.Name; var session = parameters.Session; // Log progress var projectName = name; ProjectTemplateGeneratorHelper.Progress(logger, $"Generating {projectName}...", 0, 1); // Generate the library List <string> generatedFiles; ProjectTemplateGeneratorHelper.AddOption(parameters, "Platforms", AssetRegistry.SupportedPlatforms); var project = ProjectTemplateGeneratorHelper.GenerateTemplate(parameters, "ProjectLibrary/ProjectLibrary.ttproj", projectName, PlatformType.Shared, null, ProjectType.Library, out generatedFiles); session.Projects.Add(project); // Load missing references session.LoadMissingReferences(parameters.Logger); // Log done ProjectTemplateGeneratorHelper.Progress(logger, "Done", 1, 1); return(true); }
private static List <string> ExtractReferencesList(SessionTemplateGeneratorParameters parameters) { // libraries and executables var referencedBinaryNames = new List <string>(); referencedBinaryNames.AddRange(parameters.Session.Projects.OfType <SolutionProject>().Where(x => x.FullPath != null).Select(x => x.FullPath.GetFileNameWithoutExtension())); return(referencedBinaryNames); }
public override Task <bool> PrepareForRun(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } parameters.Validate(); return(Task.FromResult(true)); }
protected override async Task <bool> AfterSave(SessionTemplateGeneratorParameters parameters) { // If package was not generated Package package; parameters.Tags.TryGetValue(GeneratedPackageKey, out package); if (package == null) { return(false); } // Update platforms for the sample var updateSample = TemplateManager.FindTemplates(package.Session).FirstOrDefault(template => template.Id == UpdatePlatformsTemplateGenerator.TemplateId); parameters.Description = updateSample; var updateParameters = new PackageTemplateGeneratorParameters(parameters, package); updateParameters.Unattended = true; var orientation = package.GetGameSettingsAsset()?.GetOrCreate <RenderingSettings>().DisplayOrientation ?? RequiredDisplayOrientation.Default; UpdatePlatformsTemplateGenerator.SetOrientation(updateParameters, (DisplayOrientation)orientation); UpdatePlatformsTemplateGenerator.SetPlatforms(updateParameters, parameters.GetTag(PlatformsKey)); // We want to force regeneration of Windows platform in case the sample .csproj is outdated UpdatePlatformsTemplateGenerator.SetForcePlatformRegeneration(updateParameters, true); var updateTemplate = UpdatePlatformsTemplateGenerator.Default; if (!await updateTemplate.PrepareForRun(updateParameters) || !updateTemplate.Run(updateParameters)) { // Remove the created project var path = Path.GetDirectoryName(parameters.Session.SolutionPath.ToWindowsPath()); try { Directory.Delete(path ?? "", true); } catch (IOException ex) { parameters.Logger.Error("Error when removing generated project.", ex); } catch (UnauthorizedAccessException ex) { parameters.Logger.Error("Error when removing generated project.", ex); } // Notify cancellation return(false); } // Save again post update SaveSession(parameters); // Restore NuGet packages again parameters.Logger.Verbose("Restore NuGet packages..."); await VSProjectHelper.RestoreNugetPackages(parameters.Logger, parameters.Session.SolutionPath); return(true); }
private static int Main(string[] args) { Console.WriteLine(@"Bootstrapping: " + args[0]); var xenkoDir = Environment.GetEnvironmentVariable("SiliconStudioXenkoDir"); var xenkoPkgPath = UPath.Combine(xenkoDir, new UFile("Xenko.xkpkg")); var session = PackageSession.Load(xenkoPkgPath); var generator = TemplateSampleGenerator.Default; var logger = new LoggerResult(); var parameters = new SessionTemplateGeneratorParameters { Session = session.Session }; TemplateSampleGenerator.SetDontAskForPlatforms(parameters, true); TemplateSampleGenerator.SetPlatforms(parameters, AssetRegistry.SupportedPlatforms.ToList()); var outputPath = UPath.Combine(new UDirectory(xenkoDir), new UDirectory("samplesGenerated")); outputPath = UPath.Combine(outputPath, new UDirectory(args[0])); var xenkoTemplates = session.Session.Packages.First().Templates; parameters.Description = xenkoTemplates.First(x => x.Group.StartsWith("Samples") && x.Id == new Guid(args[1])); parameters.Name = args[0]; parameters.Namespace = args[0]; parameters.OutputDirectory = outputPath; parameters.Logger = logger; if (!generator.PrepareForRun(parameters)) { logger.Error("PrepareForRun returned false for the TemplateSampleGenerator"); } if (!generator.Run(parameters)) { logger.Error("Run returned false for the TemplateSampleGenerator"); } var updaterTemplate = xenkoTemplates.First(x => x.FullPath.ToString().EndsWith("UpdatePlatforms.xktpl")); parameters.Description = updaterTemplate; Console.WriteLine(logger.ToText()); return(logger.HasErrors ? 1 : 0); }
/// <summary> /// Sets the parameters required by this template when running in <see cref="TemplateGeneratorParameters.Unattended"/> mode. /// </summary> public static void SetParameters([NotNull] SessionTemplateGeneratorParameters parameters, [NotNull] IEnumerable <SelectedSolutionPlatform> platforms, GraphicsProfile graphicsProfile = GraphicsProfile.Level_10_0, bool isHDR = true, DisplayOrientation orientation = DisplayOrientation.Default, IEnumerable <UDirectory> assets = null) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (platforms == null) { throw new ArgumentNullException(nameof(platforms)); } parameters.SetTag(PlatformsKey, new List <SelectedSolutionPlatform>(platforms)); if (assets != null) { parameters.SetTag(AssetsKey, new List <UDirectory>(assets)); } parameters.SetTag(IsHDRKey, isHDR); parameters.SetTag(GraphicsProfileKey, graphicsProfile); parameters.SetTag(OrientationKey, orientation); }
private void CreateCameraScript(SessionTemplateGeneratorParameters parameters, Package package, ProjectReference projectGameReference, string projectGameName, Entity cameraEntity, AssetItem sceneAssetItem) { var logger = parameters.Logger; // Create camera script var cameraScriptTemplate = TemplateManager.FindTemplates(package.Session).OfType <TemplateAssetDescription>().FirstOrDefault(x => x.DefaultOutputName == CameraScriptDefaultOutputName); if (cameraScriptTemplate == null) { throw new InvalidOperationException($"Could not find template for script '{CameraScriptDefaultOutputName}'"); } var cameraScriptParameters = new AssetTemplateGeneratorParameters(projectGameName) { Name = cameraScriptTemplate.DefaultOutputName, Description = cameraScriptTemplate, Namespace = parameters.Namespace, Package = package, Logger = logger, Unattended = true, }; ScriptTemplateGenerator.SetClassName(cameraScriptParameters, cameraScriptTemplate.DefaultOutputName); if (!ScriptTemplateGenerator.Default.PrepareForRun(cameraScriptParameters).Result || !ScriptTemplateGenerator.Default.Run(cameraScriptParameters)) { throw new InvalidOperationException($"Could not create script '{CameraScriptDefaultOutputName}'"); } // Force save after having created the script // Note: We do that AFTER GameSettings is dirty, otherwise it would ask for an assembly reload (game settings saved might mean new graphics API) SaveSession(parameters); parameters.Logger.Verbose("Restore NuGet packages..."); VSProjectHelper.RestoreNugetPackages(parameters.Logger, parameters.Session.SolutionPath).Wait(); logger.Verbose("Compiling game assemblies..."); parameters.Session.UpdateAssemblyReferences(logger); if (package.State < PackageState.DependenciesReady) { logger.Warning("Assembly references were not compiled properly"); return; } logger.Verbose("Game assemblies compiled..."); // Create the Camera script in Camera entity // Since we rely on lot of string check, added some null checking and try/catch to not crash the apps in case something went wrong // We only emit warnings rather than errors, so that the user could continue try { var gameAssembly = package.LoadedAssemblies.FirstOrDefault(x => x.ProjectReference == projectGameReference)?.Assembly; if (gameAssembly == null) { logger.Warning("Can't load Game assembly"); return; } var cameraScriptType = package.LoadedAssemblies.First(x => x.ProjectReference == projectGameReference).Assembly.GetType($"{parameters.Namespace}.{CameraScriptDefaultOutputName}"); if (cameraScriptType == null) { logger.Warning($"Could not find script '{CameraScriptDefaultOutputName}' in Game assembly"); return; } cameraEntity.Add((EntityComponent)Activator.CreateInstance(cameraScriptType)); sceneAssetItem.IsDirty = true; } catch (Exception e) { logger.Warning($"Could not instantiate {CameraScriptDefaultOutputName} script", e); } }
/// <summary> /// Copy any referenced asset packages to the project's folder /// </summary> private static void CopyAssetPacks(SessionTemplateGeneratorParameters parameters) { var logger = parameters.Logger; var installDir = DirectoryHelper.GetInstallationDirectory("Xenko"); var assetPackagesDir = (DirectoryHelper.IsRootDevDirectory(installDir)) ? UDirectory.Combine(installDir, @"samples\Templates\Packs") : UDirectory.Combine(ProjectTemplateGeneratorHelper.GetTemplateDataDirectory(parameters.Description).GetParent(), @"Samples\Templates\Packs"); var assetPacks = parameters.TryGetTag(AssetsKey); if (assetPacks == null) { return; } try { var outAssetDir = UPath.Combine(parameters.OutputDirectory, (UDirectory)"Assets"); var outResourceDir = UPath.Combine(parameters.OutputDirectory, (UDirectory)"Resources"); foreach (var uDirectory in assetPacks) { var packageDir = UDirectory.Combine(assetPackagesDir, uDirectory); var inputAssetDir = UDirectory.Combine(packageDir, "Assets"); foreach (var directory in FileUtility.EnumerateDirectories(inputAssetDir, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { var relativeFile = new UFile(file.FullName).MakeRelative(inputAssetDir); var outputFile = UPath.Combine(outAssetDir, relativeFile); var outputFileDirectory = outputFile.GetParent(); if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } File.Copy(file.FullName, outputFile, true); } } var inputResourceDir = UDirectory.Combine(packageDir, "Resources"); foreach (var directory in FileUtility.EnumerateDirectories(inputResourceDir, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { var relativeFile = new UFile(file.FullName).MakeRelative(inputResourceDir); var outputFile = UPath.Combine(outResourceDir, relativeFile); { // Create the output directory if needed var outputFileDirectory = outputFile.GetParent(); if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } } File.Copy(file.FullName, outputFile, true); } } } } catch (Exception ex) { logger.Error("Unexpected exception while copying asset packages", ex); } }
/// <summary> /// Creates default scene, with a ground plane, sphere, directional light and camera. /// If graphicsProfile is 10+, add cubemap light, otherwise ambient light. /// Also properly setup graphics pipeline depending on if HDR is set or not /// </summary> /// <param name="parameters">The parameters.</param> /// <param name="package">The package in which to create these assets.</param> private void CreateAndSetNewScene(SessionTemplateGeneratorParameters parameters, Package package, ProjectReference projectGameReference, string projectGameName) { var logger = parameters.Logger; var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var isHDR = parameters.GetTag(IsHDRKey); if (graphicsProfile < GraphicsProfile.Level_10_0) { isHDR = false; } // Create the material for the sphere var sphereMaterial = new MaterialAsset { Attributes = { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF8C8C8C))), DiffuseModel = new MaterialDiffuseLambertModelFeature(), } }; if (isHDR) { // Create HDR part of material sphereMaterial.Attributes.Specular = new MaterialMetalnessMapFeature(new ComputeFloat(1.0f)); sphereMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature(); sphereMaterial.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeFloat(0.65f)); } var sphereMaterialAssetItem = new AssetItem("Sphere Material", sphereMaterial); package.Assets.Add(sphereMaterialAssetItem); sphereMaterialAssetItem.IsDirty = true; // Create the sphere model var sphereModel = new ProceduralModelAsset { Type = new SphereProceduralModel { MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(sphereMaterialAssetItem.Id, sphereMaterialAssetItem.Location) }, Tessellation = 30, }, }; var sphereModelAssetItem = new AssetItem("Sphere", sphereModel); package.Assets.Add(sphereModelAssetItem); sphereModelAssetItem.IsDirty = true; // Create sphere entity var sphereEntity = new Entity("Sphere") { new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(sphereModelAssetItem.Id, sphereModelAssetItem.Location)) }; sphereEntity.Transform.Position = new Vector3(0.0f, 0.5f, 0.0f); // Create the material for the ground var groundMaterial = new MaterialAsset { Attributes = { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF242424))), DiffuseModel = new MaterialDiffuseLambertModelFeature(), } }; if (isHDR) { // Create HDR part of material groundMaterial.Attributes.Specular = new MaterialMetalnessMapFeature(new ComputeFloat(0.0f)); groundMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature(); groundMaterial.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeFloat(0.1f)); } var groundMaterialAssetItem = new AssetItem("Ground Material", groundMaterial); package.Assets.Add(groundMaterialAssetItem); groundMaterialAssetItem.IsDirty = true; // Create the ground model var groundModel = new ProceduralModelAsset { Type = new PlaneProceduralModel { Size = new Vector2(10.0f, 10.0f), MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(groundMaterialAssetItem.Id, groundMaterialAssetItem.Location) }, }, }; var groundModelAssetItem = new AssetItem("Ground", groundModel); package.Assets.Add(groundModelAssetItem); groundModelAssetItem.IsDirty = true; // Create the ground entity var groundEntity = new Entity("Ground") { new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(groundModelAssetItem.Id, groundModelAssetItem.Location)) }; // Copy file in Resources var skyboxFilename = (UFile)(isHDR ? "skybox_texture_hdr.dds" : "skybox_texture_ldr.dds"); try { var resources = UPath.Combine(parameters.OutputDirectory, (UDirectory)"Resources"); Directory.CreateDirectory(resources.ToWindowsPath()); // TODO: Hardcoded due to the fact that part of the template is in another folder in dev build // We might want to extend TemplateFolder to support those cases var dataDirectory = ProjectTemplateGeneratorHelper.GetTemplateDataDirectory(parameters.Description); var skyboxFullPath = UPath.Combine(dataDirectory, skyboxFilename).ToWindowsPath(); File.Copy(skyboxFullPath, UPath.Combine(resources, skyboxFilename).ToWindowsPath(), true); } catch (Exception ex) { logger.Error("Unexpected exception while copying cubemap", ex); } // Create the texture asset var skyboxTextureAsset = new TextureAsset { Source = Path.Combine(@"..\..\Resources", skyboxFilename), IsCompressed = isHDR, Type = new ColorTextureType { UseSRgbSampling = false } }; var skyboxTextureAssetItem = new AssetItem("Skybox texture", skyboxTextureAsset); package.Assets.Add(skyboxTextureAssetItem); skyboxTextureAssetItem.IsDirty = true; // Create the skybox asset var skyboxAsset = new SkyboxAsset { CubeMap = AttachedReferenceManager.CreateProxyObject <Texture>(skyboxTextureAssetItem.Id, skyboxTextureAssetItem.Location) }; var skyboxAssetItem = new AssetItem("Skybox", skyboxAsset); package.Assets.Add(skyboxAssetItem); skyboxAssetItem.IsDirty = true; // Create the scene var defaultSceneAsset = isHDR ? SceneHDRFactory.Create() : SceneLDRFactory.Create(); defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(groundEntity)); defaultSceneAsset.Hierarchy.RootParts.Add(groundEntity); defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(sphereEntity)); defaultSceneAsset.Hierarchy.RootParts.Add(sphereEntity); var sceneAssetItem = new AssetItem(GameSettingsAsset.DefaultSceneLocation, defaultSceneAsset); package.Assets.Add(sceneAssetItem); sceneAssetItem.IsDirty = true; // Sets the scene created as default in the shared profile var gameSettingsAsset = package.Assets.Find(GameSettingsAsset.GameSettingsLocation); if (gameSettingsAsset != null) { ((GameSettingsAsset)gameSettingsAsset.Asset).DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(sceneAssetItem.Id, sceneAssetItem.Location); gameSettingsAsset.IsDirty = true; } var skyboxEntity = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.SkyboxEntityName); skyboxEntity.Get <BackgroundComponent>().Texture = skyboxAsset.CubeMap; if (isHDR) { skyboxEntity.Get <LightComponent>().Type = new LightSkybox { Skybox = AttachedReferenceManager.CreateProxyObject <Skybox>(skyboxAssetItem.Id, skyboxAssetItem.Location) }; } var cameraEntity = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.CameraEntityName); var graphicsCompositor = package.Assets.Select(x => x.Asset).OfType <GraphicsCompositorAsset>().Single(); cameraEntity.Components.Get <CameraComponent>().Slot = graphicsCompositor.Cameras.Single().ToSlotId(); // Let's add camera script CreateCameraScript(parameters, package, projectGameReference, projectGameName, cameraEntity, sceneAssetItem); }
private void AddAssets(SessionTemplateGeneratorParameters parameters, Package package, ProjectReference projectGameReference, string projectGameName) { // Sets a default scene CreateAndSetNewScene(parameters, package, projectGameReference, projectGameName); }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // Structure of files to generate: // $Name$.xkpkg // $Name$.targets // Assets\ // $Name$.Game\ // $Name$.Windows\ // $Name$.Android\ // $Name$.iOS\ var logger = parameters.Logger; var platforms = parameters.GetTag(PlatformsKey); var name = parameters.Name; var outputDirectory = parameters.OutputDirectory; var orientation = parameters.GetTag(OrientationKey); // Generate the package var package = NewPackageTemplateGenerator.GeneratePackage(parameters); // Generate projects for this package var session = parameters.Session; var sharedProfile = package.Profiles.FindSharedProfile(); // Setup the assets folder Directory.CreateDirectory(UPath.Combine(outputDirectory, (UDirectory)"Assets/Shared")); //write gitignore WriteGitIgnore(parameters); var previousCurrent = session.CurrentPackage; session.CurrentPackage = package; var projectGameName = Utilities.BuildValidNamespaceName(name) + ".Game"; var stepIndex = 0; var stepCount = platforms.Count + 1; // Log progress ProjectTemplateGeneratorHelper.Progress(logger, $"Generating {projectGameName}...", stepIndex++, stepCount); // Generate the Game library var projectGameReference = ProjectTemplateGeneratorHelper.GenerateTemplate(parameters, platforms, package, "ProjectLibrary.Game/ProjectLibrary.Game.ttproj", projectGameName, PlatformType.Shared, null, null, ProjectType.Library, orientation); projectGameReference.Type = ProjectType.Library; sharedProfile.ProjectReferences.Add(projectGameReference); // Add Effects as an asset folder in order to load xksl sharedProfile.AssetFolders.Add(new AssetFolder(projectGameName + "/Effects")); // Generate executable projects for each platform ProjectTemplateGeneratorHelper.UpdatePackagePlatforms(parameters, platforms, orientation, projectGameReference.Id, name, package, false); // Add asset packages CopyAssetPacks(parameters); // Load assets from HDD package.LoadTemporaryAssets(logger); // Validate assets package.ValidateAssets(true, false, logger); // Setup GraphicsCompositor using DefaultGraphicsCompositor var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var defaultCompositorUrl = graphicsProfile >= GraphicsProfile.Level_10_0 ? XenkoPackageUpgrader.DefaultGraphicsCompositorLevel10Url : XenkoPackageUpgrader.DefaultGraphicsCompositorLevel9Url; var defaultCompositor = session.FindAsset(defaultCompositorUrl); var graphicsCompositor = new AssetItem("GraphicsCompositor", defaultCompositor.CreateDerivedAsset()); package.Assets.Add(graphicsCompositor); graphicsCompositor.IsDirty = true; // Setup GameSettingsAsset var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.GetOrCreate <EditorSettings>().RenderingMode = parameters.GetTag(IsHDRKey) ? RenderingMode.HDR : RenderingMode.LDR; gameSettingsAsset.GraphicsCompositor = AttachedReferenceManager.CreateProxyObject <GraphicsCompositor>(graphicsCompositor.ToReference()); var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(); renderingSettings.DefaultGraphicsProfile = parameters.GetTag(GraphicsProfileKey); renderingSettings.DisplayOrientation = (RequiredDisplayOrientation)orientation; var gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = true; // Add assets to the package AddAssets(parameters, package, projectGameReference, projectGameName); // Log done ProjectTemplateGeneratorHelper.Progress(logger, "Done", stepCount, stepCount); session.CurrentPackage = previousCurrent; return(true); }
private static void GenerateUnitTestProject(string outputDirectory, string templateFile, string name, string projectNamespace) { var projectTemplate = ProjectTemplate.Load(templateFile); // Force reference to Xenko.Assets (to have acess to SolutionPlatform) projectTemplate.Assemblies.Add(typeof(GraphicsProfile).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(XenkoConfig).Assembly.FullName); var options = new Dictionary <string, object>(); // When generating over an existing set of files, retrieve the existing IDs // for better incrementality Guid projectGuid, assetId; GetExistingGuid(outputDirectory, name + ".Windows.csproj", out projectGuid); GetExistingAssetId(outputDirectory, name + ".xkpkg", out assetId); var session = new PackageSession(); var result = new LoggerResult(); var templateGeneratorParameters = new SessionTemplateGeneratorParameters(); templateGeneratorParameters.OutputDirectory = outputDirectory; templateGeneratorParameters.Session = session; templateGeneratorParameters.Name = name; templateGeneratorParameters.Logger = result; templateGeneratorParameters.Description = new TemplateDescription(); templateGeneratorParameters.Id = assetId; if (!PackageUnitTestGenerator.Default.PrepareForRun(templateGeneratorParameters).Result) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.PrepareForRun returned false"); return; } if (!PackageUnitTestGenerator.Default.Run(templateGeneratorParameters)) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.Run returned false"); return; } if (result.HasErrors) { Console.WriteLine($"Error generating package: {result.ToText()}"); return; } var package = session.LocalPackages.Single(); var previousCurrent = session.CurrentPackage; session.CurrentPackage = package; // Compute Xenko Sdk relative path // We are supposed to be in standard output binary folder, so Xenko root should be at ..\.. var xenkoPath = UPath.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), new UDirectory(@"..\..")); var xenkoRelativePath = new UDirectory(xenkoPath) .MakeRelative(outputDirectory) .ToString() .Replace('/', '\\'); xenkoRelativePath = xenkoRelativePath.TrimEnd('\\'); options["Namespace"] = projectNamespace ?? name; options["Package"] = package; options["Platforms"] = new List <SolutionPlatform>(AssetRegistry.SupportedPlatforms); options["XenkoSdkRelativeDir"] = xenkoRelativePath; // Generate project template result = projectTemplate.Generate(outputDirectory, name, projectGuid, options); if (result.HasErrors) { Console.WriteLine("Error generating solution: {0}", result.ToText()); return; } var sharedProfile = package.Profiles.FindSharedProfile(); // Setup the assets folder Directory.CreateDirectory(UPath.Combine(outputDirectory, (UDirectory)"Assets/Shared")); // Add Windows test as Shared library var projectWindowsRef = new ProjectReference(projectGuid, UPath.Combine(outputDirectory, (UFile)(name + ".Windows.csproj")), SiliconStudio.Assets.ProjectType.Library); sharedProfile.ProjectReferences.Add(projectWindowsRef); // Generate executable projects for each platform foreach (var platform in AssetRegistry.SupportedPlatforms) { var platformProfile = new PackageProfile(platform.Name) { Platform = platform.Type }; platformProfile.AssetFolders.Add(new AssetFolder("Assets/" + platform.Name)); // Log progress var projectName = name + "." + platform.Type; // Create project reference var projectPlatformRef = new ProjectReference(projectGuid, UPath.Combine(outputDirectory, (UFile)(projectName + ".csproj")), SiliconStudio.Assets.ProjectType.Executable); platformProfile.ProjectReferences.Add(projectPlatformRef); package.Profiles.Add(platformProfile); } session.CurrentPackage = previousCurrent; session.Save(result); if (result.HasErrors) { Console.WriteLine("Error saving package: {0}", result.ToText()); return; } }
private static void GenerateUnitTestProject(string outputDirectory, string templateFile, string name, string projectNamespace) { var projectTemplate = ProjectTemplate.Load(templateFile); // Force reference to Xenko.Assets (to have acess to SolutionPlatform) projectTemplate.Assemblies.Add(typeof(GraphicsProfile).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(XenkoConfig).Assembly.FullName); var options = new Dictionary<string, object>(); // When generating over an existing set of files, retrieve the existing IDs // for better incrementality Guid projectGuid, assetId; GetExistingGuid(outputDirectory, name + ".Windows.csproj", out projectGuid); GetExistingAssetId(outputDirectory, name + ".xkpkg", out assetId); var session = new PackageSession(); var result = new LoggerResult(); var templateGeneratorParameters = new SessionTemplateGeneratorParameters(); templateGeneratorParameters.OutputDirectory = outputDirectory; templateGeneratorParameters.Session = session; templateGeneratorParameters.Name = name; templateGeneratorParameters.Logger = result; templateGeneratorParameters.Description = new TemplateDescription(); templateGeneratorParameters.Id = assetId; if (!PackageUnitTestGenerator.Default.PrepareForRun(templateGeneratorParameters).Result) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.PrepareForRun returned false"); return; } if (!PackageUnitTestGenerator.Default.Run(templateGeneratorParameters)) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.Run returned false"); return; } if (result.HasErrors) { Console.WriteLine($"Error generating package: {result.ToText()}"); return; } var package = session.LocalPackages.Single(); var previousCurrent = session.CurrentPackage; session.CurrentPackage = package; // Compute Xenko Sdk relative path // We are supposed to be in standard output binary folder, so Xenko root should be at ..\.. var xenkoPath = UPath.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), new UDirectory(@"..\..")); var xenkoRelativePath = new UDirectory(xenkoPath) .MakeRelative(outputDirectory) .ToString() .Replace('/', '\\'); xenkoRelativePath = xenkoRelativePath.TrimEnd('\\'); options["Namespace"] = projectNamespace ?? name; options["Package"] = package; options["Platforms"] = new List<SolutionPlatform>(AssetRegistry.SupportedPlatforms); options["XenkoSdkRelativeDir"] = xenkoRelativePath; // Generate project template result = projectTemplate.Generate(outputDirectory, name, projectGuid, options); if (result.HasErrors) { Console.WriteLine("Error generating solution: {0}", result.ToText()); return; } var sharedProfile = package.Profiles.FindSharedProfile(); // Setup the assets folder Directory.CreateDirectory(UPath.Combine(outputDirectory, (UDirectory)"Assets/Shared")); // Add Windows test as Shared library var projectWindowsRef = new ProjectReference { Id = projectGuid, Location = UPath.Combine(outputDirectory, (UFile)(name + ".Windows.csproj")), Type = SiliconStudio.Assets.ProjectType.Library }; sharedProfile.ProjectReferences.Add(projectWindowsRef); // Generate executable projects for each platform foreach (var platform in AssetRegistry.SupportedPlatforms) { var platformProfile = new PackageProfile(platform.Name) { Platform = platform.Type }; platformProfile.AssetFolders.Add(new AssetFolder("Assets/"+ platform.Name)); // Log progress var projectName = name + "." + platform.Type; // Create project reference var projectPlatformRef = new ProjectReference { Id = projectGuid, Location = UPath.Combine(outputDirectory, (UFile)(projectName + ".csproj")), Type = SiliconStudio.Assets.ProjectType.Executable }; platformProfile.ProjectReferences.Add(projectPlatformRef); // Add build configuration per platform platform.Properties.CopyTo(platformProfile.Properties, true); package.Profiles.Add(platformProfile); } session.CurrentPackage = previousCurrent; result = session.Save(); if (result.HasErrors) { Console.WriteLine("Error saving package: {0}", result.ToText()); return; } }
private static int Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Invalid number of arguments.\n"); Console.WriteLine("Usage: Xenko.SamplesBootstrapper.exe SampleName SampleGuid"); return(1); } PackageSessionPublicHelper.FindAndSetMSBuildVersion(); Console.WriteLine(@"Bootstrapping: " + args[0]); var session = new PackageSession(); var xenkoPkg = PackageStore.Instance.DefaultPackage; Console.WriteLine("Using Xenko from " + xenkoPkg.FullPath + "..."); var xenkoDir = Path.GetDirectoryName(xenkoPkg.FullPath); var generator = TemplateSampleGenerator.Default; var logger = new LoggerResult(); // Ensure progress is shown while it is happening. logger.MessageLogged += (sender, eventArgs) => Console.WriteLine(eventArgs.Message.Text); var parameters = new SessionTemplateGeneratorParameters { Session = session }; parameters.Unattended = true; TemplateSampleGenerator.SetParameters(parameters, AssetRegistry.SupportedPlatforms.Select(x => new SelectedSolutionPlatform(x, x.Templates.FirstOrDefault())).ToList()); var outputPath = UPath.Combine(new UDirectory(xenkoDir), new UDirectory("samplesGenerated")); outputPath = UPath.Combine(outputPath, new UDirectory(args[0])); session.SolutionPath = UPath.Combine <UFile>(outputPath, args[0] + ".sln"); // Properly delete previous version if (Directory.Exists(outputPath)) { try { Directory.Delete(outputPath, true); } catch (Exception) { logger.Warning($"Unable to delete directory [{outputPath}]"); } } var xenkoTemplates = xenkoPkg.Templates; parameters.Description = xenkoTemplates.First(x => x.Id == new Guid(args[1])); parameters.Name = args[0]; parameters.Namespace = args[0]; parameters.OutputDirectory = outputPath; parameters.Logger = logger; if (!generator.PrepareForRun(parameters).Result) { logger.Error("PrepareForRun returned false for the TemplateSampleGenerator"); } if (!generator.Run(parameters)) { logger.Error("Run returned false for the TemplateSampleGenerator"); } var updaterTemplate = xenkoTemplates.First(x => x.FullPath.ToString().EndsWith("UpdatePlatforms.xktpl")); parameters.Description = updaterTemplate; return(logger.HasErrors ? 1 : 0); }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { return(GeneratePackage(parameters) != null); }
private static void GenerateUnitTestProject(string outputDirectory, string templateFile, string name, string projectNamespace) { var projectTemplate = ProjectTemplate.Load(templateFile); // Force reference to Stride.Assets (to have acess to SolutionPlatform) projectTemplate.Assemblies.Add(typeof(GraphicsProfile).Assembly.FullName); projectTemplate.Assemblies.Add(typeof(StrideConfig).Assembly.FullName); var options = new Dictionary <string, object>(); // When generating over an existing set of files, retrieve the existing IDs // for better incrementality Guid projectGuid, assetId; GetExistingGuid(outputDirectory, name + ".Windows.csproj", out projectGuid); GetExistingAssetId(outputDirectory, name + ".sdpkg", out assetId); var session = new PackageSession(); var result = new LoggerResult(); var templateGeneratorParameters = new SessionTemplateGeneratorParameters(); templateGeneratorParameters.OutputDirectory = outputDirectory; templateGeneratorParameters.Session = session; templateGeneratorParameters.Name = name; templateGeneratorParameters.Logger = result; templateGeneratorParameters.Description = new TemplateDescription(); templateGeneratorParameters.Id = assetId; templateGeneratorParameters.Namespace = projectNamespace; if (!PackageUnitTestGenerator.Default.PrepareForRun(templateGeneratorParameters).Result) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.PrepareForRun returned false"); return; } if (!PackageUnitTestGenerator.Default.Run(templateGeneratorParameters)) { Console.WriteLine(@"Error generating package: PackageUnitTestGenerator.Run returned false"); return; } if (result.HasErrors) { Console.WriteLine($"Error generating package: {result.ToText()}"); return; } var project = session.Projects.OfType <SolutionProject>().Single(); var previousCurrent = session.CurrentProject; session.CurrentProject = project; // Compute Stride Sdk relative path // We are supposed to be in standard output binary folder, so Stride root should be at ..\.. var stridePath = UPath.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), new UDirectory(@"..\..")); var strideRelativePath = new UDirectory(stridePath) .MakeRelative(outputDirectory) .ToString() .Replace('/', '\\'); strideRelativePath = strideRelativePath.TrimEnd('\\'); options["Namespace"] = projectNamespace ?? name; options["Package"] = project.Package; options["Platforms"] = new List <SolutionPlatform>(AssetRegistry.SupportedPlatforms); options["StrideSdkRelativeDir"] = strideRelativePath; // Generate project template result = projectTemplate.Generate(outputDirectory, name, projectGuid, options); if (result.HasErrors) { Console.WriteLine("Error generating solution: {0}", result.ToText()); return; } // Setup the assets folder Directory.CreateDirectory(UPath.Combine(outputDirectory, (UDirectory)"Assets/Shared")); session.CurrentProject = previousCurrent; session.Save(result); if (result.HasErrors) { Console.WriteLine("Error saving package: {0}", result.ToText()); return; } }
/// <summary> /// Copy any referenced asset packages to the project's folder /// </summary> private static void CopyAssetPacks(SessionTemplateGeneratorParameters parameters, Package package) { var logger = parameters.Logger; var presentationPackageFile = PackageStore.Instance.GetPackageFileName("Stride.Samples.Templates", new PackageVersionRange(new PackageVersion(Stride.Samples.Templates.ThisPackageVersion.Current))); var assetPackagesDir = UDirectory.Combine(presentationPackageFile.GetFullDirectory(), @"Templates\Samples\Templates\Packs"); var assetPacks = parameters.TryGetTag(AssetsKey); if (assetPacks == null) { return; } try { var outAssetDir = UPath.Combine(package.RootDirectory, (UDirectory)"Assets"); var outResourceDir = UPath.Combine(package.RootDirectory, (UDirectory)"Resources"); foreach (var uDirectory in assetPacks) { var packageDir = UDirectory.Combine(assetPackagesDir, uDirectory); var inputAssetDir = UDirectory.Combine(packageDir, "Assets"); foreach (var directory in FileUtility.EnumerateDirectories(inputAssetDir, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { var relativeFile = new UFile(file.FullName).MakeRelative(inputAssetDir); var outputFile = UPath.Combine(outAssetDir, relativeFile); var outputFileDirectory = outputFile.GetParent(); if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } File.Copy(file.FullName, outputFile, true); } } var inputResourceDir = UDirectory.Combine(packageDir, "Resources"); foreach (var directory in FileUtility.EnumerateDirectories(inputResourceDir, SearchDirection.Down)) { foreach (var file in directory.GetFiles()) { var relativeFile = new UFile(file.FullName).MakeRelative(inputResourceDir); var outputFile = UPath.Combine(outResourceDir, relativeFile); { // Create the output directory if needed var outputFileDirectory = outputFile.GetParent(); if (!Directory.Exists(outputFileDirectory)) { Directory.CreateDirectory(outputFileDirectory); } } File.Copy(file.FullName, outputFile, true); } } } } catch (Exception ex) { logger.Error("Unexpected exception while copying asset packages", ex); } }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // Structure of files to generate: // $Name$.sdpkg // $Name$.targets // Assets\ // $Name$.Game\ // $Name$.Windows\ // $Name$.Android\ // $Name$.iOS\ var logger = parameters.Logger; var platforms = parameters.GetTag(PlatformsKey); var name = parameters.Name; var outputDirectory = parameters.OutputDirectory; var orientation = parameters.GetTag(OrientationKey); // Generate the package //var package = NewPackageTemplateGenerator.GeneratePackage(parameters); // Generate projects for this package var session = parameters.Session; var projectGameName = Utilities.BuildValidNamespaceName(name); var stepIndex = 0; var stepCount = platforms.Count + 1; // Log progress ProjectTemplateGeneratorHelper.Progress(logger, $"Generating {projectGameName}...", stepIndex++, stepCount); // Generate the Game library var project = ProjectTemplateGeneratorHelper.GenerateTemplate(parameters, platforms, "ProjectLibrary.Game/ProjectLibrary.Game.ttproj", projectGameName, PlatformType.Shared, null, ProjectType.Library, orientation); var package = project.Package; //write gitignore WriteGitIgnore(parameters); // Setup the assets folder //Directory.CreateDirectory(UPath.Combine(package.RootDirectory, (UDirectory)"Assets/Shared")); session.Projects.Add(project); // Load missing references session.LoadMissingDependencies(parameters.Logger); // Load dependency assets (needed for camera script template) session.LoadMissingAssets(parameters.Logger, project.FlattenedDependencies.Select(x => x.Package).NotNull()); // Add Effects as an asset folder in order to load sdsl package.AssetFolders.Add(new AssetFolder("Effects")); var packageParameters = new PackageTemplateGeneratorParameters { Name = package.Meta.Name, OutputDirectory = package.FullPath.GetFullDirectory(), Description = parameters.Description, Package = package, Logger = parameters.Logger, Namespace = parameters.Namespace }; // Generate executable projects for each platform var platformProjects = ProjectTemplateGeneratorHelper.UpdatePackagePlatforms(packageParameters, platforms, orientation, false).ToList(); // Add asset packages CopyAssetPacks(parameters, package); // Create camera script var cameraScriptTemplate = TemplateManager.FindTemplates(package.Session).OfType <TemplateAssetDescription>().FirstOrDefault(x => x.DefaultOutputName == CameraScriptDefaultOutputName); if (cameraScriptTemplate == null) { throw new InvalidOperationException($"Could not find template for script '{CameraScriptDefaultOutputName}'"); } var cameraScriptParameters = new AssetTemplateGeneratorParameters(string.Empty) { Name = cameraScriptTemplate.DefaultOutputName, Description = cameraScriptTemplate, Namespace = parameters.Namespace, Package = package, Logger = logger, Unattended = true, }; ScriptTemplateGenerator.SetClassName(cameraScriptParameters, cameraScriptTemplate.DefaultOutputName); if (!ScriptTemplateGenerator.Default.PrepareForRun(cameraScriptParameters).Result || !ScriptTemplateGenerator.Default.Run(cameraScriptParameters)) { throw new InvalidOperationException($"Could not create script '{CameraScriptDefaultOutputName}'"); } // Force save after having created the script // Note: We do that AFTER GameSettings is dirty, otherwise it would ask for an assembly reload (game settings saved might mean new graphics API) SaveSession(parameters); // Load missing references session.LoadMissingReferences(parameters.Logger); // Setup GraphicsCompositor using DefaultGraphicsCompositor var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var defaultCompositorUrl = graphicsProfile >= GraphicsProfile.Level_10_0 ? StridePackageUpgrader.DefaultGraphicsCompositorLevel10Url : StridePackageUpgrader.DefaultGraphicsCompositorLevel9Url; var defaultCompositor = session.FindAsset(defaultCompositorUrl); var graphicsCompositor = new AssetItem("GraphicsCompositor", defaultCompositor.CreateDerivedAsset()); package.Assets.Add(graphicsCompositor); graphicsCompositor.IsDirty = true; // Setup GameSettingsAsset var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.GetOrCreate <EditorSettings>().RenderingMode = parameters.GetTag(IsHDRKey) ? RenderingMode.HDR : RenderingMode.LDR; gameSettingsAsset.GraphicsCompositor = AttachedReferenceManager.CreateProxyObject <GraphicsCompositor>(graphicsCompositor.ToReference()); var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(); renderingSettings.DefaultGraphicsProfile = parameters.GetTag(GraphicsProfileKey); renderingSettings.DisplayOrientation = (RequiredDisplayOrientation)orientation; var gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = true; // Add assets to the package AddAssets(parameters, package, projectGameName); // Log done ProjectTemplateGeneratorHelper.Progress(logger, "Done", stepCount, stepCount); // Set current project session.CurrentProject = platformProjects.FirstOrDefault(x => x.Platform == PlatformType.Windows) ?? project; return(true); }
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 packageFile = Path.ChangeExtension(description.FullPath, Package.PackageFileExtension); if (!File.Exists(packageFile)) { log.Error($"Unable to find package [{packageFile}]"); return(false); } var packageLoadResult = new LoggerResult(); var package = Package.Load(packageLoadResult, packageFile, new PackageLoadParameters { AutoLoadTemporaryAssets = false, AutoCompileProjects = false, LoadAssemblyReferences = false, }); packageLoadResult.CopyTo(log); if (packageLoadResult.HasErrors) { return(false); } // We are going to replace all projects id by new ids var idsToReplace = package.Profiles.SelectMany(profile => profile.ProjectReferences).Select(project => project.Id).Distinct().ToDictionary(guid => guid.ToString("D"), guid => Guid.NewGuid(), StringComparer.OrdinalIgnoreCase); idsToReplace.Add(package.Id.ToString("D"), Guid.NewGuid()); // Add dependencies foreach (var packageReference in package.LocalDependencies) { description.FullPath.GetFullDirectory(); var referencePath = UPath.Combine(description.FullPath.GetFullDirectory(), packageReference.Location); if (!File.Exists(referencePath)) { log.Error($"Unable to find dependency package [{referencePath}]"); return(false); } var referenceLoadResult = new LoggerResult(); var reference = Package.Load(referenceLoadResult, referencePath, new PackageLoadParameters { AutoLoadTemporaryAssets = false, AutoCompileProjects = false, LoadAssemblyReferences = false, }); referenceLoadResult.CopyTo(log); if (referenceLoadResult.HasErrors) { return(false); } var extraIdsToReplace = reference.Profiles.SelectMany(profile => profile.ProjectReferences).Select(project => project.Id).Distinct().ToDictionary(guid => guid.ToString("D"), guid => Guid.NewGuid(), StringComparer.OrdinalIgnoreCase); idsToReplace.AddRange(extraIdsToReplace); } var guidRegexPattern = new StringBuilder(); guidRegexPattern.Append("("); guidRegexPattern.Append(string.Join("|", idsToReplace.Keys)); guidRegexPattern.Append(")"); var regexes = new List <Tuple <Regex, MatchEvaluator> >(); var guidRegex = new Tuple <Regex, MatchEvaluator>(new Regex(guidRegexPattern.ToString(), RegexOptions.IgnoreCase), match => idsToReplace[match.Groups[1].Value].ToString("D")); regexes.Add(guidRegex); 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); UFile packageOutputFile = 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(); // Grab the name of the output package file var isPackageFile = (packageOutputFile == null && file.FullName.EndsWith(Package.PackageFileExtension)); if (isPackageFile) { packageOutputFile = 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)); } } } // 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 packageReference in package.LocalDependencies) { var packageDirectory = packageReference.Location.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); } } } } if (packageOutputFile != null) { // Add package to session var loadParams = PackageLoadParameters.Default(); loadParams.ForceNugetRestore = true; loadParams.GenerateNewAssetIds = true; loadParams.LoadMissingDependencies = false; var session = parameters.Session; var loadedPackage = session.AddExistingPackage(packageOutputFile, log, loadParams); RemoveUnusedAssets(loadedPackage, session); parameters.Tags.Add(GeneratedPackageKey, loadedPackage); } 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); }
/// <summary> /// Sets the parameters required by this template when running in <see cref="TemplateGeneratorParameters.Unattended"/> mode. /// </summary> public static void SetParameters(SessionTemplateGeneratorParameters parameters, IEnumerable <SelectedSolutionPlatform> platforms) => parameters.SetTag(PlatformsKey, new List <SelectedSolutionPlatform>(platforms));
private static PackageSession GenerateSample(UDirectory outputPath, Guid templateGuid, string sampleName, LoggerResult logger) { // Make output path absolute if (!outputPath.IsAbsolute) { outputPath = UPath.Combine(Environment.CurrentDirectory, outputPath); } Console.WriteLine(@"Bootstrapping: " + sampleName); var session = new PackageSession(); var generator = TemplateSampleGenerator.Default; // Ensure progress is shown while it is happening. logger.MessageLogged += (sender, eventArgs) => Console.WriteLine(eventArgs.Message.Text); var parameters = new SessionTemplateGeneratorParameters { Session = session }; parameters.Unattended = true; TemplateSampleGenerator.SetParameters( parameters, AssetRegistry.SupportedPlatforms.Where(x => x.Type == Core.PlatformType.Windows).Select(x => new SelectedSolutionPlatform(x, x.Templates.FirstOrDefault())).ToList(), addGamesTesting: true); session.SolutionPath = UPath.Combine <UFile>(outputPath, sampleName + ".sln"); // Properly delete previous version if (Directory.Exists(outputPath)) { try { Directory.Delete(outputPath, true); } catch (Exception) { logger.Warning($"Unable to delete directory [{outputPath}]"); } } // Load templates StrideDefaultAssetsPlugin.LoadDefaultTemplates(); var strideTemplates = TemplateManager.FindTemplates(session); parameters.Description = strideTemplates.First(x => x.Id == templateGuid); parameters.Name = sampleName; parameters.Namespace = sampleName; parameters.OutputDirectory = outputPath; parameters.Logger = logger; if (!generator.PrepareForRun(parameters).Result) { logger.Error("PrepareForRun returned false for the TemplateSampleGenerator"); } if (!generator.Run(parameters)) { logger.Error("Run returned false for the TemplateSampleGenerator"); } var updaterTemplate = strideTemplates.First(x => x.FullPath.ToString().EndsWith("UpdatePlatforms.sdtpl")); parameters.Description = updaterTemplate; if (logger.HasErrors) { throw new InvalidOperationException($"Error generating sample {sampleName} from template:\r\n{logger.ToText()}"); } return(session); }
/// <summary> /// Sets the parameters required by this template when running in <see cref="TemplateGeneratorParameters.Unattended"/> mode. /// </summary> public static void SetParameters(SessionTemplateGeneratorParameters parameters, IEnumerable <SelectedSolutionPlatform> platforms, bool addGamesTesting = false) { parameters.SetTag(PlatformsKey, new List <SelectedSolutionPlatform>(platforms)); parameters.SetTag(AddGamesTestingKey, addGamesTesting); }
public static IEnumerable <SolutionProject> UpdatePackagePlatforms(PackageTemplateGeneratorParameters packageParameters, ICollection <SelectedSolutionPlatform> platforms, DisplayOrientation orientation, bool forcePlatformRegeneration) { if (platforms == null) { throw new ArgumentNullException(nameof(platforms)); } var logger = packageParameters.Logger; var package = packageParameters.Package; var name = packageParameters.Name; var addedProjects = new List <SolutionProject>(); // Adjust output directory var parameters = new SessionTemplateGeneratorParameters { Logger = logger, Name = name, OutputDirectory = package.FullPath.GetFullDirectory().GetParent(), Session = package.Session, Description = packageParameters.Description, Namespace = packageParameters.Namespace }; // Setup the ProjectGameGuid to be accessible from exec (in order to be able to link to the game project. AddOption(parameters, "ProjectGameGuid", (package.Container as SolutionProject)?.Id ?? Guid.Empty); AddOption(parameters, "ProjectGameRelativePath", (package.Container as SolutionProject)?.FullPath.MakeRelative(parameters.OutputDirectory).ToWindowsPath()); AddOption(parameters, "PackageGameAssemblyName", package.Meta.Name); // Sample templates still have .Game in their name var packageNameWithoutGame = package.Meta.Name; if (packageNameWithoutGame.EndsWith(".Game")) { packageNameWithoutGame = packageNameWithoutGame.Substring(0, packageNameWithoutGame.Length - ".Game".Length); } AddOption(parameters, "PackageGameName", packageNameWithoutGame); AddOption(parameters, "PackageGameDisplayName", package.Meta.Title ?? packageNameWithoutGame); // Escape illegal characters for the short name AddOption(parameters, "PackageGameNameShort", Utilities.BuildValidClassName(packageNameWithoutGame.Replace(" ", string.Empty))); AddOption(parameters, "PackageGameRelativePath", package.FullPath.MakeRelative(parameters.OutputDirectory).ToWindowsPath()); // Override namespace AddOption(parameters, "Namespace", parameters.Namespace ?? Utilities.BuildValidNamespaceName(packageNameWithoutGame)); // Add projects var stepIndex = 0; var stepCount = platforms.Count + 1; var projectsToRemove = AssetRegistry.SupportedPlatforms .Where(platform => !platforms.Select(x => x.Platform).Contains(platform)) .Select(platform => { var projectFullPath = GeneratePlatformProjectLocation(name, package, platform); return(package.Session.Projects.OfType <SolutionProject>().FirstOrDefault(project => project.FullPath == projectFullPath)); }) .NotNull() .ToList(); foreach (var platform in platforms) { stepIndex++; var projectFullPath = GeneratePlatformProjectLocation(name, package, platform.Platform); var projectName = projectFullPath.GetFileNameWithoutExtension(); // Don't add a platform that is already in the package var existingProject = package.Session.Projects.OfType <SolutionProject>().FirstOrDefault(x => x.FullPath == projectFullPath); var projectGuid = Guid.NewGuid(); if (existingProject != null) { if (!forcePlatformRegeneration) { continue; } projectGuid = existingProject.Id; // We are going to regenerate this platform, so we are removing it before package.Session.Projects.Remove(existingProject); } var projectDirectory = Path.GetDirectoryName(projectFullPath.ToWindowsPath()); if (projectDirectory != null && Directory.Exists(projectDirectory)) { try { Directory.Delete(projectDirectory, true); } catch (Exception) { logger.Warning($"Unable to delete directory [{projectDirectory}]"); } } var templatePath = platform.Template?.TemplatePath ?? $"ProjectExecutable.{platform.Platform.Name}/ProjectExecutable.{platform.Platform.Name}.ttproj"; // Log progress Progress(logger, $"Generating {projectName}...", stepIndex - 1, stepCount); var graphicsPlatform = platform.Platform.Type.GetDefaultGraphicsPlatform(); var newExeProject = GenerateTemplate(parameters, platforms, templatePath, projectName, platform.Platform.Type, graphicsPlatform, ProjectType.Executable, orientation, projectGuid); package.Session.Projects.Add(newExeProject); package.Session.IsDirty = true; addedProjects.Add(newExeProject); } foreach (var project in projectsToRemove) { var projectFullPath = project.FullPath; var projectDirectory = Path.GetDirectoryName(projectFullPath.ToWindowsPath()); if (projectDirectory != null && Directory.Exists(projectDirectory)) { try { Directory.Delete(projectDirectory, true); } catch (Exception) { logger.Warning($"Unable to delete directory [{projectDirectory}]"); } } package.Session.Projects.Remove(project); package.Session.IsDirty = true; } return(addedProjects); }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters is 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 / 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); 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 is 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 static int Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Invalid number of arguments.\n"); Console.WriteLine("Usage: Xenko.SamplesBootstrapper.exe SampleName SampleGuid"); return(1); } Console.WriteLine(@"Bootstrapping: " + args[0]); // When running the SamplesBootstrapper from within Visual Studio and XenkoDir // points to your installation of Xenko and not the development checkout, make sure to override // the environment variable properly otherwise it will get the samples from the Xenko installation. var xenkoDir = Environment.GetEnvironmentVariable("XenkoDir"); var xenkoPkgPath = UPath.Combine(xenkoDir, new UFile("Xenko.xkpkg")); Console.WriteLine("Loading " + xenkoPkgPath + "..."); var session = new PackageSession(); var xenkoPkg = PackageStore.Instance.DefaultPackage; var generator = TemplateSampleGenerator.Default; var logger = new LoggerResult(); // Ensure progress is shown while it is happening. logger.MessageLogged += (sender, eventArgs) => Console.WriteLine(eventArgs.Message.Text); var parameters = new SessionTemplateGeneratorParameters { Session = session }; parameters.Unattended = true; TemplateSampleGenerator.SetParameters(parameters, AssetRegistry.SupportedPlatforms.Select(x => new SelectedSolutionPlatform(x, x.Templates.FirstOrDefault())).ToList()); var outputPath = UPath.Combine(new UDirectory(xenkoDir), new UDirectory("samplesGenerated")); outputPath = UPath.Combine(outputPath, new UDirectory(args[0])); var xenkoTemplates = xenkoPkg.Templates; parameters.Description = xenkoTemplates.First(x => x.Id == new Guid(args[1])); parameters.Name = args[0]; parameters.Namespace = args[0]; parameters.OutputDirectory = outputPath; parameters.Logger = logger; if (!generator.PrepareForRun(parameters).Result) { logger.Error("PrepareForRun returned false for the TemplateSampleGenerator"); } if (!generator.Run(parameters)) { logger.Error("Run returned false for the TemplateSampleGenerator"); } var updaterTemplate = xenkoTemplates.First(x => x.FullPath.ToString().EndsWith("UpdatePlatforms.xktpl")); parameters.Description = updaterTemplate; return(logger.HasErrors ? 1 : 0); }