예제 #1
0
 public void PostLoad(GMProject proj)
 {
     if (_ParentInd > -1)
     {
         Parent = proj.Objects[_ParentInd];
     }
 }
예제 #2
0
        public void Load(ProjectReader reader, GMProject proj)
        {
            int _x, _y, _w, _h;

            Visible    = reader.ReadBoolean();
            _x         = reader.ReadInt32();
            _y         = reader.ReadInt32();
            _w         = reader.ReadInt32();
            _h         = reader.ReadInt32();
            ViewCoords = new Rectangle(_x, _y, _w, _h);
            _x         = reader.ReadInt32();
            _y         = reader.ReadInt32();
            _w         = reader.ReadInt32();
            _h         = reader.ReadInt32();
            PortCoords = new Rectangle(_x, _y, _w, _h);
            BorderHor  = reader.ReadInt32();
            BorderVert = reader.ReadInt32();
            HSpeed     = reader.ReadInt32();
            VSpeed     = reader.ReadInt32();
            ViewObject = null;
            int _objind = reader.ReadInt32();

            if (_objind > -1)
            {
                ViewObject = proj.Objects[_objind];
            }
        }
예제 #3
0
 /// <summary>
 /// Project reader do work
 /// </summary>
 private void bgwProjectReader_DoWork(object sender, DoWorkEventArgs e)
 {
     // Create new Game Maker project, hook progress changed event, start reading project
     _project = new GMProject();
     _project.OnProgressChanged += new GMProject.ProgressChangedHandler(ReaderProgressChanged);
     _project.ReadProject(e.Argument.ToString());
 }
예제 #4
0
        public void Save(ProjectWriter writer, GMProject proj)
        {
            writer.Write(Version);
            writer.Write(LibID);
            writer.Write(ID);
            writer.Write((int)Kind);
            writer.Write(UseRelative);
            writer.Write(IsQuestion);
            writer.Write(UseApplyTo);
            writer.Write((int)ExeType);
            writer.Write(Name);
            writer.Write(Code);
            writer.Write(ArgumentCount);
            writer.Write(ArgumentTypes.Count);
            for (int i = 0; i < ArgumentTypes.Count; i++)
            {
                writer.Write((int)ArgumentTypes[i]);
            }
            if (WhoObj == null)
            {
                writer.Write(Who);                 // -1 = self, -2 = other...
            }
            else
            {
                writer.Write(proj.Objects.IndexOf(WhoObj));
            }

            writer.Write(Relative);
            writer.Write(Arguments.Count);
            for (int i = 0; i < Arguments.Count; i++)
            {
                writer.Write(Arguments[i]);
            }
            writer.Write(IsNot);
        }
예제 #5
0
 public void PostLoad(GMProject proj)
 {
     if (_BackgroundRoom > -1)
     {
         BackgroundRoom = proj.Rooms[_BackgroundRoom];
     }
 }
예제 #6
0
 public void PostLoad(GMProject proj)
 {
     if (Who > -1)
     {
         WhoObj = proj.Objects[Who];
     }
 }
예제 #7
0
        public static void Script(ProjectWriter writer, GMScript self, GMProject _)
        {
            writer.Write(self.Name);
            writer.Write(self.Version);

            writer.Write(self.Code);
        }
예제 #8
0
 public static void Trigger(ProjectWriter writer, GMTrigger self, GMProject _)
 {
     writer.Write(self.Version);
     writer.Write(self.Name);
     writer.Write(self.Condition);
     writer.Write((int)self.Event);
     writer.Write(self.ConstName);
 }
