public static void Font(ProjectWriter writer, GMFont self, GMProject _) { writer.Write(self.Name); writer.Write(self.Version); writer.Write(self.FontName); writer.Write(self.Size); writer.Write(self.Bold); writer.Write(self.Italic); writer.Write(self.RangeMinInt); writer.Write(self.RangeMax); // generate le font texture. FontManager.FontResult fnt = FontManager.FindFont(self.FontName, self.Size, self.Bold, self.Italic, 0, self.RangeMin, self.RangeMax, self.AA); // glyph table. (there are always 255 of them) for (int chr = 0; chr < 256; chr++) { // write dummy glyph if out of range. if (chr < self.RangeMin || chr > self.RangeMax) { for (int a = 0; a < 6; a++) { writer.Write(0); // x,y,w,h,shift,offset. } continue; } // write actual glyph. for (int a = 0; a < 6; a++) { writer.Write(fnt.Glyphs[chr][a]); } } // write the generated font texture as an Alpha-only bitmap. writer.Write(fnt.Width); writer.Write(fnt.Height); writer.Write(fnt.Texture.Length); writer.Write(fnt.Texture); }
public override void ConvertData(ProjectFile pf, int index) { GMFont asset = (GMFont)pf.Fonts[index].DataAsset; AssetFont projectAsset = new AssetFont() { Name = asset.Name?.Content, DisplayName = asset.DisplayName?.Content, Bold = asset.Bold, Italic = asset.Italic, Charset = asset.Charset, AntiAlias = asset.AntiAlias, ScaleX = asset.ScaleX, ScaleY = asset.ScaleY, TextureItem = asset.TextureItem, TextureGroup = pf.Textures.TextureGroups[pf.Textures.PageToGroup[asset.TextureItem.TexturePageID]].Name, Glyphs = asset.Glyphs.ToList() }; if (asset.Size < 0) { projectAsset.SizeFloat = asset.SizeFloat; } else { projectAsset.Size = asset.Size; } if (pf.DataHandle.VersionInfo.FormatID >= 17) { projectAsset.AscenderOffset = asset.AscenderOffset; } pf.Fonts[index].Asset = projectAsset; }
/// <summary> /// Reads a Game Maker project file /// </summary> public void ReadProject(string file) { // If the file does not exist, throw exception if (File.Exists(file) == false) { throw new Exception("The Game Maker project file does not exist."); } // Get file extension string ext = file.Substring(file.LastIndexOf('.')).ToLower(); // If a GMS project file if (ext == ".gmx") { // Read in the project as a Game Maker Studio project and return ReadProjectGMS(file); return; } // Get file size FileInfo info = new FileInfo(file); long length = info.Length; // Create a new GM file reader using (GMFileReader reader = new GMFileReader(new FileStream(file, FileMode.Open, FileAccess.Read))) { // Progress event ProgressChanged("Starting project read...", reader.BaseStream.Position, length); // Read the magic number int id = reader.ReadGMInt(); // If the magic number was incorrect, not a Game Maker project file if (id != 1234321) { throw new Exception("Not a valid Game Maker project file."); } // Get Game Maker project file version int version = reader.ReadGMInt(); // Check version switch (version) { case 500: this.GameMakerVersion = GMVersionType.GameMaker50; break; case 510: this.GameMakerVersion = GMVersionType.GameMaker51; break; case 520: this.GameMakerVersion = GMVersionType.GameMaker52; break; case 530: this.GameMakerVersion = GMVersionType.GameMaker53; break; case 600: this.GameMakerVersion = GMVersionType.GameMaker60; break; case 701: this.GameMakerVersion = GMVersionType.GameMaker70; break; case 800: this.GameMakerVersion = GMVersionType.GameMaker80; break; case 810: this.GameMakerVersion = GMVersionType.GameMaker81; break; } // Skip over reserved bytes if (version < 600) { reader.ReadGMBytes(4); } // Game Maker 7 project file encryption if (version == 701) { // Bill and Fred, psssttt they like each other ;) int bill = reader.ReadGMInt(); int fred = reader.ReadGMInt(); // Skip bytes to treasure. reader.ReadGMBytes(bill * 4); // Get the seed for swap table int seed = reader.ReadGMInt(); // Skip bytes to get out of the junk yard reader.ReadGMBytes(fred * 4); // Read first byte of Game id (Not encrypted) byte b = reader.ReadByte(); // Set the seed reader.SetSeed(seed); // Read game id id = reader.ReadGMInt(b); } else // Read game id normally { id = reader.ReadGMInt(); } // Skip unknown bytes reader.ReadGMBytes(16); // Read settings ProgressChanged("Reading Settings...", reader.BaseStream.Position, length); // Read main project objects this.Settings = GMSettings.ReadSettings(reader); this.Settings.GameIdentifier = id; // If the version is greater than Game Maker 7.0 if (version > 701) { // Read triggers and constants. this.Triggers = GMTrigger.ReadTriggers(reader); this.Settings.Constants = GMConstant.ReadConstants(reader); } // Read sounds ProgressChanged("Reading Sounds...", reader.BaseStream.Position, length); this.Sounds = GMSound.ReadSounds(reader); // Read sprites ProgressChanged("Reading Sprites...", reader.BaseStream.Position, length); this.Sprites = GMSprite.ReadSprites(reader); // Read backgrounds ProgressChanged("Reading Backgrounds...", reader.BaseStream.Position, length); this.Backgrounds = GMBackground.ReadBackgrounds(reader); // Read paths ProgressChanged("Reading Paths...", reader.BaseStream.Position, length); this.Paths = GMPath.ReadPaths(reader); // Read scripts ProgressChanged("Reading Scripts...", reader.BaseStream.Position, length); this.Scripts = GMScript.ReadScripts(reader); // Get version int version2 = reader.ReadGMInt(); // Check version if (version2 != 440 && version2 != 540 && version2 != 800) { throw new Exception("Unsupported Pre-Font/Pre-Data File object version."); } // If version is old, read data files else, read fonts. if (version2 == 440) { // Read data files ProgressChanged("Reading Data Files...", reader.BaseStream.Position, length); this.DataFiles = GMDataFile.ReadDataFiles(reader); } else { // Read fonts ProgressChanged("Reading Fonts...", reader.BaseStream.Position, length); this.Fonts = GMFont.ReadFonts(version2, reader); } // Read timelines ProgressChanged("Reading Timelines...", reader.BaseStream.Position, length); this.Timelines = GMTimeline.ReadTimelines(reader); // Read objects ProgressChanged("Reading Objects...", reader.BaseStream.Position, length); this.Objects = GMObject.ReadObjects(reader); // Read rooms ProgressChanged("Reading Rooms...", reader.BaseStream.Position, length); this.Rooms = GMRoom.ReadRooms(this.Objects, reader); // Read last ids for instances and tiles this.LastInstanceId = reader.ReadGMInt(); this.LastTileId = reader.ReadGMInt(); // If the version is above 6.1, read include files and packages if (version >= 700) { // Read includes ProgressChanged("Reading Includes...", reader.BaseStream.Position, length); this.Settings.Includes = GMInclude.ReadIncludes(reader); // Read packages ProgressChanged("Reading Packages...", reader.BaseStream.Position, length); this.Packages.AddRange(GMPackage.ReadPackages(reader)); } // Read game information ProgressChanged("Reading Game Information...", reader.BaseStream.Position, length); this.GameInformation = GMGameInformation.ReadGameInformation(reader); // Get version version = reader.ReadGMInt(); // Check version if (version != 500) { throw new Exception("Unsupported Post-Game Information object version."); } // Read libraries ProgressChanged("Reading Libraries...", reader.BaseStream.Position, length); this.Libraries = GMLibrary.ReadLibraries(reader); // Read project tree ProgressChanged("Reading Project Tree...", reader.BaseStream.Position, length); this.ProjectTree = GMNode.ReadTree(file.Substring(file.LastIndexOf(@"\") + 1), reader); // Progress event ProgressChanged("Finished Reading Project.", reader.BaseStream.Position, length); } }
/// <summary> /// Reads fonts from GM file. /// </summary> private GMList<GMFont> ReadFonts(int version) { // Create a new list of fonts. GMList<GMFont> fonts = new GMList<GMFont>(); // Amount of font ids. int num = ReadInt(); // Iterate through fonts. for (int i = 0; i < num; i++) { // If version is 8.0, start inflate. if (version == 800) Decompress(); // If the font at index does not exists, continue. if (ReadBool() == false) { fonts.LastId++; EndDecompress(); continue; } // Create a new font object. GMFont font = new GMFont(); // Set font id. font.Id = i; // Read font data. font.Name = ReadString(); // If version is 8.0, get last changed. if (version == 800) font.LastChanged = ReadDouble(); // Get version. version = ReadInt(); // Check version. if (version != 540 && version != 800) throw new Exception("Unsupported Font object version."); // Read font data. font.FontName = ReadString(); font.Size = ReadInt(); font.Bold = ReadBool(); font.Italic = ReadBool(); font.CharacterRangeMin = ReadInt(); font.CharacterRangeMax = ReadInt(); // End object inflate. EndDecompress(); // Add font. fonts.Add(font); } // Return fonts. return fonts; }
public override void ConvertProject(ProjectFile pf) { var dataAssets = pf.DataHandle.GetChunk <GMChunkFONT>().List; // Assemble dictionary of group names to actual Group classes Dictionary <string, Textures.Group> groupNames = new Dictionary <string, Textures.Group>(); foreach (var g in pf.Textures.TextureGroups) { groupNames[g.Name] = g; } List <GMFont> newList = new List <GMFont>(); for (int i = 0; i < pf.Fonts.Count; i++) { AssetFont projectAsset = pf.Fonts[i].Asset; if (projectAsset == null) { // This asset was never converted newList.Add((GMFont)pf.Fonts[i].DataAsset); continue; } // Add texture item to proper texture group if (projectAsset.TextureGroup != null && groupNames.TryGetValue(projectAsset.TextureGroup, out var group)) { group.AddNewEntry(pf.Textures, projectAsset.TextureItem); } else { // Make a new texture group for this var g = new Textures.Group() { Dirty = true, Border = 0, AllowCrop = false, Name = $"__DS_AUTO_GEN_{projectAsset.Name}__{pf.Textures.TextureGroups.Count}" }; g.AddNewEntry(pf.Textures, projectAsset.TextureItem); pf.Textures.TextureGroups.Add(g); } GMFont dataAsset = new GMFont() { Name = pf.DataHandle.DefineString(projectAsset.Name), DisplayName = pf.DataHandle.DefineString(projectAsset.DisplayName), Bold = projectAsset.Bold, Italic = projectAsset.Italic, Charset = projectAsset.Charset, AntiAlias = projectAsset.AntiAlias, ScaleX = projectAsset.ScaleX, ScaleY = projectAsset.ScaleY, TextureItem = projectAsset.TextureItem, Glyphs = new Core.GMUniquePointerList <GMGlyph>() }; if (projectAsset.Size != null) { dataAsset.Size = (int)projectAsset.Size; } else { dataAsset.SizeFloat = (float)projectAsset.SizeFloat; } foreach (var g in projectAsset.Glyphs.OrderBy(g => g.Character)) { dataAsset.Glyphs.Add(g); } if (dataAsset.Glyphs.Count != 0) { dataAsset.RangeStart = dataAsset.Glyphs[0].Character; dataAsset.RangeEnd = dataAsset.Glyphs[^ 1].Character;