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.
        }
Esempio n. 2
0
        private static UFile GenerateLocation(string assetName, AssetTemplateGeneratorParameters parameters)
        {
            var location = assetName.StartsWith(parameters.TargetLocation) ? new UFile(assetName)
                                    : UPath.Combine(parameters.TargetLocation, new UFile(assetName));

            return(NamingHelper.ComputeNewName(location, x => parameters.Package.Assets.Find(x) != null, "{0}_{1}"));
        }
Esempio n. 3
0
        /// <summary>
        /// Creates a new sub-directory with a default name in this directory.
        /// </summary>
        /// <param name="editing">Indicates whether the new sub-directory should be put in edit mode immediately when constructed.</param>
        /// <returns>A new instance of <see cref="DirectoryViewModel"/> representing the new sub-directory.</returns>
        public DirectoryViewModel CreateSubDirectory(bool editing)
        {
            var newDirectory = new DirectoryViewModel(NamingHelper.ComputeNewName(NewFolderDefaultName, SubDirectories.Cast <DirectoryBaseViewModel>(), x => x.Name), this, true)
            {
                IsEditing = editing
            };

            return(newDirectory);
        }
Esempio n. 4
0
 /// <summary>
 /// Finds a name available for a new asset. This method will try to create a name based on an existing name and will append
 /// "_" + (number++) on every try. The new location found is added to the known existing locations.
 /// </summary>
 /// <param name="location">The location.</param>
 /// <param name="newLocation">The new location.</param>
 /// <returns><c>true</c> if there is a new location, <c>false</c> otherwise.</returns>
 public bool RegisterLocation(UFile location, out UFile newLocation)
 {
     newLocation = location;
     if (IsContainingLocation(location))
     {
         newLocation = NamingHelper.ComputeNewName(location, IsContainingLocation);
     }
     ExistingLocations.Add(newLocation);
     return(newLocation != location);
 }
Esempio n. 5
0
        protected List <AssetItem> MakeUniqueNames(IEnumerable <AssetItem> assets)
        {
            var result = new List <AssetItem>();

            foreach (var asset in assets)
            {
                var uniqueName = NamingHelper.ComputeNewName(asset.Location, x => result.Any(y => y.Asset != asset.Asset && x == y.Location), "{0}_{1}");
                result.Add(new AssetItem(uniqueName, asset.Asset));
            }
            return(result);
        }
        protected string GenerateUniqueNameAtLocation(List <string> conflictingNames = null)
        {
            if (conflictingNames == null)
            {
                conflictingNames = new List <string>();
            }

            if (Directory.Exists(Location))
            {
                // Also add currently existing folders
                var existingFolders = Directory.GetDirectories(Location).Select(Path.GetFileName);
                conflictingNames.AddRange(existingFolders);
            }
            // Generate a name that does not collide with one of the previously gathered names
            var newName = NamingHelper.ComputeNewName(SelectedTemplate.DefaultOutputName, conflictingNames, x => x, "{0}{1}");

            return(newName);
        }
Esempio n. 7
0
        private void CreateUnitTestAsset()
        {
#if DEBUG
            var package = Editor.Session.CurrentPackage;
            if (package != null)
            {
                using (var transaction = Editor.Session.UndoRedoService.CreateTransaction())
                {
                    var dir            = package.AssetMountPoint;
                    var name           = NamingHelper.ComputeNewName("UnitTestAsset", x => dir.Assets.Any(y => string.Equals(x, y.Name, StringComparison.OrdinalIgnoreCase)));
                    var asset          = UnitTestAsset.CreateNew();
                    var assetItem      = new AssetItem(name, asset);
                    var assetViewModel = package.CreateAsset(dir, assetItem, true, null);
                    Editor.Session.NotifyAssetPropertiesChanged(new[] { assetViewModel });
                    Editor.Session.ActiveAssetView.SelectAssets(new[] { assetViewModel });
                    Editor.Session.UndoRedoService.SetName(transaction, $"Create test asset '{name}'");
                }
            }
#endif
        }
        protected override string UpdateNameFromSelectedTemplate()
        {
            var selectedTemplate = SelectedTemplate?.GetTemplate() as TemplateAssetDescription;

            if (selectedTemplate == null || !selectedTemplate.RequireName)
            {
                return(null);
            }

            // If the mount point of the current folder does not support this type of asset, try to select the first mount point that support it.
            var assetType = selectedTemplate.GetAssetType();

            TargetDirectory = AssetViewModel.FindValidCreationLocation(assetType, CurrentDirectory);
            if (TargetDirectory == null)
            {
                return(null);
            }

            var baseName = selectedTemplate.DefaultOutputName ?? selectedTemplate.AssetTypeName;
            var name     = NamingHelper.ComputeNewName(baseName, TargetDirectory.Assets, x => x.Name, "{0}{1}");

            return(name);
        }
