/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { GorgonExample.PlugInLocationDirectory = new DirectoryInfo(Settings.Default.PlugInLocation); GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); // Create our virtual file system. _fileSystem = new GorgonFileSystem(Program.Log); _writer = new GorgonFileSystemWriter(_fileSystem, Program.WriteDirectory.FullName); LoadText(); labelFileSystem.Text = $"{GorgonExample.GetResourcePath(@"FolderSystem\").FullName.Ellipses(100, true)} mounted as '/'."; labelWriteLocation.Text = $"{Program.WriteDirectory.FullName.Ellipses(100, true)} mounted as '/'"; } catch (Exception ex) { GorgonExample.HandleException(ex); GorgonApplication.Quit(); } finally { CommandEnable(!string.Equals(_originalText, _changedText, StringComparison.CurrentCulture)); UpdateInfo(); } }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { _writePath = Path.GetDirectoryName(Gorgon.Log.LogPath) + @"\Examples\FileSystem.Writing\"; // Create our virtual file system. _fileSystem = new GorgonFileSystem(); LoadText(); labelFileSystem.Text = string.Format("{0} mounted as '/'.", Program.GetResourcePath(@"FolderSystem\").Ellipses(100, true)); labelWriteLocation.Text = string.Format("{0} mounted as '/'", _writePath.Ellipses(100, true)); } catch (Exception ex) { GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex)); Application.Exit(); } finally { itemLoadChanged.Enabled = !string.Equals(textDisplay.Text, _originalText, StringComparison.CurrentCulture); UpdateInfo(); } }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFileSystemDirectory"/> class. /// </summary> /// <param name="fileSystem">The file system that owns this directory.</param> /// <param name="name">The name of the directory.</param> /// <param name="parent">Parent directory.</param> internal GorgonFileSystemDirectory(GorgonFileSystem fileSystem, string name, GorgonFileSystemDirectory parent) : base(name.RemoveIllegalPathChars()) { Directories = new GorgonFileSystemDirectoryCollection(); FileSystem = fileSystem; Files = new GorgonFileSystemFileEntryCollection(this); Parent = parent; }
/// <summary> /// Initializes a new instance of the <see cref="VirtualDirectory" /> class. /// </summary> /// <param name="mountPoint">The mount point that supplied this directory.</param> /// <param name="fileSystem">The file system that contains the directory.</param> /// <param name="parentDirectory">The parent of this directory.</param> /// <param name="name">The name of the directory.</param> public VirtualDirectory(GorgonFileSystemMountPoint mountPoint, GorgonFileSystem fileSystem, VirtualDirectory parentDirectory, string name) { MountPoint = mountPoint; FileSystem = fileSystem; Name = name != "/" ? name.FormatPathPart() : name; Parent = parentDirectory; Directories = new VirtualDirectoryCollection(this); Files = new VirtualFileCollection(this); }
/// <summary> /// Initializes the <see cref="GorgonEditorFile"/> class. /// </summary> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="fileSystem"/> parameter is NULL (Nothing in VB.Net).</exception> public GorgonEditorFile(GorgonFileSystem fileSystem) { if (fileSystem == null) { throw new ArgumentNullException("fileSystem"); } FileSystem = fileSystem; Dependencies = new Dictionary <string, GorgonEditorDependencyCollection>(); _fileHandlers = new Dictionary <Type, Func <Stream, IReadOnlyDictionary <GorgonEditorDependency, object>, object> >(); }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { // Picture box. _picture = new PictureBox { Name = "pictureImage" }; // Text display. _textDisplay = new TextBox { Name = "textDisplay" }; _textFont = new Font("Consolas", 10.0f, FontStyle.Regular, GraphicsUnit.Point); _textDisplay.Font = _textFont; _instructions = new Label { Name = "labelInstructions", Text = "Double click on a file node in the tree to display it.", AutoSize = false, TextAlign = ContentAlignment.MiddleCenter, Dock = DockStyle.Fill, Font = Font }; // Add the instructions. splitFileSystem.Panel2.Controls.Add(_instructions); // Create the file system. _fileSystem = new GorgonFileSystem(); // Get the zip file provider. LoadZipFileSystemProvider(); // Mount the physical file system directory. _fileSystem.Mount(Program.GetResourcePath(@"VFSRoot\")); // Mount the zip file into a sub directory. _fileSystem.Mount(Program.GetResourcePath("VFSRoot.zip"), "/ZipFile"); // Fill the root of the tree. FillTree(null); } catch (Exception ex) { GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex)); Application.Exit(); } }
/// <summary> /// Function to return the file system used for writing out temporary data. /// </summary> /// <param name="tempDirectory">The physical directory to store the temporary data into.</param> /// <returns>A new writable file system for writing temporary data into.</returns> private IGorgonFileSystemWriter <Stream> GetScratchArea(DirectoryInfo tempDirectory) { string scratchPath = Path.Combine(tempDirectory.FullName, "Tools", GetType().FullName).FormatDirectory(Path.DirectorySeparatorChar); if (!Directory.Exists(scratchPath)) { Directory.CreateDirectory(scratchPath); } var scratchArea = new GorgonFileSystem(CommonServices.Log); scratchArea.Mount(scratchPath); return(new GorgonFileSystemWriter(scratchArea, scratchPath)); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFileSystemRamDiskWriter"/> class. /// </summary> /// <param name="fileSystem">A file system used to track the updates when writing.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fileSystem" /> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="fileSystem"/> does not contain a <see cref="GorgonFileSystemRamDiskProvider"/>.</exception> public GorgonFileSystemRamDiskWriter(GorgonFileSystem fileSystem) : base(Resources.GORFS_RAMDISK_WRITER_FS_DESC) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } _provider = (from providers in fileSystem.Providers let ramProvider = providers as GorgonFileSystemRamDiskProvider select ramProvider) .FirstOrDefault(); _ramFiles = _provider?.FileData ?? throw new ArgumentException(Resources.GORFS_ERR_NO_RAMDISK_PROVIDER, nameof(fileSystem)); _fileSystem = fileSystem; }
/// <summary> /// Function to load the zip file provider plugin. /// </summary> /// <returns><b>true</b> if successfully loaded, <b>false</b> if not.</returns> private static bool LoadZipProviderPlugIn() { var zipProviderFile = new FileInfo(Path.Combine(PlugInPath.FormatDirectory(Path.DirectorySeparatorChar), "Gorgon.FileSystem.Zip.dll")); // Check to see if the file exists. if (!zipProviderFile.Exists) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Could not find the plugin assembly file:\n'{0}'.", zipProviderFile.FullName); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif return(false); } // Load the plugin assembly. _pluginAssemblies.LoadPlugInAssemblies(zipProviderFile.Directory?.FullName, zipProviderFile.Name); // Create our file system provider factory so we can retrieve the zip file provider. var providerFactory = new GorgonFileSystemProviderFactory(_pluginService, _log); // Get our zip file provider. GorgonFileSystemProvider provider; try { provider = providerFactory.CreateProvider(PlugInName); } catch (GorgonException gEx) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(gEx.Message); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif return(false); } _fileSystem = new GorgonFileSystem(provider, _log); Console.WriteLine("\nThe zip file file system provider was loaded successfully."); return(true); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFileSystemWriter"/> class. /// </summary> /// <param name="fileSystem">A file system used to track the updates when writing.</param> /// <param name="writeLocation">The directory on the physical file system to actually write data into.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fileSystem"/>, or the <paramref name="writeLocation"/> parameters are <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="writeLocation"/> is empty.</exception> public GorgonFileSystemWriter(GorgonFileSystem fileSystem, string writeLocation) : base(Resources.GORFS_FOLDER_WRITER_FS_DESC) { if (writeLocation == null) { throw new ArgumentNullException(nameof(writeLocation)); } if (string.IsNullOrWhiteSpace(writeLocation)) { throw new ArgumentEmptyException(nameof(writeLocation)); } // We need the concrete type in here because we need access to its internals. _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); WriteLocation = writeLocation.FormatDirectory(Path.DirectorySeparatorChar); _mountPoint = new GorgonFileSystemMountPoint(fileSystem.DefaultProvider, WriteLocation, "/"); }
/// <summary> /// Function to load the zip file system provider. /// </summary> private void LoadZipFileSystemProvider() { // Name of our zip provider plugin. const string zipProviderPlugInName = "Gorgon.IO.Zip.ZipProvider"; // We can load the objects we need and discard the plugin system after. // This works because we keep the references to the objects that our // plugin creates, even after the plugin is gone. using (var pluginAssemblies = new GorgonMefPlugInCache(Program.Log)) { pluginAssemblies.LoadPlugInAssemblies(Program.PlugInPath, "Gorgon.FileSystem.Zip.DLL"); var providerFactory = new GorgonFileSystemProviderFactory( new GorgonMefPlugInService(pluginAssemblies), Program.Log); _fileSystem = new GorgonFileSystem(providerFactory.CreateProvider(zipProviderPlugInName), Program.Log); } }
/// <summary> /// Function to determine if this directory, or optionally, any of the sub directories contains a <see cref="IGorgonVirtualFile"/> with the specified file name. /// </summary> /// <param name="fileName">The name of the file to search for.</param> /// <returns><b>true</b> if found, <b>false</b> if not.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fileName"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="fileName"/> parameter is empty.</exception> /// <remarks> /// Use this to determine if a <see cref="IGorgonVirtualFile"/> exists under this directory or any of its sub directories. This search includes all sub directories for this and child directories. /// To determine if a file exists in the immediate directory, use the <see cref="IGorgonNamedObjectReadOnlyDictionary{T}.Contains"/> method. /// </remarks> public bool ContainsFile(string fileName) { if (fileName == null) { throw new ArgumentNullException(nameof(fileName)); } if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentEmptyException(nameof(fileName)); } if (Files.Contains(fileName)) { return(true); } IEnumerable <VirtualDirectory> directories = GorgonFileSystem.FlattenDirectoryHierarchy(this, "*"); return(directories.Any(item => item.Files.Contains(fileName))); }
/// <summary> /// Function to retrieve the total number of directories in this directory including any directories under this one. /// </summary> /// <returns>The total number of directories.</returns> /// <remarks> /// Use this to retrieve the total number of <see cref="IGorgonVirtualDirectory"/> entries under this directory. This search includes all sub directories for this and child directories. To get /// the count of the immediate subdirectories, use the <see cref="IReadOnlyCollection{T}.Count"/> property on the <see cref="IGorgonVirtualDirectory.Directories"/> property. /// </remarks> public int GetDirectoryCount() => Directories.Count == 0 ? 0 : GorgonFileSystem.FlattenDirectoryHierarchy(this, "*").Count();
/// <summary> /// Function to open the editor file. /// </summary> /// <param name="path">Path to the editor file.</param> public static void Open(string path) { var packFileSystem = new GorgonFileSystem(); FileChanged = false; // Add the new file system as a mount point. var plugIns = from plugIn in Gorgon.PlugIns where plugIn is GorgonFileSystemProviderPlugIn && !PlugIns.IsDisabled(plugIn) select plugIn; foreach (var plugIn in plugIns) { packFileSystem.Providers.LoadProvider(plugIn.Name); } if (!packFileSystem.Providers.Any(item => item.CanReadFile(path))) { throw new FileLoadException(string.Format(APIResources.GOREDIT_ERR_NO_READ_PROVIDERS, Path.GetFileName(path))); } packFileSystem.Mount(path); try { // Remove our previous scratch data. ResetFile(); // At this point we should have a clean scratch area, so all files will exist in the packed file. // Unpack the file structure so we can work with it. var directories = packFileSystem.FindDirectories("*", true); var files = packFileSystem.FindFiles("*", true); // Create our directories. foreach (var directory in directories) { ScratchArea.ScratchFiles.CreateDirectory(directory.FullPath); } // Copy our files. foreach (var file in files) { using (var inputStream = packFileSystem.OpenStream(file, false)) { using (var outputStream = ScratchArea.ScratchFiles.OpenStream(file.FullPath, true)) { inputStream.CopyTo(outputStream); } } } FilePath = string.Empty; Filename = Path.GetFileName(path); // Load the meta data if it exists. EditorMetaDataFile.Load(); // If we can't write the file, then leave the editor file path as blank. // If the file path is blank, then the Save As function will be triggered if we attempt to save so we // can save it in a format that we DO understand. This is of course assuming we have any plug-ins loaded // that will allow us to save. if (GetWriterPlugIn(path) != null) { FilePath = path; } } catch { // We have a problem, reset whatever changes we've made. ResetFile(); throw; } finally { // At this point we don't need this file system any more. We'll // be using our scratch system instead. packFileSystem.Clear(); } }
/// <summary> /// The main entry point for the application. /// </summary> static void Main() { try { // Create a new file system. // The file system must be created first and given access to the various // data sources via the provider plug-ins. // For example, this will allow us to create a file system that can read // a RAR file, while another file system would only cater to Zip files. // By default, every file system comes with a folder file system provider // that can mount a directory from the hard drive as a VFS root. _fileSystem = new GorgonFileSystem(); Console.WriteLine("Gorgon is capable of mounting virtual file systems for file access. A virtual"); Console.WriteLine("filesystem root can be a folder on a harddrive, a zip file, or any data store"); Console.WriteLine("(assuming there's a provider for it).\n"); Console.WriteLine("In Gorgon, the types of data that can be mounted as a virtual file system is"); Console.WriteLine("managed by plug-ins called providers. By default, the file system has a folder"); Console.WriteLine("provider. This allows a folder to be mounted as the root of a virtual file\nsystem.\n"); Console.WriteLine("This example will show how to load extra providers into a file system.\n"); Console.ForegroundColor = ConsoleColor.White; // Get our file system providers. Console.WriteLine("Found {0} external file system plug-ins.\n", LoadFileSystemProviders()); // Loop through each provider and print some info. for (int i = 0; i < _fileSystem.Providers.Count; i++) { var provider = _fileSystem.Providers[i]; // Print some info about the file system provider. Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}. {1}", (i + 1), provider.Name); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(" Description: {0}", provider.Description); // Gather the preferred extensions. // File system providers that use a file (like a Zip file) as its root // have a list of file extensions that are preferred. For example, the // Zip provider, expects to find *.zip files. These are merely here // for the convenience of the developer and are formatted like a common // dialog file mask so they can be easily dropped into that control. // In this case, we're going to just strip out the relevant part and // concatenate each preferred extension description into a single string. // // Note that a provider may have multiple preferred extensions. var extensionList = (from preferred in provider.PreferredExtensions select string.Format("*.{0}", preferred.Extension)).ToArray(); if (extensionList.Length > 0) { Console.WriteLine(" Preferred Extensions: {0}", string.Join(", ", extensionList)); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { // Catch all exceptions here. If we had logging for the application enabled, then this // would record the exception in the log. GorgonException.Catch(ex, () => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", ex.Message, ex.StackTrace); }); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif } }
/// <summary> /// The main entry point for the application. /// </summary> private static void Main() { _log = new GorgonLog("FolderFileSystem", "Tape_Worm"); _log.LogStart(); try { Console.WindowHeight = 26.Max(Console.WindowHeight); Console.BufferHeight = Console.WindowHeight; // Create a new file system. _fileSystem = new GorgonFileSystem(_log); // Set the following directory as root on the virtual file system. // To mount a directory we need to put in the trailing slash. // // If we wanted to, we could mount a directory as a sub directory of // the root of the virtual file system. For example, mounting the // directory D:\Dir with Mount(@"D:\Dir", "/VFSDir"); would mount the // contents of the D:\Dir directory under /VFSDir. // // It's also important to point out that the old Gorgon "file system" // would load files from the system into memory when mounting a // directory. While this version only loads directory and file // information when mounting. This is considerably more efficient. string physicalPath = GetResourcePath(@"FolderSystem\"); _fileSystem.Mount(physicalPath); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This example will mount a physical file system directory as the root of a"); Console.WriteLine("virtual file system. The virtual file system is capable of mounting various"); Console.WriteLine("types of data such as a zip file, a file system folder, etc... as the root or a"); Console.WriteLine("sub directory. You can even mount a zip file as the root, and a physical file"); Console.WriteLine("system directory as a virtual sub directory in the same virtual file system and"); Console.WriteLine("access them as a single unified file system."); Console.Write("\nMounted: "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true)); Console.ForegroundColor = ConsoleColor.White; Console.Write(" as "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("'/'\n"); Console.ForegroundColor = ConsoleColor.White; // Get a count of all sub directories and files under the root directory. IGorgonVirtualDirectory[] directoryList = _fileSystem.FindDirectories("*").ToArray(); // Display directories. Console.WriteLine("Virtual file system contents:"); for (int i = -1; i < directoryList.Length; i++) { IGorgonVirtualDirectory directory = _fileSystem.RootDirectory; // Go into the sub directories under root. if (i > -1) { directory = directoryList[i]; } Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}", directory.FullPath); Console.ForegroundColor = ConsoleColor.Yellow; foreach (IGorgonVirtualFile file in directory.Files) { Console.Write(" {0}", file.Name); // Align the size to the same place. Console.CursorLeft = 65; Console.WriteLine("{0}", file.Size.FormatMemory()); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { ex.Catch(_ => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", _.Message, _.StackTrace); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif }, _log); } finally { _log.LogEnd(); } }
/// <summary> /// The main entry point for the application. /// </summary> static void Main() { try { Console.WindowHeight = 28; Console.BufferHeight = Console.WindowHeight; // Create a new file system. _fileSystem = new GorgonFileSystem(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("This example will mount a zip file as the root of a virtual file system. The"); Console.WriteLine("virtual file system is capable of mounting various types of data such as a zip,"); Console.WriteLine("a file system folder, etc... as the root or a sub directory. You can even"); Console.WriteLine("mount a zip file as the root, and a physical file system directory as a virtual"); Console.WriteLine("sub directory in the same virtual file system and access them as a single"); Console.WriteLine("unified file system."); // Unlike the folder file system example, we need to load // a provider to handle zip files before trying to mount // one. if (!LoadZipProviderPlugIn()) { return; } // Set the following zip file as root on the virtual file system. // // If we wanted to, we could mount a zip file as a sub directory of // the root of the virtual file system. For example, mounting the // directory D:\Dir\zipFile.zip with Mount(@"D:\Dir", "/VFSDir"); would mount // the contents of the D:\Dir\zipFile.zip directory under /VFSDir. // // It's also important to point out that the old Gorgon "file system" // would load files from the system into memory when mounting a // directory. While this version only loads directory and file // information when mounting. This is considerably more efficient. var physicalPath = GetResourcePath(@"FileSystem.zip"); _fileSystem.Mount(physicalPath); Console.Write("\nMounted: "); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true)); Console.ForegroundColor = ConsoleColor.White; Console.Write(" as "); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("'/'\n"); Console.ForegroundColor = ConsoleColor.White; // Get a count of all sub directories and files under the root directory. var directoryList = _fileSystem.FindDirectories("*", true).ToArray(); // Display directories. Console.WriteLine("Virtual file system contents:"); for (int i = -1; i < directoryList.Length; i++) { GorgonFileSystemDirectory directory = _fileSystem.RootDirectory; // Go into the sub directories under root. if (i > -1) { directory = directoryList[i]; } Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("{0}", directory.FullPath); Console.ForegroundColor = ConsoleColor.Yellow; foreach (var file in directory.Files) { Console.Write(" {0}", file.Name); // Align the size to the same place. Console.CursorLeft = 65; Console.WriteLine("{0}", file.Size.FormatMemory()); } } Console.ResetColor(); Console.WriteLine("\nPress any key to close."); Console.ReadKey(); } catch (Exception ex) { // Catch all exceptions here. If we had logging for the application enabled, then this // would record the exception in the log. GorgonException.Catch(ex, () => { Console.Clear(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", ex.Message, ex.StackTrace); Console.ResetColor(); #if DEBUG Console.ReadKey(); #endif }); } }
/// <summary> /// Function to load a <see cref="IGorgonAnimation"/> from a <see cref="GorgonFileSystem"/>. /// </summary> /// <param name="fileSystem">The file system to load the animation from.</param> /// <param name="renderer">The renderer for the animation.</param> /// <param name="path">The path to the animation file in the file system.</param> /// <param name="textureOptions">[Optional] Options for the texture loaded associated the sprite.</param> /// <param name="animationCodecs">The list of animation codecs to try and load the animation with.</param> /// <param name="imageCodecs">The list of image codecs to try and load the animation texture(s) with.</param> /// <returns>The animation data in the file as a <see cref="IGorgonAnimation"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fileSystem"/>, <paramref name="renderer"/>, or <paramref name="path"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="path"/> parameter is empty.</exception> /// <exception cref="FileNotFoundException">Thrown if the file in the <paramref name="path"/> was not found.</exception> /// <exception cref="GorgonException">Thrown if the animation data in the file system could not be loaded because a suitable codec was not found.</exception> /// <remarks> /// <para> /// This method extends a <see cref="GorgonFileSystem"/> so that animations can be loaded by calling a method on the file system object itself. This negates the need for users to create complex code /// for loading an animation. /// </para> /// <para> /// When loading an animation, the method will attempt to locate any <see cref="GorgonTexture2DView"/> objects associated with the animation (if they exist). When loading, it will check: /// <list type="number"> /// <item> /// <description>For a texture resource with the same name that is already loaded into memory.</description> /// </item> /// <item> /// <description>Use the local <see cref="IGorgonVirtualDirectory"/> for the sprite file and search for the texture in that directory.</description> /// </item> /// <item> /// <description>Check the entire <paramref name="fileSystem"/> for a file if the texture name contains path information (this is done by the GorgonEditor from v2).</description> /// </item> /// </list> /// If the file is found, and can be loaded by one of the <paramref name="imageCodecs"/>, then it is loaded and assigned to the sprite. /// </para> /// <para> /// The <paramref name="animationCodecs"/> is a list of codecs for loading sprite data. If the user specifies this parameter, the only the codecs provided will be used for determining if an /// animation can be read. If it is not supplied, then all built-in (i.e. not plug in based) sprite codecs will be used. /// </para> /// <para> /// The <paramref name="imageCodecs"/> is a list of codecs for loading image data. If the user specifies this parameter, the only the codecs provided will be used for determining if an image can be /// read. If it is not supplied, then all built-in (i.e. not plug in based) image codecs will be used. /// </para> /// </remarks> /// <seealso cref="GorgonFileSystem"/> /// <seealso cref="GorgonTexture2DView"/> /// <seealso cref="IGorgonAnimation"/> public static IGorgonAnimation LoadAnimationFromFileSystem(this GorgonFileSystem fileSystem, Gorgon2D renderer, string path, GorgonTexture2DLoadOptions textureOptions = null, IEnumerable <IGorgonAnimationCodec> animationCodecs = null, IEnumerable <IGorgonImageCodec> imageCodecs = null) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } IGorgonVirtualFile file = fileSystem.GetFile(path); if (file == null) { throw new FileNotFoundException(string.Format(Resources.GOR2DIO_ERR_FILE_NOT_FOUND, path)); } if ((imageCodecs == null) || (!imageCodecs.Any())) { // If we don't specify any codecs, then use the built in ones. imageCodecs = new IGorgonImageCodec[] { new GorgonCodecPng(), new GorgonCodecBmp(), new GorgonCodecDds(), new GorgonCodecGif(), new GorgonCodecJpeg(), new GorgonCodecTga(), }; } else { // Only use codecs that can decode image data. imageCodecs = imageCodecs.Where(item => item.CanDecode); } if ((animationCodecs == null) || (!animationCodecs.Any())) { // Use all built-in codecs if we haven't asked for any. animationCodecs = new IGorgonAnimationCodec[] { new GorgonV3AnimationBinaryCodec(renderer), new GorgonV3AnimationJsonCodec(renderer), new GorgonV1AnimationCodec(renderer) }; } else { // Only use codecs that can decode sprite data. animationCodecs = animationCodecs.Where(item => item.CanDecode); } Stream animStream = file.OpenStream(); try { if (!animStream.CanSeek) { Stream newStream = new DataStream((int)animStream.Length, true, true); animStream.CopyTo(newStream); newStream.Position = 0; animStream.Dispose(); animStream = newStream; } IGorgonAnimationCodec animationCodec = GetAnimationCodec(animStream, animationCodecs); if (animationCodec == null) { throw new GorgonException(GorgonResult.CannotRead, string.Format(Resources.GOR2DIO_ERR_NO_SUITABLE_ANIM_CODEC_FOUND, path)); } // Load the animation. IGorgonAnimation animation = animationCodec.FromStream(animStream, (int)file.Size); // We have no textures to update, leave. if (animation.Texture2DTrack.KeyFrames.Count == 0) { return(animation); } // Try to locate the textures. // V1 sprite animations need texture coordinate correction. bool needsCoordinateFix = animationCodec is GorgonV1AnimationCodec; foreach (GorgonKeyTexture2D textureKey in animation.Texture2DTrack.KeyFrames) { // Let's try and load the texture into memory. // This does this by: // 1. Checking to see if a texture resource with the name specified is already available in memory. // 2. Checking the local directory of the file to see if the texture is there. // 3. A file system wide search. // ReSharper disable once InvertIf (IGorgonImageCodec codec, IGorgonVirtualFile textureFile, bool loaded) = LocateTextureCodecAndFile(fileSystem, file.Directory, renderer, textureKey.TextureName, imageCodecs); // We have not loaded the texture yet. Do so now. // ReSharper disable once InvertIf if ((!loaded) && (textureFile != null) && (codec != null)) { using (Stream textureStream = textureFile.OpenStream()) { textureKey.Value = GorgonTexture2DView.FromStream(renderer.Graphics, textureStream, codec, textureFile.Size, GetTextureOptions(textureFile.FullPath, textureOptions)); } } if ((needsCoordinateFix) && (textureKey.Value != null)) { textureKey.TextureCoordinates = new RectangleF(textureKey.TextureCoordinates.X / textureKey.Value.Width, textureKey.TextureCoordinates.Y / textureKey.Value.Height, textureKey.TextureCoordinates.Width / textureKey.Value.Width, textureKey.TextureCoordinates.Height / textureKey.Value.Height); } } return(animation); } finally { animStream?.Dispose(); } }
/// <summary> /// Function called to initialize the application. /// </summary> private void Initialize() { // Resize and center the screen. var screen = Screen.FromHandle(Handle); ClientSize = Settings.Default.Resolution; Location = new Point(screen.Bounds.Left + screen.WorkingArea.Width / 2 - ClientSize.Width / 2, screen.Bounds.Top + screen.WorkingArea.Height / 2 - ClientSize.Height / 2); // Initialize our graphics. _graphics = new GorgonGraphics(); _2D = _graphics.Output.Create2DRenderer(this, ClientSize.Width, ClientSize.Height, BufferFormat.R8G8B8A8_UIntNormal, Settings.Default.IsWindowed); // Show the logo because I'm insecure. _2D.IsLogoVisible = true; // Create fonts. _textFont = _graphics.Fonts.CreateFont("GiGi_24pt", new GorgonFontSettings { FontFamilyName = "GiGi", AntiAliasingMode = FontAntiAliasMode.AntiAlias, Size = 24.0f, FontHeightMode = FontHeightMode.Points, TextureSize = new Size(512, 256) }); // Use the form font for this one. _helpFont = _graphics.Fonts.CreateFont("FormFont", new GorgonFontSettings { FontFamilyName = Font.FontFamily.Name, FontStyle = FontStyle.Bold, AntiAliasingMode = FontAntiAliasMode.AntiAlias, Size = Font.Size, FontHeightMode = FontHeightMode.Points }); // Create our file system and mount the resources. _fileSystem = new GorgonFileSystem(); _fileSystem.Mount(Program.GetResourcePath(@"FolderSystem\")); // Get the sprite image. _spriteImage = _graphics.Textures.FromMemory <GorgonTexture2D>("0_HardVacuum", _fileSystem.ReadFile("/Images/0_HardVacuum.png"), new GorgonCodecPNG()); // Get the sprites. // The sprites in the file system are from version 1.0 of Gorgon. // This version is backwards compatible and can load any version // of the sprites produced by older versions of Gorgon. _sprites = new GorgonSprite[3]; _sprites[0] = _2D.Renderables.FromMemory <GorgonSprite>("Base", _fileSystem.ReadFile("/Sprites/base.gorSprite")); _sprites[1] = _2D.Renderables.FromMemory <GorgonSprite>("Mother", _fileSystem.ReadFile("/Sprites/Mother.gorSprite")); _sprites[2] = _2D.Renderables.FromMemory <GorgonSprite>("Mother2c", _fileSystem.ReadFile("/Sprites/Mother2c.gorSprite")); // Get poetry. _textPosition = new Vector2(0, ClientSize.Height + _textFont.LineHeight); _poetry = _2D.Renderables.CreateText("Poetry", _textFont, Encoding.UTF8.GetString(_fileSystem.ReadFile("/SomeText.txt")), Color.Black); _poetry.Position = _textPosition; // Set up help text. _helpText = _2D.Renderables.CreateText("Help", _helpFont, "F1 - Show/hide this help text.\nS - Show frame statistics.\nESC - Exit.", Color.Blue); _helpText.Position = new Vector2(3, 3); // Set the initial blur value. // We set a small render target for the blur, this will help // speed up the effect. _2D.Effects.GaussianBlur.BlurAmount = 13.0f; _2D.Effects.GaussianBlur.BlurRenderTargetsSize = new Size(128, 128); _2D.Effects.GaussianBlur.RenderScene = pass => { // Draw the sprite at the upper left corner instead of // centered. Otherwise it'll be centered in the blur // render target and will be clipped. _sprites[2].Anchor = Vector2.Zero; _sprites[2].Position = Vector2.Zero; // Scale to the size of the blur target. _sprites[2].Scale = new Vector2(1.0f, _2D.Effects.GaussianBlur.BlurRenderTargetsSize.Height / _sprites[2].Size.Y); // Adjust the texture size to avoid bleed when blurring. // Bleed means that other portions of the texture get pulled // in to the texture because of bi-linear filtering (and the // blur operates in a similar manner, and therefore unwanted // pixels get pulled in as well). // See http://tape-worm.net/?page_id=277 for more info. _sprites[2].TextureSize = new Vector2(125.0f / _spriteImage.Settings.Width, _sprites[2].TextureSize.Y); _sprites[2].Draw(); // Reset. _sprites[2].TextureSize = new Vector2(128.0f / _spriteImage.Settings.Width, _sprites[2].TextureSize.Y); }; Gorgon.ApplicationIdleLoopMethod = Idle; }
/// <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); }
/// <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); }
/// <summary> /// Function to load a <see cref="GorgonPolySprite"/> from a <see cref="GorgonFileSystem"/>. /// </summary> /// <param name="fileSystem">The file system to load the sprite from.</param> /// <param name="renderer">The renderer for the sprite.</param> /// <param name="path">The path to the sprite file in the file system.</param> /// <param name="textureOptions">[Optional] Options for the texture loaded associated the sprite.</param> /// <param name="spriteCodecs">The list of polygonal sprite codecs to try and load the sprite with.</param> /// <param name="imageCodecs">The list of image codecs to try and load the sprite texture with.</param> /// <returns>The sprite data in the file as a <see cref="GorgonSprite"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fileSystem"/>, <paramref name="renderer"/>, or <paramref name="path"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="path"/> parameter is empty.</exception> /// <exception cref="FileNotFoundException">Thrown if the file in the <paramref name="path"/> was not found.</exception> /// <exception cref="GorgonException">Thrown if the sprite data in the file system could not be loaded because a suitable codec was not found.</exception> /// <remarks> /// <para> /// This method extends a <see cref="GorgonFileSystem"/> so that sprites can be loaded by calling a method on the file system object itself. This negates the need for users to create complex code /// for loading a sprite. /// </para> /// <para> /// When loading a sprite, the method will attempt to locate the <see cref="GorgonTexture2DView"/> associated with the sprite (if it exists). When loading, it will check: /// <list type="number"> /// <item> /// <description>For a texture resource with the same name that is already loaded into memory.</description> /// </item> /// <item> /// <description>Use the local <see cref="IGorgonVirtualDirectory"/> for the sprite file and search for the texture in that directory.</description> /// </item> /// <item> /// <description>Check the entire <paramref name="fileSystem"/> for a file if the texture name contains path information (this is done by the GorgonEditor from v2).</description> /// </item> /// </list> /// If the file is found, and can be loaded by one of the <paramref name="imageCodecs"/>, then it is loaded and assigned to the sprite. /// </para> /// <para> /// The <paramref name="spriteCodecs"/> is a list of codecs for loading polygonal sprite data. If the user specifies this parameter, the only the codecs provided will be used for determining if a /// sprite can be read. If it is not supplied, then all built-in (i.e. not plug in based) sprite codecs will be used. /// </para> /// <para> /// The <paramref name="imageCodecs"/> is a list of codecs for loading image data. If the user specifies this parameter, the only the codecs provided will be used for determining if an image can be /// read. If it is not supplied, then all built-in (i.e. not plug in based) image codecs will be used. /// </para> /// </remarks> /// <seealso cref="GorgonFileSystem"/> /// <seealso cref="GorgonTexture2DView"/> /// <seealso cref="GorgonPolySprite"/> public static GorgonPolySprite LoadPolySpriteFromFileSystem(this GorgonFileSystem fileSystem, Gorgon2D renderer, string path, GorgonTexture2DLoadOptions textureOptions = null, IEnumerable <IGorgonPolySpriteCodec> spriteCodecs = null, IEnumerable <IGorgonImageCodec> imageCodecs = null) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } IGorgonVirtualFile file = fileSystem.GetFile(path); if (file == null) { throw new FileNotFoundException(string.Format(Resources.GOR2DIO_ERR_FILE_NOT_FOUND, path)); } if ((imageCodecs == null) || (!imageCodecs.Any())) { // If we don't specify any codecs, then use the built in ones. imageCodecs = new IGorgonImageCodec[] { new GorgonCodecPng(), new GorgonCodecBmp(), new GorgonCodecDds(), new GorgonCodecGif(), new GorgonCodecJpeg(), new GorgonCodecTga(), }; } else { // Only use codecs that can decode image data. imageCodecs = imageCodecs.Where(item => item.CanDecode); } if ((spriteCodecs == null) || (!spriteCodecs.Any())) { // Use all built-in codecs if we haven't asked for any. spriteCodecs = new IGorgonPolySpriteCodec[] { new GorgonV3PolySpriteBinaryCodec(renderer), new GorgonV3PolySpriteJsonCodec(renderer) }; } else { // Only use codecs that can decode sprite data. spriteCodecs = spriteCodecs.Where(item => item.CanDecode); } Stream spriteStream = file.OpenStream(); try { if (!spriteStream.CanSeek) { Stream newStream = new DataStream((int)spriteStream.Length, true, true); spriteStream.CopyTo(newStream); newStream.Position = 0; spriteStream.Dispose(); spriteStream = newStream; } IGorgonPolySpriteCodec spriteCodec = GetPolySpriteCodec(spriteStream, spriteCodecs); if (spriteCodec == null) { throw new GorgonException(GorgonResult.CannotRead, string.Format(Resources.GOR2DIO_ERR_NO_SUITABLE_SPRITE_CODEC_FOUND, path)); } // Try to locate the texture. string textureName = spriteCodec.GetAssociatedTextureName(spriteStream); GorgonTexture2DView textureForSprite = null; // Let's try and load the texture into memory. // This does this by: // 1. Checking to see if a texture resource with the name specified is already available in memory. // 2. Checking the local directory of the file to see if the texture is there. // 3. A file system wide search. // ReSharper disable once InvertIf if (!string.IsNullOrWhiteSpace(textureName)) { (IGorgonImageCodec codec, IGorgonVirtualFile textureFile, bool loaded) = LocateTextureCodecAndFile(fileSystem, file.Directory, renderer, textureName, imageCodecs); // We have not loaded the texture yet. Do so now. // ReSharper disable once InvertIf if ((!loaded) && (textureFile != null) && (codec != null)) { using (Stream textureStream = textureFile.OpenStream()) { textureForSprite = GorgonTexture2DView.FromStream(renderer.Graphics, textureStream, codec, textureFile.Size, GetTextureOptions(textureFile.FullPath, textureOptions)); } } } return(spriteCodec.FromStream(spriteStream, textureForSprite, (int)file.Size)); } finally { spriteStream?.Dispose(); } }
/// <summary> /// Function to retrieve the total number of files in this directory and any directories under this one. /// </summary> /// <returns>The total number of files.</returns> /// <remarks> /// Use this to retrieve the total number of <see cref="IGorgonVirtualFile"/> entries under this directory. This search includes all sub directories for this and child directories. To get /// the count of the immediate files, use the <see cref="IReadOnlyCollection{T}.Count"/> property on the <see cref="IGorgonVirtualDirectory.Files"/> property. /// </remarks> public int GetFileCount() => GorgonFileSystem.FlattenDirectoryHierarchy(this, "*").Sum(item => item.Files.Count) + Files.Count;
/// <summary> /// Function called to initialize the application. /// </summary> private void Initialize() { GorgonExample.ResourceBaseDirectory = new DirectoryInfo(Settings.Default.ResourceLocation); // Resize and center the screen. var screen = Screen.FromHandle(Handle); ClientSize = Settings.Default.Resolution; Location = new Point(screen.Bounds.Left + (screen.WorkingArea.Width / 2) - (ClientSize.Width / 2), screen.Bounds.Top + (screen.WorkingArea.Height / 2) - (ClientSize.Height / 2)); // Initialize our graphics. IReadOnlyList <IGorgonVideoAdapterInfo> videoAdapters = GorgonGraphics.EnumerateAdapters(log: GorgonApplication.Log); if (videoAdapters.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(videoAdapters.OrderByDescending(item => item.FeatureSet).First()); // Build our "screen". _screen = new GorgonSwapChain(_graphics, this, new GorgonSwapChainInfo { Width = ClientSize.Width, Height = ClientSize.Height, Format = BufferFormat.R8G8B8A8_UNorm }); if (!Settings.Default.IsWindowed) { // Go full screen by using borderless windowed mode. _screen.EnterFullScreen(); } // Build up our 2D renderer. _renderer = new Gorgon2D(_graphics); // Load in the logo texture from our resources. GorgonExample.LoadResources(_graphics); // Create fonts. _textFont = GorgonExample.Fonts.GetFont(new GorgonFontInfo("GiGi", 24.0f, FontHeightMode.Points, "GiGi_24pt") { AntiAliasingMode = FontAntiAliasMode.AntiAlias, TextureWidth = 512, TextureHeight = 256 }); // Use the form font for this one. _helpFont = GorgonExample.Fonts.GetFont(new GorgonFontInfo(Font.FontFamily.Name, Font.Size, Font.Unit == GraphicsUnit.Pixel ? FontHeightMode.Pixels : FontHeightMode.Points, "Form Font") { AntiAliasingMode = FontAntiAliasMode.AntiAlias, FontStyle = FontStyle.Bold }); // Create our file system and mount the resources. _fileSystem = new GorgonFileSystem(GorgonApplication.Log); _fileSystem.Mount(GorgonExample.GetResourcePath(@"FileSystems\FolderSystem").FullName); // In the previous versions of Gorgon, we used to load the image first, and then the sprites. // But in this version, we have an extension that will load the sprite textures for us. _sprites = new GorgonSprite[3]; // The sprites are in the v2 format. IEnumerable <IGorgonSpriteCodec> v2Codec = new[] { new GorgonV2SpriteCodec(_renderer) }; IEnumerable <IGorgonImageCodec> pngCodec = new[] { new GorgonCodecPng() }; _sprites[0] = _fileSystem.LoadSpriteFromFileSystem(_renderer, "/Sprites/base.gorSprite", spriteCodecs: v2Codec, imageCodecs: pngCodec); _sprites[1] = _fileSystem.LoadSpriteFromFileSystem(_renderer, "/Sprites/Mother.gorSprite", spriteCodecs: v2Codec, imageCodecs: pngCodec); _sprites[2] = _fileSystem.LoadSpriteFromFileSystem(_renderer, "/Sprites/Mother2c.gorSprite", spriteCodecs: v2Codec, imageCodecs: pngCodec); // This is how you would get the sprites in v2 of Gorgon: /*_spriteImage = _graphics.Textures.FromMemory<GorgonTexture2D>("0_HardVacuum", LoadFile("/Images/0_HardVacuum.png"), new GorgonCodecPNG()); * * // Get the sprites. * // The sprites in the file system are from version 1.0 of Gorgon. * // This version is backwards compatible and can load any version * // of the sprites produced by older versions of Gorgon. * _sprites = new GorgonSprite[3]; * _sprites[0] = _renderer.Renderables.FromMemory<GorgonSprite>("Base", LoadFile("/Sprites/base.gorSprite")); * _sprites[1] = _renderer.Renderables.FromMemory<GorgonSprite>("Mother", LoadFile("/Sprites/Mother.gorSprite")); * _sprites[2] = _renderer.Renderables.FromMemory<GorgonSprite>("Mother2c", LoadFile("/Sprites/Mother2c.gorSprite")); */ // Get poetry. _textPosition = new DX.Vector2(0, ClientSize.Height + _textFont.LineHeight); _poetry = new GorgonTextSprite(_textFont, Encoding.UTF8.GetString(LoadFile("/SomeText.txt"))) { Position = _textPosition, Color = Color.Black }; // Set up help text. _helpText = new GorgonTextSprite(_helpFont, "F1 - Show/hide this help text.\nS - Show frame statistics.\nESC - Exit.") { Color = Color.Blue, Position = new DX.Vector2(3, 3) }; // Unlike the old example, we'll blend to render targets, ping-ponging back and forth, for a much better quality image and smoother transition. _blurEffect = new Gorgon2DGaussBlurEffect(_renderer, 3) { BlurRenderTargetsSize = new DX.Size2((int)_sprites[2].Size.Width * 2, (int)_sprites[2].Size.Height * 2), PreserveAlpha = false }; _blurEffect.Precache(); _blurredTarget[0] = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, new GorgonTexture2DInfo("Blurred RTV") { Width = _blurEffect.BlurRenderTargetsSize.Width, Height = _blurEffect.BlurRenderTargetsSize.Height, Binding = TextureBinding.ShaderResource, Format = BufferFormat.R8G8B8A8_UNorm, Usage = ResourceUsage.Default }); _blurredTarget[1] = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, _blurredTarget[0]); _blurredImage[0] = _blurredTarget[0].GetShaderResourceView(); _blurredImage[1] = _blurredTarget[1].GetShaderResourceView(); GorgonApplication.IdleMethod = Idle; }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFileSystemProviderCollection"/> class. /// </summary> /// <param name="fileSystem">File system that owns this collection.</param> internal GorgonFileSystemProviderCollection(GorgonFileSystem fileSystem) : base(false) { _fileSystem = fileSystem; }