/// <summary> /// Function to load a single dependency for a file. /// </summary> /// <param name="dependency">Dependency to load.</param> /// <param name="childDependencies">The dependencies for this dependency.</param> /// <returns>The loaded dependency object.</returns> private object LoadDependency(GorgonEditorDependency dependency, IReadOnlyDictionary <GorgonEditorDependency, object> childDependencies) { GorgonFileSystemFileEntry dependencyFile = FileSystem.GetFile(dependency.Path); if (dependencyFile == null) { throw new IOException(string.Format(Resources.GORFS_ERR_DEPENDENCY_NOT_FOUND, dependency.Path)); } // Find a handler for this file. KeyValuePair <Type, Func <Stream, IReadOnlyDictionary <GorgonEditorDependency, object>, object> > handler = _fileHandlers.FirstOrDefault(item => string.Equals(item.Key.FullName, dependency.Type, StringComparison.OrdinalIgnoreCase)); if (handler.Key == null) { throw new IOException(string.Format(Resources.GORFS_ERR_FILE_NO_HANDLER, dependency.Path)); } using (Stream dependencyStream = dependencyFile.OpenStream(false)) { return(handler.Value(dependencyStream, childDependencies)); } }
/// <summary> /// Function to determine if the directory contains the specified file. /// </summary> /// <param name="file">File to look for.</param> /// <param name="searchChildren">[Optional] TRUE to search through child directories, FALSE to only search this directory.</param> /// <returns>TRUE if found, FALSE if not.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="file"/> parameter is NULL (Nothing in VB.Net).</exception> public bool Contains(GorgonFileSystemFileEntry file, bool searchChildren = true) { if (file == null) { throw new ArgumentNullException("file"); } return(Files.Any(item => item == file) || ((searchChildren) && (Directories.Any(directory => directory.Contains(file))))); }
/// <summary> /// Function to load a file from the editor file. /// </summary> /// <typeparam name="T">The type of object to load. Must be a reference type.</typeparam> /// <param name="path">Path to the file to load.</param> /// <remarks> /// Use this method to load a file from the file system generated by the editor. The type parameter T is used to determine how to load an object through a registered type loader. /// <para>The type loader is registered by supplying a type and a function to read in the file. This allows the developer to load in their own file formats if required. New loader types /// can be added through the <see cref="RegisteredEditorTypes"/> parameter.</para> /// <para>Without adding any new loader types Gorgon will support loading of its supported image codecs, sprites (for the 2D renderer), animations and fonts. The loader will attempt to load /// any dependencies required by the requested file as well.</para> /// </remarks> public T ReadFile <T>(string path) where T : class { if (path == null) { throw new ArgumentNullException("path"); } if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentException(Resources.GORFS_ERR_PARAMETER_MUST_NOT_BE_EMPTY, "path"); } Type type = typeof(T); Func <Stream, IReadOnlyDictionary <GorgonEditorDependency, object>, object> loader; if (!_fileHandlers.TryGetValue(type, out loader)) { throw new IOException(string.Format(Resources.GORFS_ERR_FILE_NO_HANDLER, path)); } GorgonFileSystemFileEntry file = FileSystem.GetFile(path); if (file == null) { throw new IOException(string.Format(Resources.GORFS_ERR_FILE_NOT_FOUND, path)); } // Load the meta data if it's not been loaded yet. if (_hasMetaData == null) { GetDependencies(); } GorgonEditorDependencyCollection dependencies; IReadOnlyDictionary <GorgonEditorDependency, object> dependencyObjects = new Dictionary <GorgonEditorDependency, object>(); // Check to see if the file has dependencies. if (Dependencies.TryGetValue(file.FullPath, out dependencies)) { dependencyObjects = LoadDependencies(dependencies); } using (Stream fileStream = file.OpenStream(false)) { return((T)loader(fileStream, dependencyObjects)); } }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFileSystemStream"/> class. /// </summary> /// <param name="file">File being read/written.</param> /// <param name="baseStream">The underlying stream to use for this stream.</param> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="baseStream"/> or the <paramref name="file"/> parameter is NULL (Nothing in VB.Net).</exception> public GorgonFileSystemStream(GorgonFileSystemFileEntry file, Stream baseStream) { if (file == null) { throw new ArgumentNullException("file"); } if (baseStream == null) { throw new ArgumentNullException("baseStream"); } CloseUnderlyingStream = true; _baseStream = baseStream; FileEntry = file; // Reset the position to the beginning. if (_baseStream.CanSeek) { _baseStream.Position = 0; } }
/// <summary> /// Function called when a file is read from the provider. /// </summary> /// <param name="file">File to read.</param> /// <returns>The file data stored in a byte array or NULL if the file could not be read.</returns> /// <remarks>Implementors must implement this method to read the file from the physical file system.</remarks> protected internal virtual byte[] OnReadFile(GorgonFileSystemFileEntry file) { byte[] data; // Return an empty file if the file does not exist on the physical file system. if (!File.Exists(file.PhysicalFileSystemPath)) { return(new byte[0]); } using (FileStream stream = File.Open(file.PhysicalFileSystemPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { data = new byte[stream.Length]; if (stream.Length > 0) { stream.Read(data, 0, (int)stream.Length); } } return(data); }
/// <summary> /// Function called when a file is opened as a file stream. /// </summary> /// <param name="file">File to open.</param> /// <returns>The open <see cref="GorgonFileSystemStream"/> file stream object.</returns> protected internal virtual GorgonFileSystemStream OnOpenFileStream(GorgonFileSystemFileEntry file) { return(new GorgonFileSystemStream(file, File.Open(file.PhysicalFileSystemPath, FileMode.Open, FileAccess.Read, FileShare.Read))); }
/// <summary> /// Function to retrieve the dependencies file and process it. /// </summary> private void GetDependencies() { if ((_hasMetaData != null) && (!_hasMetaData.Value)) { return; } // If we've already loaded the file system meta data for this file system, then leave. if (_metaDataFile != null) { return; } GorgonFileSystemFileEntry file = FileSystem.GetFile(MetaDataFile); if (file == null) { _hasMetaData = false; return; } // Create and load the object. using (Stream metaFile = file.OpenStream(false)) { _metaDataFile = XDocument.Load(metaFile); } XElement rootNode = _metaDataFile.Element(MetaDataRootName); if (rootNode == null) { _hasMetaData = false; return; } XElement dependencyNode = rootNode.Element(ContentDependencyFiles); if (dependencyNode == null) { _hasMetaData = false; return; } IEnumerable <XElement> fileNodes = dependencyNode.Elements(FileNode); var dependencies = new Dictionary <string, GorgonEditorDependencyCollection>(); // Lock here because we're updating a collection that's not thread safe. foreach (XElement fileNode in fileNodes) { XAttribute path = fileNode.Attribute(NameAttr); if ((path == null) || (string.IsNullOrWhiteSpace(path.Value))) { continue; } dependencies.Add(path.Value, GorgonEditorDependencyCollection .Deserialize(fileNode.Elements(GorgonEditorDependency.DependencyNode))); } Dependencies = dependencies; _hasMetaData = Dependencies.Count > 0; }