Esempio n. 1
0
        /// <summary>
        /// Function to retrieve a plug in list item view model based on the plug in passed in.
        /// </summary>
        /// <param name="plugin">The plug in to retrieve data from.</param>
        /// <returns>The view model.</returns>
        private ISettingsPlugInListItem GetPlugInListItem(IGorgonFileSystemProvider plugin)
        {
            var result = new SettingsPlugInListItem();

            result.Initialize(new SettingsPlugInListItemParameters(plugin, _viewModelInjection));
            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Function to find the most suitable provider for the file specified in the path.
        /// </summary>
        /// <param name="file">The file to evaluate.</param>
        /// <returns>The best suitable provider, or <b>null</b> if none could be located.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="file"/> parameter is <b>null</b>.</exception>
        public IGorgonFileSystemProvider GetBestReader(FileInfo file)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            // First, try to locate by extension.
            IGorgonFileSystemProvider result = _readers.Select(item => item.Value)
                                               .FirstOrDefault(item => item.PreferredExtensions.Contains(file.Extension));

            // No provider is registered with that extension, fall back to trying to read each file.
            if (result == null)
            {
                return(GetBestFit(file));
            }
            else
            {
                if (!result.CanReadFileSystem(file.FullName))
                {
                    return(GetBestFit(file));
                }
            }

            return(result);
        }
        /// <summary>
        /// Function to load in the file system for the application.
        /// </summary>
        /// <param name="path">The path to the file system.</param>
        public void Load(string path)
        {
            // Load the file system containing our application data (sprites, images, etc...)
            IGorgonFileSystemProviderFactory providerFactory = new GorgonFileSystemProviderFactory(_plugIns, GorgonApplication.Log);
            IGorgonFileSystemProvider        provider        = providerFactory.CreateProvider("Gorgon.IO.GorPack.GorPackProvider");

            _fileSystem = new GorgonFileSystem(provider, GorgonApplication.Log);

            _fileSystem.Mount(path);
        }
Esempio n. 4
0
        /// <summary>Initializes a new instance of the <see cref="SettingsPlugInListItemParameters"/> class.</summary>
        /// <param name="plugin">The plugin to evaluate.</param>
        /// <param name="commonServices">Common application services.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="plugin"/> is parameter <b>null</b>.</exception>
        public SettingsPlugInListItemParameters(IGorgonFileSystemProvider plugin, IViewModelInjection commonServices)
            : base(commonServices)
        {
            if (plugin == null)
            {
                throw new ArgumentNullException(nameof(plugin));
            }

            Name           = string.IsNullOrWhiteSpace(plugin.Description) ? plugin.Name : plugin.Description;
            Type           = PlugInType.Reader;
            State          = Resources.GOREDIT_PLUGIN_STATE_LOADED;
            DisabledReason = string.Empty;
            Path           = plugin.ProviderPath;
        }
