/// <summary> /// Saves a GUIOMETRY.BIN data class to the disk. /// </summary> /// <param name="data">The GUIOMETRY data class.</param> /// <param name="filename">The filename to save as.</param> /// <returns>Whether the save was successful or not.</returns> public static bool Save(GUIOMETRY data, string filename) { // Collect data class metadata var textureMetadata = new Dictionary<byte, string>(); // For each of these, only add the metadata if the source of the texture is not blank or null // Add font metadata foreach (var font in data.Fonts) { if (!string.IsNullOrEmpty(font.Value.Texture.Source)) textureMetadata.Add(GetTextureNameToID(font.Key), font.Value.Texture.Source); } // Add element metadata foreach (var element in data.Elements) { // In here element.Key is the internal name of the element, and element.Value is the ElementInfo object if (!string.IsNullOrEmpty(element.Value.Texture.Source)) textureMetadata.Add(GetTextureNameToID(element.Key), element.Value.Texture.Source); } // Construct the save data file var saveData = new List<byte>(); saveData.Add(GUIOMETRY.VERSION); // Add format version byte // Add metadata foreach (var metadata in textureMetadata) { saveData.Add(metadata.Key); // Texture ID saveData.AddRange(UnicodeEncoding.Unicode.GetBytes(metadata.Value + "\0")); // Texture path with NULL char } saveData.Add(0); // End metadata byte // Add font data saveData.AddRange(data.Fonts["ChatFont"].GetBytes()); saveData.AddRange(data.Fonts["SmallFont"].GetBytes()); saveData.AddRange(data.Fonts["MediumFont"].GetBytes()); saveData.AddRange(data.Fonts["HugeFont"].GetBytes()); // Add element data and save saveData.AddRange(data.GetElementInfo("Button")); saveData.AddRange(data.GetElementInfo("Text")); saveData.AddRange(data.GetElementInfo("Check")); return Files.PutBinaryFile(filename, saveData.ToArray()); }
/// <summary> /// Reads a GUIOMETRY.BIN file into its data class. /// </summary> /// <param name="filename">The filename of the GUIOMETRY.BIN to read.</param> /// <returns>A GUIOMETRY data class with the contents of the file if it exists, null otherwise.</returns> public static GUIOMETRY Read(string filename) { // This function is still a WIP, implementing reading of GUIOMETRY.BIN files // The spec for this can be found inside of formats.md in the project root! if (!File.Exists(filename)) { return null; } var guiometry = new GUIOMETRY(); // The result we're working on IList<byte> guiometryFile = Files.GetBinaryFile(filename); int currentIndex = 0; // Index of the byte in the array we're reading bool nextSection = false; // Set this to true to move onto the next section // Get the version before doing anything byte version = ByteParse.NextByte(guiometryFile, ref currentIndex); // Read file metadata (for the textures) while (!nextSection && currentIndex <= guiometryFile.Count - 1) { byte textureID = ByteParse.NextByte(guiometryFile, ref currentIndex); if (textureID == 0) // End of metadata { nextSection = true; } else { string textureName = GetTextureIDToName(textureID); string textureSource = ByteParse.NextString(guiometryFile, ref currentIndex); // Attempt to assign textures to relevant objects in their dictionaries. if (File.Exists(textureSource)) { if (textureName.EndsWith("Font")) // Assign inside of the Fonts Dictionary { guiometry.Fonts[textureName].Texture.Source = textureSource; guiometry.Fonts[textureName].Texture.Data = Image.FromFile(textureSource); } else if (textureName.StartsWith("Button") || textureName.StartsWith("Text") || textureName.StartsWith("Check")) // Assign inside of the Elements Dictionary { guiometry.Elements[textureName].Texture.Source = textureSource; guiometry.Elements[textureName].Texture.Data = Image.FromFile(textureSource); } } } } if (version == 1) { #region Version 1 // This should be the fonts to look for (eg. ChatFont, SmallFont etc.) in the order they are // supposed to be according to the format string[] fonts = new string[] { "ChatFont", "SmallFont", "MediumFont", "HugeFont" }; // Keep track of the current character being read (out of the number in the font) short currentChar = 0; // Make sure to reset this to 0 after reading a font or you will be shot // However many characters are in the font being read short charsInFont; // This should be the elements to look for (eg. Button, Text etc.) in the order they are // supposed to be according to the format string[] elements = new string[] { "Button", "Text", "Check" }; // This should be the 'parts' of the elements to look for (eg. Body, Top, Side etc.) in the // order they are supposed to be according to the format string[] elementParts; #region Font Data foreach (string font in fonts) { charsInFont = ByteParse.NextShort(guiometryFile, ref currentIndex); while (currentChar++ < charsInFont) { char character = ByteParse.NextChar(guiometryFile, ref currentIndex); guiometry.Fonts[font].AddNewCharacter(character, NextCharacter(guiometryFile, ref currentIndex)); } guiometry.Fonts[font].SpacingWidth = ByteParse.NextByte(guiometryFile, ref currentIndex); guiometry.Fonts[font].LineHeight = ByteParse.NextByte(guiometryFile, ref currentIndex); currentChar = 0; } #endregion #region Element Data foreach (string element in elements) { // Set up the parts to look for... if (element == "Button" || element == "Text") elementParts = new string[] { "Top", "Side", "EdgeSE", "EdgeSW" }; else // element == "CheckBox" elementParts = new string[] { "Top", "Side", "EdgeSE", "EdgeSW", "Tick" }; foreach (string part in elementParts) { if (part == "Side" || part == "EdgeSE" || part == "EdgeSW" || part == "Tick") guiometry.Elements[element + part].XOffset = ByteParse.NextSByte(guiometryFile, ref currentIndex); if (part == "Top" || part == "EdgeSE" || part == "EdgeSW" || part == "Tick") guiometry.Elements[element + part].YOffset = ByteParse.NextSByte(guiometryFile, ref currentIndex); } // Read the element details too if (element == "Button") { guiometry.ButtonCentredText = ByteParse.NextBool(guiometryFile, ref currentIndex); guiometry.ButtonOffsetTop = ByteParse.NextSByte(guiometryFile, ref currentIndex); guiometry.ButtonOffsetLeft = ByteParse.NextSByte(guiometryFile, ref currentIndex); } else if (element == "Text") { guiometry.TextCentredText = ByteParse.NextBool(guiometryFile, ref currentIndex); guiometry.TextOffsetTop = ByteParse.NextSByte(guiometryFile, ref currentIndex); guiometry.TextOffsetLeft = ByteParse.NextSByte(guiometryFile, ref currentIndex); } } #endregion #endregion } return guiometry; }