예제 #9
0
        public void Save(ProjectWriter writer, GMProject proj)
        {
            writer.Write(Name);
            writer.Write(LastChanged);
            writer.Write(Version);
            writer.Write(Caption);
            writer.Write(Width);
            writer.Write(Height);
            writer.Write(Snap);
            writer.Write(Isometric);
            writer.Write(Speed);
            writer.Write(Persistent);
            writer.Write(BackgroundColor);
            int val = DrawBackgroundColor ? 1 : 0;

            if (ClearBGWithWindowColor)
            {
                val |= 0b10;
            }
            writer.Write(val);
            writer.Write(CreationCode);
            writer.Write(Backgrounds.Count);
            for (int i = 0; i < Backgrounds.Count; i++)
            {
                Backgrounds[i].Save(writer, proj);
            }
            writer.Write(EnableViews);
            writer.Write(Views.Count);
            for (int i = 0; i < Views.Count; i++)
            {
                Views[i].Save(writer, proj);
            }
            writer.Write(Instances.Count);
            for (int i = 0; i < Instances.Count; i++)
            {
                Instances[i].Save(writer, proj);
            }
            writer.Write(Tiles.Count);
            for (int i = 0; i < Tiles.Count; i++)
            {
                Tiles[i].Save(writer, proj);
            }

            // weird Room Editor settings...
            writer.Write(REI);
            writer.Write(EditorWidth);
            writer.Write(EditorHeight);
            writer.Write(ShowGrid);
            writer.Write(ShowObjects);
            writer.Write(ShowTiles);
            writer.Write(ShowBGs);
            writer.Write(ShowFGs);
            writer.Write(ShowViews);
            writer.Write(DeleteUnderlyingObj);
            writer.Write(DeleteUnderlyingTil);
            writer.Write((int)Tab);
            writer.Write(Scrollbar);
        }
예제 #10
0
        public GMObject(ProjectReader reader, GMProject proj)
        {
            Name        = reader.ReadString();
            LastChanged = reader.ReadDate();
            Version     = reader.ReadInt32();
            if (Version != 430)
            {
                throw new InvalidDataException("Invalid Object version, got " + Version);
            }
            Sprite = null;
            int spr = reader.ReadInt32();

            if (spr > -1)
            {
                Sprite = proj.Sprites[spr];
            }

            Solid      = reader.ReadBoolean();
            Visible    = reader.ReadBoolean();
            Depth      = reader.ReadInt32();
            Persistent = reader.ReadBoolean();
            Parent     = null;
            _ParentInd = reader.ReadInt32();
            Mask       = null;
            int mask = reader.ReadInt32();

            if (mask > -1)
            {
                Mask = proj.Sprites[mask];
            }

            int ev_count = reader.ReadInt32();

            Events = new List <List <GMEvent> >(ev_count + 1);
            for (int i = 0; i <= ev_count; i++)
            {
                var  l    = new List <GMEvent>();
                bool done = false;
                while (!done)
                {
                    int first = reader.ReadInt32();
                    if (first != -1)
                    {
                        var ev = new GMEvent(reader);
                        ev.Key = first;
                        l.Add(ev);
                    }
                    else
                    {
                        done = true;
                    }
                }
                Events.Add(l);
            }

            reader.Dispose();
        }
예제 #11
0
        public int Key; // only used in GMObject.

        public void Save(ProjectWriter writer, GMProject proj)
        {
            writer.Write(Version);
            writer.Write(Actions.Count);
            for (int i = 0; i < Actions.Count; i++)
            {
                var action = Actions[i];
                action.Save(writer, proj);
            }
        }
예제 #12
0
        //internal GMResourceManager AlteredResources { get; }

        internal GMProjectParent(GMProject project)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            Reference       = null;
            HiddenResources = new List <Guid>();
            //AlteredResources = new GMResourceManager(project);
        }
예제 #13
0
        /// <summary>
        /// Constructs a new project form for writing
        /// </summary>
        /// <param name="project">The project to write</param>
        /// <param name="path">The path to write to</param>
        public GMProjectLoadForm(GMProject project, string path)
        {
            // Set text
            this.Text = "Project Write";

            // Set project to write
            _project = project;

            // Write project
            bgwProjectReader.RunWorkerAsync(path);
        }
예제 #14
0
        internal override void Deserialize(ModelBase model)
        {
            var parentProjectModel = (GMProjectParentModel)model;

            HiddenResources = parentProjectModel.hiddenResources;
            //AlteredResources.Deserialize(parentProjectModel.alteredResources);

            if (!string.IsNullOrEmpty(parentProjectModel.projectPath))
            {
                Reference = GMProject.Load(parentProjectModel.projectPath);
            }
        }