Esempio n. 9
0
        public sealed override bool Run(AssetTemplateGeneratorParameters parameters)
        {
            var assets = CreateAssets(parameters)?.ToList();

            if (assets == null)
            {
                parameters.Logger.Error("No asset created by the asset factory.");
                return(false);
            }

            // Step one: add assets to package with proper unique name
            var newAssets = new Dictionary <AssetId, AssetItem>();

            foreach (var asset in assets)
            {
                if (string.IsNullOrEmpty(asset.Location))
                {
                    throw new InvalidOperationException($"Asset returned by {nameof(CreateAssets)} has no location. Use {nameof(GenerateLocation)} to generate the location for each asset.");
                }

                // Ensure unicity of names amongst package
                var name = NamingHelper.ComputeNewName(asset.Location, x => parameters.Package.Assets.Find(x) != null, "{0}_{1}");
                var item = new AssetItem(name, asset.Asset);

                try
                {
                    parameters.Package.Assets.Add(item);
                    // Ensure the dirty flag is properly set to refresh the dependency manager
                    item.IsDirty = true;
                }
                catch (Exception ex)
                {
                    parameters.Logger.Error("Failed to create new asset from template.", ex);
                    return(false);
                }
                newAssets.Add(item.Id, item);
            }

            // Step two: fix references in the newly added assets
            foreach (var asset in newAssets)
            {
                var referencesToFix = AssetReferenceAnalysis.Visit(asset.Value);
                foreach (var assetReferenceLink in referencesToFix)
                {
                    var refToUpdate = assetReferenceLink.Reference as IReference;
                    if (refToUpdate == null)
                    {
                        continue;
                    }

                    AssetItem realItem;
                    // Look for the referenced asset in the new assets
                    if (newAssets.TryGetValue(refToUpdate.Id, out realItem))
                    {
                        assetReferenceLink.UpdateReference(realItem.Id, realItem.Location);
                    }
                    else
                    {
                        // If not found, try on the already existing assets
                        realItem = parameters.Package.Session.FindAsset(refToUpdate.Id);
                        assetReferenceLink.UpdateReference(realItem?.Id ?? AssetId.Empty, realItem?.Location);
                    }
                }
            }

            // Step three: complete creation and mark them as dirty
            foreach (var asset in newAssets.Values)
            {
                try
                {
                    PostAssetCreation(parameters, asset);
                    // Ensure the dirty flag is properly set to refresh the dependency manager
                    asset.IsDirty = true;
                }
                catch (Exception ex)
                {
                    parameters.Logger.Error("Failed to create new asset from template.", ex);
                    return(false);
                }
            }
            return(true);
        }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Checks if a default scene exists for this game package.
        /// </summary>
        /// <param name="log">The log to output the result of the validation.</param>
        public override void Run(ILogger log)
        {
            if (log == null)
            {
                throw new ArgumentNullException(nameof(log));
            }

            foreach (var package in Session.Packages)
            {
                // Make sure package has its assets loaded
                if (package.State < PackageState.AssetsReady)
                {
                    continue;
                }

                var hasGameExecutable = package.Profiles.SelectMany(profile => profile.ProjectReferences).Any(projectRef => projectRef.Type == ProjectType.Executable);
                if (!hasGameExecutable)
                {
                    continue;
                }

                // Find game settings
                var       gameSettingsAssetItem = package.Assets.Find(GameSettingsAsset.GameSettingsLocation);
                AssetItem defaultScene          = null;

                // If game settings is found, try to find default scene inside
                var defaultSceneRuntime   = ((GameSettingsAsset)gameSettingsAssetItem?.Asset)?.DefaultScene;
                var defaultSceneReference = AttachedReferenceManager.GetAttachedReference(defaultSceneRuntime);
                if (defaultSceneReference != null)
                {
                    // Find it either by Url or Id
                    defaultScene = package.Assets.Find(defaultSceneReference.Id) ?? package.Assets.Find(defaultSceneReference.Url);

                    // Check it is actually a scene asset
                    if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                    {
                        defaultScene = null;
                    }
                }

                // Find or create default scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.Find(GameSettingsAsset.DefaultSceneLocation);
                    if (defaultScene != null && !(defaultScene.Asset is SceneAsset))
                    {
                        defaultScene = null;
                    }
                }

                // Otherwise, try to find any scene
                if (defaultScene == null)
                {
                    defaultScene = package.Assets.FirstOrDefault(x => x.Asset is SceneAsset);
                }

                // Nothing found, let's create an empty one
                if (defaultScene == null)
                {
                    log.Error(package, null, AssetMessageCode.DefaultSceneNotFound, null);

                    var defaultSceneName  = NamingHelper.ComputeNewName(GameSettingsAsset.DefaultSceneLocation, package.Assets, a => a.Location);
                    var defaultSceneAsset = DefaultAssetFactory <SceneAsset> .Create();

                    defaultScene = new AssetItem(defaultSceneName, defaultSceneAsset);
                    package.Assets.Add(defaultScene);
                    defaultScene.IsDirty = true;
                }

                // Create game settings if not done yet
                if (gameSettingsAssetItem == null)
                {
                    log.Error(package, null, AssetMessageCode.AssetForPackageNotFound, GameSettingsAsset.GameSettingsLocation, package.FullPath.GetFileName());

                    var gameSettingsAsset = GameSettingsFactory.Create();

                    gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(defaultScene.Id, defaultScene.Location);

                    gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset);
                    package.Assets.Add(gameSettingsAssetItem);

                    gameSettingsAssetItem.IsDirty = true;
                }
            }
        }
        /// <summary>
        /// Checks if a default scene exists for this game package.
        /// </summary>
        /// <param name="log">The log to output the result of the validation.</param>
        public override void Run(ILogger log)
        {
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            foreach (var package in Session.Packages)
            {
                var hasGameExecutable = package.Profiles.SelectMany(profile => profile.ProjectReferences).Any(projectRef => projectRef.Type == ProjectType.Executable);
                if (!hasGameExecutable)
                {
                    continue;
                }

                var sharedProfile = package.Profiles.FindSharedProfile();
                if (sharedProfile == null)
                {
                    continue;
                }

                var defaultScene = sharedProfile.Properties.Get(GameSettingsAsset.DefaultScene);

                // If the pdxpkg does not reference any scene
                if (defaultScene == null)
                {
                    log.Error(package, null, AssetMessageCode.DefaultSceneNotFound, null);

                    // Creates a new default scene
                    // Checks we don't overwrite an existing asset
                    const string defaultSceneLocation = "MainScene";
                    var          existingDefault      = package.Assets.Find(defaultSceneLocation);
                    if (existingDefault != null && existingDefault.Asset is SceneAsset)
                    {
                        // A scene at the default location already exists among the assets, let's reference it as the default scene
                        var sceneAsset = new AssetReference <SceneAsset>(existingDefault.Id, existingDefault.Location);
                        GameSettingsAsset.SetDefaultScene(package, sceneAsset);
                    }
                    else if (existingDefault != null)
                    {
                        // Very rare case: the default scene location is occupied by another asset which is not a scene
                        // Compute a new default name to not overwrite the existing asset
                        var newName = NamingHelper.ComputeNewName(defaultSceneLocation, package.Assets, a => a.Location);
                        GameSettingsAsset.CreateAndSetDefaultScene(package, newName);
                    }
                    else
                    {
                        // Creates a new default scene asset
                        GameSettingsAsset.CreateAndSetDefaultScene(package, defaultSceneLocation);
                    }

                    continue;
                }

                // The pdxpkg references an asset
                var defaultAsset = package.Assets.Find(defaultScene.Location);

                if (defaultAsset != null)
                {
                    continue;                       // Default scene exists and is referenced
                }
                // The asset referenced does not exist, create it
                log.Error(package, defaultScene, AssetMessageCode.AssetNotFound, defaultScene);
                GameSettingsAsset.CreateAndSetDefaultScene(package);
            }
        }