Esempio n. 5
0
        /// <summary>
        /// Function to open a project from a file on the disk.
        /// </summary>
        /// <param name="path">The path to the project file.</param>
        /// <param name="providers">The providers used to read the project file.</param>
        /// <param name="workspace">The workspace directory that will receive the files from the project file.</param>
        /// <returns>A task for asynchronous operation.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="path"/>, or the <paramref name="workspace"/> parameter is <b>null</b>.</exception>
        /// <exception cref="FileNotFoundException">Thrown if the file specified by the <paramref name="path"/> does not exist.</exception>
        /// <exception cref="GorgonException">Thrown if no provider could be found to load the file.</exception>
        public async Task OpenPackFileProjectAsync(FileInfo path, DirectoryInfo workspace)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (workspace == null)
            {
                throw new ArgumentNullException(nameof(workspace));
            }

            if (!path.Exists)
            {
                throw new FileNotFoundException(string.Format(Resources.GOREDIT_ERR_PROJECT_NOT_FOUND, path.FullName));
            }

            IGorgonFileSystemProvider provider = Providers.GetBestReader(path);

            if (provider == null)
            {
                throw new GorgonException(GorgonResult.CannotRead, string.Format(Resources.GOREDIT_ERR_NO_PROVIDER, path.Name));
            }

            // Unlock the directory if we have it locked.
            // Unlock our own lock prior to opening.
            Unlock(workspace);

            if (IsDirectoryLocked(workspace))
            {
                throw new GorgonException(GorgonResult.CannotRead, string.Format(Resources.GOREDIT_ERR_PROJECT_OPEN_LOCKED, workspace.FullName));
            }

            if (workspace.Exists)
            {
                PurgeStaleDirectories(workspace, true);
            }

            (DirectoryInfo _, DirectoryInfo fsDir, DirectoryInfo tempDir, DirectoryInfo srcDir) = SetupProjectFolders(workspace.FullName);

            try
            {
                FileInfo metaData = await CopyFileSystemAsync(path, provider, fsDir);

                // Pull the meta data file into the root of the project directory.
                if (metaData.Exists)
                {
                    metaData.MoveTo(Path.Combine(workspace.FullName, metaData.Name));
                    return;
                }

                Program.Log.Print("No metadata file exists. A new one will be created.", LoggingLevel.Verbose);

                // Create a dummy project, so we have something to serialize.
                var dummyProject = new Project(workspace, tempDir, fsDir, srcDir);

                // If we have v2 meatdata, upgrade the file.
                var v2Metadata = new FileInfo(Path.Combine(workspace.FullName, V2MetadataImporter.V2MetadataFilename));
                if (!v2Metadata.Exists)
                {
                    metaData = new FileInfo(Path.Combine(workspace.FullName, metaData.Name));
                    BuildMetadataDatabase(dummyProject, metaData);
                    return;
                }

                var importer = new V2MetadataImporter(v2Metadata);
                importer.Import(dummyProject);
                PersistMetadata(dummyProject, CancellationToken.None);
            }
            finally
            {
                // For the file import, we will unlock the directory once we're done writing into it.
                // The open project functionality will re-establish the lock after this method completes.
                Unlock(workspace);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Function to copy the file system data from a file system file.
        /// </summary>
        /// <param name="fileSystemFile">The file system file to copy.</param>
        /// <param name="provider">The provider to use.</param>
        /// <param name="fileSystemDir">The workspace directory to copy the files into.</param>
        /// <returns>The path to the metadata file.</returns>
        private async Task <FileInfo> CopyFileSystemAsync(FileInfo fileSystemFile, IGorgonFileSystemProvider provider, DirectoryInfo fileSystemDir)
        {
            IGorgonFileSystem fileSystem = new GorgonFileSystem(provider, Program.Log);

            fileSystem.Mount(fileSystemFile.FullName);

            IGorgonVirtualFile metaData = fileSystem.GetFile(Path.Combine("/", CommonEditorConstants.EditorMetadataFileName));

            // Get all directories and replicate them.
            IEnumerable <IGorgonVirtualDirectory> directories = fileSystem.FindDirectories("/", "*")
                                                                .OrderBy(item => item.FullPath.Length);

            foreach (IGorgonVirtualDirectory directory in directories)
            {
                var dirInfo = new DirectoryInfo(Path.Combine(fileSystemDir.FullName, directory.FullPath.FormatDirectory(Path.DirectorySeparatorChar).Substring(1)));

                if (dirInfo.Exists)
                {
                    continue;
                }

                dirInfo.Create();
            }

            // Copy all files into the directories we just created.
            var files = fileSystem.FindFiles("/", "*")
                        .Where(item => item != metaData)
                        .OrderByDescending(item => item.Size)
                        .ToList();

            int maxJobCount = (Environment.ProcessorCount * 2).Min(32).Max(1);
            int filesPerJob = (int)((float)files.Count / maxJobCount).FastCeiling();
            var jobs        = new List <Task>();

            if ((files.Count <= 100) || (maxJobCount < 2))
            {
                filesPerJob = files.Count;
            }

            Program.Log.Print($"Copying file system. {filesPerJob} files will be copied in a single job.", LoggingLevel.Verbose);

            void CopyFile(FileCopyJob job)
            {
                foreach (IGorgonVirtualFile file in job.Files)
                {
                    var fileInfo = new FileInfo(Path.Combine(fileSystemDir.FullName, file.Directory.FullPath.FormatDirectory(Path.DirectorySeparatorChar).Substring(1), file.Name));

                    using (Stream readStream = file.OpenStream())
                        using (Stream writeStream = fileInfo.OpenWrite())
                        {
                            readStream.CopyToStream(writeStream, (int)readStream.Length, job.ReadBuffer);
                        }
                }
            }

            // Build up the tasks for our jobs.
            while (files.Count > 0)
            {
                var jobData = new FileCopyJob();

                // Copy the file information to the file copy job data.
                int length = filesPerJob.Min(files.Count);
                for (int i = 0; i < length; ++i)
                {
                    jobData.Files.Add(files[i]);
                }
                files.RemoveRange(0, length);

                jobs.Add(Task.Run(() => CopyFile(jobData)));
            }

            Program.Log.Print($"{jobs.Count} jobs running for file copy from '{fileSystemFile.FullName}'.", LoggingLevel.Verbose);

            // Wait for the file copy to finish.
            await Task.WhenAll(jobs);

            var metaDataOutput = new FileInfo(Path.Combine(fileSystemDir.FullName, CommonEditorConstants.EditorMetadataFileName));

            if (metaData == null)
            {
                Program.Log.Print($"'{fileSystemFile.FullName}' has no metadata. A new metadata index will be generated.", LoggingLevel.Verbose);
                return(metaDataOutput);
            }

            Program.Log.Print($"'{fileSystemFile.FullName}' has metadata. Copying to the .", LoggingLevel.Verbose);
            byte[] writeBuffer = new byte[81920];
            using (Stream readStream = metaData.OpenStream())
                using (Stream writeStream = metaDataOutput.OpenWrite())
                {
                    readStream.CopyToStream(writeStream, (int)readStream.Length, writeBuffer);
                }

            metaDataOutput.Attributes = FileAttributes.Archive | FileAttributes.Normal;
            metaDataOutput.Refresh();

            return(metaDataOutput);
        }
Esempio n. 7
0
        /// <summary>
        /// Function to initialize the application.
        /// </summary>
        /// <returns>The main window for the application.</returns>
        private static FormMain Initialize()
        {
            GorgonExample.ResourceBaseDirectory   = new DirectoryInfo(Settings.Default.ResourceLocation);
            GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation);

            FormMain window = GorgonExample.Initialize(new DX.Size2(Settings.Default.Resolution.Width, Settings.Default.Resolution.Height), "Depth");

            try
            {
                IReadOnlyList <IGorgonVideoAdapterInfo> videoDevices = GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log);

                if (videoDevices.Count == 0)
                {
                    throw new GorgonException(GorgonResult.CannotCreate,
                                              "Gorgon requires at least a Direct3D 11.4 capable video device.\nThere is no suitable device installed on the system.");
                }

                // Find the best video device.
                _graphics = new GorgonGraphics(videoDevices.OrderByDescending(item => item.FeatureSet).First());

                _screen = new GorgonSwapChain(_graphics,
                                              window,
                                              new GorgonSwapChainInfo("Gorgon2D Depth Buffer Example")
                {
                    Width  = Settings.Default.Resolution.Width,
                    Height = Settings.Default.Resolution.Height,
                    Format = BufferFormat.R8G8B8A8_UNorm
                });

                _depthBuffer = GorgonDepthStencil2DView.CreateDepthStencil(_graphics, new GorgonTexture2DInfo(_screen.RenderTargetView)
                {
                    Binding = TextureBinding.DepthStencil,
                    Format  = BufferFormat.D24_UNorm_S8_UInt
                });

                // Tell the graphics API that we want to render to the "screen" swap chain.
                _graphics.SetRenderTarget(_screen.RenderTargetView, _depthBuffer);

                // Initialize the renderer so that we are able to draw stuff.
                _renderer = new Gorgon2D(_graphics);

                GorgonExample.LoadResources(_graphics);

                // Load our packed file system plug in.
                _assemblyCache = new GorgonMefPlugInCache(GorgonApplication.Log);
                _assemblyCache.LoadPlugInAssemblies(GorgonExample.GetPlugInPath().FullName, "Gorgon.FileSystem.GorPack.dll");
                IGorgonPlugInService plugIns = new GorgonMefPlugInService(_assemblyCache);

                // Load the file system containing our application data (sprites, images, etc...)
                IGorgonFileSystemProviderFactory providerFactory = new GorgonFileSystemProviderFactory(plugIns, GorgonApplication.Log);
                IGorgonFileSystemProvider        provider        = providerFactory.CreateProvider("Gorgon.IO.GorPack.GorPackProvider");
                IGorgonFileSystem fileSystem = new GorgonFileSystem(provider, GorgonApplication.Log);

                // We can load the editor file system directly.
                // This is handy for switching a production environment where your data may be stored
                // as a compressed file, and a development environment where your data consists of loose
                // files.
                // fileSystem.Mount(@"D:\unpak\scratch\DeepAsAPuddle.gorPack\fs\");

                // For now though, we'll load the packed file.
                fileSystem.Mount(Path.Combine(GorgonExample.GetResourcePath(@"FileSystems").FullName, "Depth.gorPack"));

                // Get our sprites.  These make up the frames of animation for our Guy.
                // If and when there's an animation editor, we'll only need to create a single sprite and load the animation.
                IGorgonVirtualFile[] spriteFiles = fileSystem.FindFiles("/Sprites/", "*", true).ToArray();

                // Load our sprite data (any associated textures will be loaded as well).
                Dictionary <string, GorgonSprite> sprites = new Dictionary <string, GorgonSprite>(StringComparer.OrdinalIgnoreCase);

                for (int i = 0; i < spriteFiles.Length; i++)
                {
                    IGorgonVirtualFile file = spriteFiles[i];
                    (GorgonSprite sprite, GorgonTexture2D texture) = fileSystem.LoadSprite(_renderer, file.FullPath);

                    // The LoadSprite extension method will automatically find and load your associated texture if you're using
                    // a Gorgon editor file system. So it's important that you leep track of your textures, disposing of just
                    // the associated GorgonTexture2DView won't cut it here, so you'll need to dispose the actual texture resource
                    // when you're done with it.
                    if (!_textures.Contains(texture))
                    {
                        _textures.Add(texture);
                    }

                    // At super duper resolution, the example graphics would be really hard to see, so we'll scale them up.
                    sprite.Scale       = new DX.Vector2((_screen.Width / (_screen.Height / 2)) * 2.0f);
                    sprites[file.Name] = sprite;
                }

                _snowTile       = sprites["Snow"];
                _snowTile.Depth = 0.5f;

                _icicle       = sprites["Icicle"];
                _icicle.Depth = 0.2f;

                _guySprite       = sprites["Guy_Up_0"];
                _guySprite.Depth = 0.1f;
                _guyPosition     = new DX.Vector2(_screen.Width / 2 + _guySprite.ScaledSize.Width * 1.25f, _screen.Height / 2 + _guySprite.ScaledSize.Height);

                BuildAnimations(sprites);
            }
            finally
            {
                GorgonExample.EndInit();
            }

            return(window);
        }