예제 #15
0
 public void Save(ProjectWriter writer, GMProject proj)
 {
     writer.Write(Name);
     writer.Write(LastChanged);
     writer.Write(Version);
     writer.Write(Moments.Count);
     for (int i = 0; i < Moments.Count; i++)
     {
         var moment = Moments[i];
         moment.Save(writer, proj);
     }
 }
예제 #16
0
        public static void Timeline(ProjectWriter writer, GMTimeline self, GMProject proj)
        {
            writer.Write(self.Name);
            writer.Write(self.Version);

            writer.Write(self.Moments.Count);
            foreach (var moment in self.Moments)
            {
                writer.Write(moment.Point);
                moment.Event.Save(writer, proj);
            }
        }
예제 #17
0
        private GMProjectWriter _writer = new GMProjectWriter();  // Project writer

        #endregion

        #region Constructor

        /// <summary>
        /// Constructs a new game maker export form
        /// </summary>
        /// <param name="projectPath">Path to a Game Maker project</param>
        public ExportGMProjectForm(GMProject project, string projectPath)
        {
            InitializeComponent();

            // Set image keys
            GMUtilities.ImageKeyGroup         = imgProjectTree.Images.Keys[0];
            GMUtilities.ImageKeyGroupSelected = imgProjectTree.Images.Keys[1];
            GMUtilities.ImageKeyRoom          = imgProjectTree.Images.Keys[2];
            GMUtilities.ImageKeyRoomSelected  = imgProjectTree.Images.Keys[2];

            // Set project target Game Maker path
            _projectPath = projectPath;

            // Set Game Maker project
            _project = project;

            // Populate the backgrounds listbox
            foreach (GMBackground background in _project.Backgrounds)
            {
                // If the background has image data, add it to the list
                if (background.Image.Data != null)
                {
                    lstBackgrounds.Items.Add(background);
                }
            }

            // If there is at least one item to select, do so
            if (lstBackgrounds.Items.Count > 0)
            {
                lstBackgrounds.SelectedIndex = 0;
            }

            // The object node index
            int roomIndex = GetResourceIndex(GMResourceType.Rooms);

            // If no object node was found, return
            if (roomIndex == -1)
            {
                return;
            }

            // Add room nodes to treeview
            //tvRooms.Nodes.Add(GMUtilities.GetTreeNodeFromGMNode(_project, _project.ProjectTree, null));
            tvRooms.Nodes.Add(GMUtilities.GetTreeNodeFromGMNode(_project, _project.ProjectTree.Nodes[roomIndex], null));
            tvRooms.SelectedNode = tvRooms.Nodes[0];
            tvRooms.Nodes[0].Expand();

            // Set name of room in text box
            txtName.Text = App.Room.Name;

            // Verify requistes
            Verify();
        }
예제 #18
0
 public static void Path(ProjectWriter writer, GMPath self, GMProject _)
 {
     writer.Write(self.Name);
     writer.Write(self.Version);
     writer.Write(self.Smooth);
     writer.Write(self.Closed);
     writer.Write(self.Precision);
     writer.Write(self.Points.Count);
     foreach (var point in self.Points)
     {
         writer.Write(point);
     }
 }
예제 #19
0
        public static void Sprite(ProjectWriter writer, GMSprite self, GMProject _)
        {
            writer.Write(self.Name);
            writer.Write(self.Version);
            writer.Write(self.Origin);
            writer.Write(self.Subimages.Count);
            foreach (var subimage in self.Subimages)
            {
                writer.Write(800);
                writer.Write(subimage.Size);
                if (subimage.Width * subimage.Height != 0)
                {
                    writer.Write(subimage, true);
                }
            }

            writer.Write(self.SeparateMasks);
            if (self.Subimages.Count <= 0)
            {
                return;
            }

            if (self.SeparateMasks)
            {
                foreach (var subimage in self.Subimages)
                {
                    writer.Write(800); // mask data version
                    writer.Write(subimage.Width);
                    writer.Write(subimage.Height);
                    writer.Write(self.BBox);
                    int[] mask = CollisionMaskGen.Generate(subimage, self);
                    foreach (int iii in mask)
                    {
                        writer.Write(iii);
                    }
                }
            }
            else
            {
                writer.Write(800); // mask data version
                writer.Write(self.Subimages[0].Width);
                writer.Write(self.Subimages[0].Height);
                writer.Write(self.BBox);
                int[] mask = CollisionMaskGen.Generate(self.Subimages[0], self);
                foreach (int iii in mask)
                {
                    writer.Write(iii);
                }
            }
        }
예제 #20
0
        public void Save(ProjectWriter writer, GMProject proj)
        {
            writer.Write(Name);
            writer.Write(LastChanged);
            writer.Write(Version);
            if (Sprite != null)
            {
                writer.Write(proj.Sprites.IndexOf(Sprite));
            }
            else
            {
                writer.Write(-1);
            }

            writer.Write(Solid);
            writer.Write(Visible);
            writer.Write(Depth);
            writer.Write(Persistent);
            if (Parent != null)
            {
                writer.Write(proj.Objects.IndexOf(Parent));
            }
            else
            {
                writer.Write(-1);
            }

            if (Mask != null)
            {
                writer.Write(proj.Sprites.IndexOf(Mask));
            }
            else
            {
                writer.Write(-1);
            }

            writer.Write(Events.Count - 1);
            for (int i = 0; i < Events.Count; i++)
            {
                var l = Events[i];
                for (int j = 0; j < l.Count; j++)
                {
                    var ev = l[j];
                    writer.Write(ev.Key);
                    ev.Save(writer, proj);
                }
                writer.Write(-1);
            }
        }
예제 #21
0
 public void Save(ProjectWriter writer, GMProject proj)
 {
     writer.Write(Position);
     if (Object != null)
     {
         writer.Write(proj.Objects.IndexOf(Object));
     }
     else
     {
         throw new System.Exception("Cannot write an instance with a non existing object!");
     }
     writer.Write(ID);
     writer.Write(CreationCode);
     writer.Write(IsLocked);
 }
예제 #22
0
        public static void Object(ProjectWriter writer, GMObject self, GMProject proj)
        {
            writer.Write(self.Name);
            writer.Write(self.Version);

            if (self.Sprite == null)
            {
                writer.Write(-1);
            }
            else
            {
                writer.Write(proj.Sprites.IndexOf(self.Sprite));
            }

            writer.Write(self.Solid);
            writer.Write(self.Visible);
            writer.Write(self.Depth);
            writer.Write(self.Persistent);

            if (self.Parent == null)
            {
                writer.Write(-100);
            }
            else
            {
                writer.Write(proj.Objects.IndexOf(self.Parent));
            }

            if (self.Mask == null)
            {
                writer.Write(-1);
            }
            else
            {
                writer.Write(proj.Sprites.IndexOf(self.Mask));
            }

            writer.Write(self.Events.Count - 1);
            foreach (var ev in self.Events)
            {
                foreach (var inner in ev)
                {
                    writer.Write(inner.Key);
                    inner.Save(writer, proj);
                }
                writer.Write(-1);
            }
        }
예제 #23
0
        public static void Background(ProjectWriter writer, GMBackground self, GMProject _)
        {
            writer.Write(self.Name);
            writer.Write(self.Version);

            writer.Write(800);
            writer.Write(self.Background.Size);
            if (self.Background.Width * self.Background.Height != 0)
            {
                writer.Write(self.Background, true);
            }
            else
            {
                writer.Write(false);
            }
        }
예제 #24
0
 public void Save(ProjectWriter writer, GMProject proj)
 {
     writer.Write(RoomPosition);
     if (Background != null)
     {
         writer.Write(proj.Backgrounds.IndexOf(Background));
     }
     else
     {
         writer.Write(-1);
     }
     writer.Write(BGCoords);
     writer.Write(Depth);
     writer.Write(ID);
     writer.Write(IsLocked);
 }
예제 #25
0
        public void Load(ProjectReader reader, GMProject proj)
        {
            int _x, _y, _objind;

            _x       = reader.ReadInt32();
            _y       = reader.ReadInt32();
            Position = new Point(_x, _y);
            Object   = null;
            _objind  = reader.ReadInt32();
            if (_objind > -1)
            {
                Object = proj.Objects[_objind];
            }
            ID           = reader.ReadInt32();
            CreationCode = reader.ReadString();
            IsLocked     = reader.ReadBoolean();
        }
예제 #26
0
 public void Save(ProjectWriter writer, GMProject proj)
 {
     writer.Write(Visible);
     writer.Write(ViewCoords);
     writer.Write(PortCoords);
     writer.Write(BorderHor);
     writer.Write(BorderVert);
     writer.Write(HSpeed);
     writer.Write(VSpeed);
     if (ViewObject != null)
     {
         writer.Write(proj.Objects.IndexOf(ViewObject));
     }
     else
     {
         writer.Write(-1);
     }
 }
예제 #27
0
 public static void IncludedFile(ProjectWriter writer, GMIncludedFile self, GMProject _)
 {
     writer.Write(self.Version);
     writer.Write(self.FileName);
     writer.Write(self.FilePath);
     writer.Write(self.Original);
     writer.Write(self.FileSize);
     writer.Write(self.StoreInProject);
     if (self.Original && self.StoreInProject)
     {
         writer.Write(self.Data.Length);
         writer.Write(self.Data);
     }
     writer.Write((int)self.ExportKind);
     writer.Write(self.ExportFolder);
     writer.Write(self.Overwrite);
     writer.Write(self.FreeMemory);
     writer.Write(self.RemoveAtGameEnd);
 }
예제 #28
0
 public void Save(ProjectWriter writer, GMProject proj)
 {
     writer.Write(Visible);
     writer.Write(IsForeground);
     if (Background != null)
     {
         writer.Write(proj.Backgrounds.IndexOf(Background));
     }
     else
     {
         writer.Write(-1);
     }
     writer.Write(Position);
     writer.Write(TileHorizontal);
     writer.Write(TileVertical);
     writer.Write(SpeedHorizontal);
     writer.Write(SpeedVertical);
     writer.Write(Stretch);
 }
예제 #29
0
        private static void LoadSaveProject()
        {
            var rootDirectory = GetInput("Drag your project folder here");
            var project       = GMProject.Load(rootDirectory);

            var script0 = project.Resources.Get <GMScript>("script0");

            script0.Contents += "\r\n// Modified by YYP";

            var object0 = project.Resources.Get <GMObject>("object0");

            foreach (var @event in object0.Events)
            {
                @event.Contents += "\r\n// Modified by YYP";
            }

            project.Save();

            Console.WriteLine("Done!");
        }
예제 #30
0
        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);
        }
예제 #31
0
 /// <summary>
 /// Writes a Game Maker project to disk.
 /// </summary>
 /// <param name="path">The path where the project should be written to.</param>
 /// <param name="project">The project that is to be written.</param>
 /// <param name="version">The target version for the write.</param>
 public static void WriteGMProject(string path, GMProject project, GMVersionType version)
 {
     GMProjectWriter writer = new GMProjectWriter();
     writer.WriteGMProject(path, project, version);
 }
예제 #32
0
        private Stream _writer = null; // The base underlining write stream.

        #endregion Fields

        #region Methods

        /// <summary>
        /// Writes a Game Maker project to disk.
        /// </summary>
        /// <param name="filePath">The file path to write the project.</param>
        /// <param name="project">The project object to write.</param>
        /// <param name="version">The target Game Maker version.</param>
        public void WriteGMProject(string filePath, GMProject project, GMVersionType version)
        {
            // Create a new stream encoder.
            using (_writer = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                // Write GM identifier.
                WriteInt(1234321);

                // Write version.
                WriteInt((int)version);

                // Write reserved bytes.
                if ((int)version < 600)
                    WriteEmpty(4);

                // If target version is GM7, start Game Maker 7 project file encryption.
                if (version == GMVersionType.GameMaker70)
                {
                    // Create random numbers.
                    Random rand = new Random();

                    byte[] bytes = null;

                    // Get game id bytes. The first byte is not encrypted.
                    byte[] id = BitConverter.GetBytes(project.Settings.GameIdentifier);

                    // Bill and Fred, psssttt they like each other ;).
                    int bill = rand.Next() % 3000 + 123;
                    int fred = rand.Next() % 3000 + 231;

                    // Write trash and treasure.
                    WriteInt(bill);
                    WriteInt(fred);

                    // Write junk integers.
                    while (bill-- > 0)
                    {
                        bytes = BitConverter.GetBytes((int)(rand.Next() % 3000));
                        _writer.Write(bytes, 0, bytes.Length);
                    }

                    // Set the seed and swap table.
                    int seed = rand.Next() % 25600 + 3328;
                    bytes = BitConverter.GetBytes((int)seed);
                    _writer.Write(bytes, 0, bytes.Length);

                    // Write junk integers.
                    while (fred-- > 0)
                    {
                        bytes = BitConverter.GetBytes((int)(rand.Next() % 3000));
                        _writer.Write(bytes, 0, bytes.Length);
                    }

                    // Write first byte of game id (Not encrypted).
                    WriteByte(id[0]);

                    // Set the seed for encryption.
                    SetSeed(seed);

                    // Write rest of game id bytes, encrypted.
                    WriteByte(id[1]);
                    WriteByte(id[2]);
                    WriteByte(id[3]);
                }
                else  // Write game id.
                    WriteInt(project.Settings.GameIdentifier);

                // Write empty bytes.
                WriteEmpty(16);

                // Write project objects.
                WriteSettings(project.Settings, version);

                // If the version is greater than 7.0.
                if (version > GMVersionType.GameMaker70)
                {
                    // Read triggers and constants.
                    WriteTriggers(project.Triggers, version);
                    WriteConstants(project.Settings.Constants, version);
                }

                WriteSounds(project.Sounds, version);
                WriteSprites(project.Sprites, version);
                WriteBackgrounds(project.Backgrounds, version);
                WritePaths(project.Paths, version);
                WriteScripts(project.Scripts, version);
                WriteDataFiles(project.DataFiles, version);
                WriteFonts(project.Fonts, version);
                WriteTimelines(project.Timelines, version);
                WriteObjects(project.Objects, version);
                WriteRooms(project.Rooms, version);

                // Write last ids for instances and tiles.
                WriteInt(project.LastInstanceId);
                WriteInt(project.LastTileId);

                // Write version.
                if (version < GMVersionType.GameMaker60)
                    WriteInt(430);
                else if (version == GMVersionType.GameMaker60)
                    WriteInt(600);
                else if (version == GMVersionType.GameMaker70)
                    WriteInt(620);
                else if (version == GMVersionType.GameMaker80)
                    WriteInt(800);

                // Check version.
                if (version < GMVersionType.GameMaker70)
                    WriteGameInformation(project.GameInformation, version);
                else
                {
                    // Write includes.
                    WriteIncludes(project.Settings.Includes, version);

                    // Write packages.
                    WritePackages(project.Packages.ToArray(), version);

                    // Write version.
                    if (version == GMVersionType.GameMaker70)
                        WriteInt(600);
                    else if (version == GMVersionType.GameMaker80)
                        WriteInt(800);

                    // Write game information.
                    WriteGameInformation(project.GameInformation, version);
                }

                // Write version.
                WriteInt(500);

                // Write the amount of libraries.
                WriteInt(project.Libraries.Count);

                // Iterate throught libraries.
                for (int j = 0; j < project.Libraries.Count; j++)
                {
                    // Write the library code.
                    WriteString(project.Libraries[j].Code);
                }

                // Write project tree.
                WriteTree(project.ProjectTree, version);
            }
        }
예제 #33
0
        private MemoryStream _zipStream = null; // A zip stream used for decompressing data.

        #endregion Fields

        #region Methods

        /// <summary>
        /// Reads a Game Maker project file.
        /// </summary>
        public GMProject ReadProject(string filePath)
        {
            // Create a new stream decoder.
            using (_reader = new BinaryReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)))
            {
                // Create a new project.
                GMProject project = new GMProject();

                // Read the magic number.
                int id = ReadInt();

                // 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 = ReadInt();

                // Check version.
                switch (version)
                {
                    case 500: project.GameMakerVersion = GMVersionType.GameMaker50; break;
                    case 510: project.GameMakerVersion = GMVersionType.GameMaker51; break;
                    case 520: project.GameMakerVersion = GMVersionType.GameMaker52; break;
                    case 530: project.GameMakerVersion = GMVersionType.GameMaker53; break;
                    case 600: project.GameMakerVersion = GMVersionType.GameMaker60; break;
                    case 701: project.GameMakerVersion = GMVersionType.GameMaker70; break;
                    case 800: project.GameMakerVersion = GMVersionType.GameMaker80; break;
                }

                // Skip over reserved bytes.
                if (version < 600)
                    ReadBytes(4);

                // Game Maker 7 project file encryption.
                if (version == 701)
                {
                    // Bill and Fred, psssttt they like each other ;).
                    int bill = ReadInt();
                    int fred = ReadInt();

                    // Skip bytes to treasure.
                    ReadBytes(bill * 4);

                    // Get the seed for swap table.
                    int seed = ReadInt();

                    // Skip bytes to get out of the junk yard.
                    ReadBytes(fred * 4);

                    // Read first byte of Game id. (Not encrypted).
                    byte b = ReadByte();

                    // Set the seed.
                    SetSeed(seed);

                    // Read game id.
                    id = ReadInt(b);
                }
                else  // Read game id normally.
                    id = ReadInt();

                // Skip unknown bytes.
                ReadBytes(16);

                // Read main project objects.
                project.Settings = ReadSettings();
                project.Settings.GameIdentifier = id;

                // If the version is greater than Game Maker 7.0.
                if (version > 701)
                {
                    // Read triggers and constants.
                    project.Triggers = ReadTriggers();
                    project.Settings.Constants = ReadConstants();
                }

                project.Sounds = ReadSounds();
                project.Sprites = ReadSprites();
                project.Backgrounds = ReadBackgrounds();
                project.Paths = ReadPaths();
                project.Scripts = ReadScripts();

                // Get version.
                int version2 = ReadInt();

                // 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)
                    project.DataFiles = ReadDataFiles();
                else
                    project.Fonts = ReadFonts(version);

                project.Timelines = ReadTimelines();
                project.Objects = ReadObjects();
                project.Rooms = ReadRooms(project.Objects);

                // Read last ids for instances and tiles.
                project.LastInstanceId = ReadInt();
                project.LastTileId = ReadInt();

                // If the version is above 6.1, read include files and packages.
                if (version >= 700)
                {
                    // Get include files.
                    project.Settings.Includes = ReadIncludes();

                    // Get packages.
                    project.Packages.AddRange(ReadPackages());
                }

                // Read game information.
                project.GameInformation = ReadGameInformation();

                // Get version.
                version = ReadInt();

                // Check version.
                if (version != 500)
                    throw new Exception("Unsupported Post-Game Information object version.");

                // Get number of libraries.
                int libNum = ReadInt();

                // Read libraries.
                for (int j = 0; j < libNum; j++)
                {
                    // Create a new library.
                    GMLibrary library = new GMLibrary();

                    // Read the library code.
                    library.Code = ReadString();

                    // Add the library.
                    project.Libraries.Add(library);
                }

                // Read project tree.
                project.ProjectTree = ReadTree(filePath.Substring(filePath.LastIndexOf(@"\") + 1));

                // Return the project.
                return project;
            }
        }