/// <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); } }
public static void Room(ProjectWriter writer, GMRoom self, GMProject proj) { writer.Write(self.Name); writer.Write(self.Version); writer.Write(self.Caption); writer.Write(self.Width); writer.Write(self.Height); writer.Write(self.Speed); writer.Write(self.Persistent); writer.Write(self.BackgroundColor); int val = self.DrawBackgroundColor ? 1 : 0; if (!self.ClearBGWithWindowColor) { val |= 0b10; } writer.Write(val); writer.Write(self.CreationCode); // -- Backgrounds writer.Write(self.Backgrounds.Count); foreach (var bg in self.Backgrounds) { writer.Write(bg.Visible); writer.Write(bg.IsForeground); if (bg.Background == null) { writer.Write(-1); } else { writer.Write(proj.Backgrounds.IndexOf(bg.Background)); } writer.Write(bg.Position); writer.Write(bg.TileHorizontal); writer.Write(bg.TileVertical); writer.Write(bg.SpeedHorizontal); writer.Write(bg.SpeedVertical); writer.Write(bg.Stretch); } // -- Views writer.Write(self.EnableViews); writer.Write(self.Views.Count); foreach (var view in self.Views) { writer.Write(view.Visible); writer.Write(view.ViewCoords); writer.Write(view.PortCoords); writer.Write(view.BorderHor); writer.Write(view.BorderVert); writer.Write(view.HSpeed); writer.Write(view.VSpeed); if (view.ViewObject == null) { writer.Write(-1); } else { writer.Write(proj.Objects.IndexOf(view.ViewObject)); } } // -- Room Instances writer.Write(self.Instances.Count); foreach (var inst in self.Instances) { if (inst.ID == -1) { Console.WriteLine("Corrupted room instance found!"); continue; } writer.Write(inst.Position); writer.Write(proj.Objects.IndexOf(inst.Object)); writer.Write(inst.ID); writer.Write(inst.CreationCode); } // -- Room Tiles writer.Write(self.Tiles.Count); foreach (var tile in self.Tiles) { writer.Write(tile.RoomPosition); writer.Write(proj.Backgrounds.IndexOf(tile.Background)); writer.Write(tile.BGCoords); writer.Write(tile.Depth); writer.Write(tile.ID); } // -- in GMK 820 Physics data would go here, but PrikolLib does not support 820 GMK files and never will. }
/// <summary> /// Reads a Game Maker Studio project file /// </summary> private void ReadProjectGMS(string file) { // Set version GameMakerVersion = GMVersionType.GameMakerStudio; // Path with project file removed string folder = file.Remove(file.LastIndexOf("\\")); // Set up resource directory strings Dictionary <GMResourceType, string> directories = new Dictionary <GMResourceType, string>(); directories.Add(GMResourceType.Assets, file); directories.Add(GMResourceType.DataFiles, file); directories.Add(GMResourceType.Configs, file); directories.Add(GMResourceType.Constants, file); directories.Add(GMResourceType.Hash, file); directories.Add(GMResourceType.Backgrounds, folder + "\\" + "background"); directories.Add(GMResourceType.Objects, folder + "\\" + "objects"); directories.Add(GMResourceType.Rooms, folder + "\\" + "rooms"); directories.Add(GMResourceType.Sprites, folder + "\\" + "sprites"); directories.Add(GMResourceType.Sounds, folder + "\\" + "sound"); directories.Add(GMResourceType.TimeLines, folder + "\\" + "timelines"); directories.Add(GMResourceType.Shaders, folder + "\\" + "shaders"); directories.Add(GMResourceType.Scripts, folder + "\\" + "scripts"); directories.Add(GMResourceType.Paths, folder + "\\" + "paths"); // Resource load index int index = 0; // Iterate through directories foreach (KeyValuePair <GMResourceType, string> item in directories) { // Increment directory index index++; // If the directory does not exist, continue if (Path.GetExtension(item.Value) != ".gmx" && !Directory.Exists(item.Value)) { continue; } // Progress changed ProgressChanged("Reading " + item.Key.ToString() + "...", index, directories.Count); // Load data based on resource type switch (item.Key) { case GMResourceType.Hash: Settings.Hash = ReadHashGMX(item.Value); break; case GMResourceType.Assets: ProjectTree = GMNode.ReadTreeGMX(item.Value); Assets = (List <string>)ProjectTree.Tag; break; case GMResourceType.DataFiles: DataFiles = GMDataFile.ReadDataFilesGMX(item.Value, out LastDataFileId); break; case GMResourceType.Sprites: Sprites = GMSprite.ReadSpritesGMX(item.Value, ref Assets); break; //case GMResourceType.Configs: Settings.Configs = GMSettings.GetConfigsGMX(item.Value); break; //case GMResourceType.Constants: Settings.Constants = GMSettings.ReadConstantsGMX(item.Value); break; case GMResourceType.Backgrounds: Backgrounds = GMBackground.ReadBackgroundsGMX(item.Value, ref Assets); break; case GMResourceType.Objects: Objects = GMObject.ReadObjectsGMX(item.Value, ref Assets); break; case GMResourceType.Rooms: Rooms = GMRoom.ReadRoomsGMX(item.Value, ref Assets, out LastTileId); break; //case GMResourceType.TimeLines: Timelines = GMTimeline.ReadTimelinesGMX(item.Value, Assets); break; //case GMResourceType.Sounds: Sounds = GMSound.ReadSoundsGMX(item.Value, ref Assets); break; //case GMResourceType.Shaders: Shaders = GMShader.ReadShadersGMX(item.Value, ref Assets); break; //case GMResourceType.Scripts: Scripts = GMScript.ReadScriptsGMX(item.Value, ref Assets); break; //case GMResourceType.Paths: Paths = GMPath.ReadPathsGMX(item.Value, ref Assets); break; //case GMResourceType.TimeLines: Timelines = GMTimeline.ReadTimelinesGMX(item.Value, Assets); break; } } // Retrieve tutorial data foreach (GMNode node in ProjectTree.Nodes) { // If the node is the tutorial state node and it has the nodes we're looking for if (node.ResourceType == GMResourceType.TutorialState && node.Nodes != null && node.Nodes.Length == 3) { Settings.IsTutorial = node.Nodes[0].Nodes == null ? Settings.IsTutorial : GMResource.GMXBool(node.Nodes[0].Nodes[0].Name, true); Settings.TutorialName = node.Nodes[1].Nodes == null ? Settings.TutorialName : GMResource.GMXString(node.Nodes[1].Nodes[0].FilePath, ""); Settings.TutorialPage = node.Nodes[2].Nodes == null ? Settings.TutorialPage : GMResource.GMXInt(node.Nodes[2].Nodes[0].Name, 0); } } // Progress event ProgressChanged("Finished Reading Project.", index, directories.Count); }
/// <summary> /// Reads rooms from GM file /// </summary> private GMList<GMRoom> ReadRooms(GMList<GMObject> objects) { // Get version. int version = ReadInt(); // Check version. if (version != 420 && version != 800) throw new Exception("Unsupported Pre-Room object version."); // Create a new list of rooms. GMList<GMRoom> rooms = new GMList<GMRoom>(); // Amount of room indexes. int num = ReadInt(); // Iterate through rooms. for (int i = 0; i < num; i++) { // If version is 8.0, start inflate. if (version == 800) Decompress(); // If the room at index does not exists, continue. if (ReadBool() == false) { rooms.LastId++; EndDecompress(); continue; } // Create a room object. GMRoom room = new GMRoom(); // Set room id. room.Id = i; // Read room data. room.Name = ReadString(); // If version is 8.0, get last changed. if (version == 800) room.LastChanged = ReadDouble(); // Get version. int version2 = ReadInt(); // Check version. if (version2 != 500 && version2 != 520 && version2 != 541) throw new Exception("Unsupported Room object version."); // Read room data. room.Caption = ReadString(); room.Width = ReadInt(); room.Height = ReadInt(); room.SnapY = ReadInt(); room.SnapX = ReadInt(); // Versions greater than 5.1 support isometric grid. if (version2 > 500) room.IsometricGrid = ReadBool(); room.Speed = ReadInt(); room.Persistent = ReadBool(); room.BackgroundColor = ReadInt(); room.DrawBackgroundColor = ReadBool(); room.CreationCode = ReadString(); // Create new parallax array. room.Parallaxes = new GMParallax[ReadInt()]; // Iterate through parallaxs. for (int j = 0; j < room.Parallaxes.Length; j++) { // Create a new parallax object. room.Parallaxes[j] = new GMParallax(); // Read room parallax data. room.Parallaxes[j].Visible = ReadBool(); room.Parallaxes[j].Foreground = ReadBool(); room.Parallaxes[j].BackgroundId = ReadInt(); room.Parallaxes[j].X = ReadInt(); room.Parallaxes[j].Y = ReadInt(); room.Parallaxes[j].TileHorizontally = ReadBool(); room.Parallaxes[j].TileVertically = ReadBool(); room.Parallaxes[j].HorizontalSpeed = ReadInt(); room.Parallaxes[j].VerticalSpeed = ReadInt(); // Versions greater than 5.1 support parallax stretching. if (version2 > 500) room.Parallaxes[j].Stretch = ReadBool(); } // Read room data. room.EnableViews = ReadBool(); // Create new view array. room.Views = new GMView[ReadInt()]; // Iterate through views for (int k = 0; k < room.Views.Length; k++) { // Create new view object. room.Views[k] = new GMView(); // Read room view data. room.Views[k].Visible = ReadBool(); room.Views[k].ViewX = ReadInt(); room.Views[k].ViewY = ReadInt(); room.Views[k].ViewWidth = ReadInt(); room.Views[k].ViewHeight = ReadInt(); room.Views[k].PortX = ReadInt(); room.Views[k].PortY = ReadInt(); // Versions greater than 5.3 support port dimensions. if (version2 > 520) { room.Views[k].PortWidth = ReadInt(); room.Views[k].PortHeight = ReadInt(); } // Read room view data. room.Views[k].HorizontalBorder = ReadInt(); room.Views[k].VerticalBorder = ReadInt(); room.Views[k].HorizontalSpeed = ReadInt(); room.Views[k].VerticalSpeed = ReadInt(); room.Views[k].ObjectToFollow = ReadInt(); } // Create a new array of instances. room.Instances = new GMInstance[ReadInt()]; // Iterate through room instances. for (int l = 0; l < room.Instances.Length; l++) { // Create new instance. room.Instances[l] = new GMInstance(); // Read room instance data. room.Instances[l].X = ReadInt(); room.Instances[l].Y = ReadInt(); room.Instances[l].ObjectId = ReadInt(); room.Instances[l].Id = ReadInt(); // Versions greater than 5.1 support creation code and instance locking. if (version2 > 500) { // Read room instance data. room.Instances[l].CreationCode = ReadString(); room.Instances[l].Locked = ReadBool(); } // Get the object the instance references. GMObject obj = objects.Find(delegate(GMObject o) { return o.Id == room.Instances[l].ObjectId; }); // If the object was found, set instance name and depth. if (obj != null) { // Read room instance data. room.Instances[l].Name = obj.Name; room.Instances[l].Depth = obj.Depth; } // Skipped reserved bytes. if (version2 < 520) ReadBytes(8); } // Create a new array of tiles. room.Tiles = new GMTile[ReadInt()]; // Iterate through room tiles. for (int m = 0; m < room.Tiles.Length; m++) { // Create new tile object. room.Tiles[m] = new GMTile(); // Read room tile data. room.Tiles[m].X = ReadInt(); room.Tiles[m].Y = ReadInt(); room.Tiles[m].BackgroundId = ReadInt(); room.Tiles[m].BackgroundX = ReadInt(); room.Tiles[m].BackgroundY = ReadInt(); room.Tiles[m].Width = ReadInt(); room.Tiles[m].Height = ReadInt(); room.Tiles[m].Depth = ReadInt(); room.Tiles[m].Id = ReadInt(); // Versions greater than 5.1 support tile locking. if (version2 > 500) room.Tiles[m].Locked = ReadBool(); } // Read room data. room.RememberWindowSize = ReadBool(); room.EditorWidth = ReadInt(); room.EditorHeight = ReadInt(); room.ShowGrid = ReadBool(); room.ShowObjects = ReadBool(); room.ShowTiles = ReadBool(); room.ShowBackgrounds = ReadBool(); room.ShowForegrounds = ReadBool(); room.ShowViews = ReadBool(); room.DeleteUnderlyingObjects = ReadBool(); room.DeleteUnderlyingTiles = ReadBool(); // Versions greater than 5.3 don't support tile settings. if (version2 > 520) { // Read room tile data. room.CurrentTab = (TabSetting)(ReadInt()); room.ScrollBarX = ReadInt(); room.ScrollBarY = ReadInt(); } else { // Read room tile data. room.TileWidth = ReadInt(); room.TileHeight = ReadInt(); room.TileHorizontalSeperation = ReadInt(); room.TileVerticalSeperation = ReadInt(); room.TileHorizontalOffset = ReadInt(); room.TileVerticalOffset = ReadInt(); room.CurrentTab = (TabSetting)(ReadInt()); room.ScrollBarX = ReadInt(); room.ScrollBarY = ReadInt(); } // End object inflate. EndDecompress(); // Set room. rooms.Add(room); } // Return rooms return rooms; }
public override void ConvertData(ProjectFile pf, int index) { // TODO use asset refs eventually var dataCode = pf.DataHandle.GetChunk <GMChunkCODE>()?.List; var dataSeqn = pf.DataHandle.GetChunk <GMChunkSEQN>()?.List; string getCode(int ind) { if (ind < 0) { return(null); } if (dataCode == null) { return(ind.ToString()); } return(dataCode[ind].Name?.Content); } GMRoom asset = (GMRoom)pf.Rooms[index].DataAsset; AssetRoom projectAsset = new AssetRoom() { Name = asset.Name?.Content, Caption = asset.Caption?.Content, Width = asset.Width, Height = asset.Height, Speed = asset.Speed, Persistent = asset.Persistent, BackgroundColor = asset.BackgroundColor, DrawBackgroundColor = asset.DrawBackgroundColor, CreationCode = getCode(asset.CreationCodeID), EnableViews = (asset.Flags & GMRoom.RoomFlags.EnableViews) == GMRoom.RoomFlags.EnableViews, ShowColor = (asset.Flags & GMRoom.RoomFlags.ShowColor) == GMRoom.RoomFlags.ShowColor, ClearDisplayBuffer = (asset.Flags & GMRoom.RoomFlags.ClearDisplayBuffer) == GMRoom.RoomFlags.ClearDisplayBuffer, Backgrounds = new(asset.Backgrounds.Count), Views = new(asset.Views.Count), GameObjects = new(asset.GameObjects.Count), Tiles = new(asset.Tiles.Count), Physics = new() { Enabled = asset.Physics, Top = asset.Top, Left = asset.Left, Right = asset.Right, Bottom = asset.Bottom, GravityX = asset.GravityX, GravityY = asset.GravityY, PixelsToMeters = asset.PixelsToMeters } }; foreach (var bg in asset.Backgrounds) { projectAsset.Backgrounds.Add(new AssetRoom.Background() { Enabled = bg.Enabled, Foreground = bg.Foreground, Asset = bg.BackgroundID >= 0 ? pf.Backgrounds[bg.BackgroundID].Name : null, X = bg.X, Y = bg.Y, TileX = bg.TileX, TileY = bg.TileY, SpeedX = bg.SpeedX, SpeedY = bg.SpeedY, Stretch = bg.Stretch }); } foreach (var view in asset.Views) { projectAsset.Views.Add(new AssetRoom.View() { Enabled = view.Enabled, ViewX = view.ViewX, ViewY = view.ViewY, ViewWidth = view.ViewWidth, ViewHeight = view.ViewHeight, PortX = view.PortX, PortY = view.PortY, PortWidth = view.PortWidth, PortHeight = view.PortHeight, BorderX = view.BorderX, BorderY = view.BorderY, SpeedX = view.SpeedX, SpeedY = view.SpeedY, FollowObject = view.FollowObjectID >= 0 ? pf.Objects[view.FollowObjectID].Name : null }); } foreach (var obj in asset.GameObjects) { var newObj = new AssetRoom.GameObject() { X = obj.X, Y = obj.Y, Asset = obj.ObjectID >= 0 ? pf.Objects[obj.ObjectID].Name : null, InstanceID = obj.InstanceID, CreationCode = getCode(obj.CreationCodeID), ScaleX = obj.ScaleX, ScaleY = obj.ScaleY, Color = obj.Color, Angle = obj.Angle, ImageSpeed = obj.ImageSpeed, ImageIndex = obj.ImageIndex }; if (pf.DataHandle.VersionInfo.RoomObjectPreCreate) { newObj.PreCreateCode = getCode(obj.PreCreateCodeID); } projectAsset.GameObjects.Add(newObj); } foreach (var tile in asset.Tiles) { var newTile = new AssetRoom.Tile() { X = tile.X, Y = tile.Y, SourceX = tile.SourceX, SourceY = tile.SourceY, Width = tile.Width, Height = tile.Height, Depth = tile.Depth, ID = tile.Depth, ScaleX = tile.ScaleX, ScaleY = tile.ScaleY, Color = tile.Color }; if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2)) { newTile.Asset = tile.AssetID >= 0 ? pf.Sprites[tile.AssetID].Name : null; } else { newTile.Asset = tile.AssetID >= 0 ? pf.Backgrounds[tile.AssetID].Name : null; } projectAsset.Tiles.Add(newTile); } if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2)) { projectAsset.Layers = new List <AssetRoom.Layer>(asset.Layers.Count); foreach (var layer in asset.Layers) { var newLayer = new AssetRoom.Layer() { Name = layer.Name?.Content, ID = layer.ID, Depth = layer.Depth, OffsetX = layer.OffsetX, OffsetY = layer.OffsetY, HSpeed = layer.HSpeed, VSpeed = layer.VSpeed, Visible = layer.Visible }; switch (layer.Kind) { case GMRoom.Layer.LayerKind.Background: newLayer.Background = new AssetRoom.Layer.LayerBackground() { Visible = layer.Background.Visible, Foreground = layer.Background.Foreground, Sprite = layer.Background.SpriteID >= 0 ? pf.Sprites[layer.Background.SpriteID].Name : null, TileHorz = layer.Background.TileHorz, TileVert = layer.Background.TileVert, Stretch = layer.Background.Stretch, Color = layer.Background.Color, FirstFrame = layer.Background.FirstFrame, AnimationSpeed = layer.Background.AnimationSpeed, AnimationSpeedType = layer.Background.AnimationSpeedType }; break; case GMRoom.Layer.LayerKind.Instances: newLayer.Instances = layer.Instances; break; case GMRoom.Layer.LayerKind.Assets: newLayer.Assets = new AssetRoom.Layer.LayerAssets() { LegacyTiles = new(layer.Assets.LegacyTiles.Count), Sprites = new(layer.Assets.Sprites.Count) }; foreach (var tile in layer.Assets.LegacyTiles) { var newTile = new AssetRoom.Tile() { X = tile.X, Y = tile.Y, SourceX = tile.SourceX, SourceY = tile.SourceY, Width = tile.Width, Height = tile.Height, Depth = tile.Depth, ID = tile.Depth, ScaleX = tile.ScaleX, ScaleY = tile.ScaleY, Color = tile.Color, Asset = tile.AssetID >= 0 ? pf.Sprites[tile.AssetID].Name : null }; newLayer.Assets.LegacyTiles.Add(newTile); } foreach (var spr in layer.Assets.Sprites) { newLayer.Assets.Sprites.Add(new() { Name = spr.Name?.Content, Asset = spr.AssetID >= 0 ? pf.Sprites[spr.AssetID].Name : null, X = spr.X, Y = spr.Y, ScaleX = spr.ScaleX, ScaleY = spr.ScaleY, Color = spr.Color, AnimationSpeed = spr.AnimationSpeed, AnimationSpeedType = spr.AnimationSpeedType, FrameIndex = spr.FrameIndex, Rotation = spr.Rotation }); } if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2, 3)) { newLayer.Assets.Sequences = new(layer.Assets.Sequences.Count); foreach (var seq in layer.Assets.Sequences) { newLayer.Assets.Sequences.Add(new() { Name = seq.Name?.Content, Asset = seq.AssetID >= 0 ? dataSeqn[seq.AssetID].Name?.Content : null, X = seq.X, Y = seq.Y, ScaleX = seq.ScaleX, ScaleY = seq.ScaleY, Color = seq.Color, AnimationSpeed = seq.AnimationSpeed, AnimationSpeedType = seq.AnimationSpeedType, FrameIndex = seq.FrameIndex, Rotation = seq.Rotation }); } if (!pf.DataHandle.VersionInfo.IsNumberAtLeast(2, 3, 2)) { newLayer.Assets.NineSlices = new(); foreach (var spr in layer.Assets.NineSlices) { newLayer.Assets.NineSlices.Add(new() { Name = spr.Name?.Content, Asset = spr.AssetID >= 0 ? pf.Sprites[spr.AssetID].Name : null, X = spr.X, Y = spr.Y, ScaleX = spr.ScaleX, ScaleY = spr.ScaleY, Color = spr.Color, AnimationSpeed = spr.AnimationSpeed, AnimationSpeedType = spr.AnimationSpeedType, FrameIndex = spr.FrameIndex, Rotation = spr.Rotation }); } } } break; case GMRoom.Layer.LayerKind.Tiles: newLayer.Tiles = new() { Background = layer.Tiles.BackgroundID >= 0 ? pf.Backgrounds[layer.Tiles.BackgroundID].Name : null, TilesX = layer.Tiles.TilesX, TilesY = layer.Tiles.TilesY, TileData = layer.Tiles.TileData }; break; case GMRoom.Layer.LayerKind.Effect: newLayer.Effect = new() { EffectType = layer.Effect.EffectType?.Content, Properties = new(layer.Effect.Properties.Count) }; foreach (var prop in layer.Effect.Properties) { newLayer.Effect.Properties.Add(new() { Kind = prop.Kind, Name = prop.Name?.Content, Value = prop.Value?.Content }); } break; } projectAsset.Layers.Add(newLayer); } if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2, 3)) { projectAsset.Sequences = new(asset.SequenceIDs.Count); foreach (int seq in asset.SequenceIDs) { projectAsset.Sequences.Add(seq >= 0 ? dataSeqn[seq].Name?.Content : null); } } } pf.Rooms[index].Asset = projectAsset; }
/// <summary> /// Sets the given Game Maker room properties to GMare project room properties /// </summary> /// <param name="room">The room to set properties of</param> /// <param name="id">Id of the room</param> /// <returns>If the room property set was sucessful</returns> private bool SetRoomProperties(GMRoom room, int id) { // Set room properties room.Id = id == -1 ? room.Id : id; room.Name = txtName.Text; room.BackgroundColor = GMUtilities.ColorToGMColor(App.Room.BackColor); room.Width = App.Room.Width; room.Height = App.Room.Height; room.TileWidth = App.Room.Backgrounds[0].TileWidth; room.TileHeight = App.Room.Backgrounds[0].TileHeight; room.Caption = App.Room.Caption; room.CreationCode = App.Room.CreationCode; room.Speed = App.Room.Speed; room.Persistent = App.Room.Persistent; // If exporting tiles, set tiles if (chkWriteTiles.Checked) { // Get the game maker background selected GMBackground background = (GMBackground)lstBackgrounds.SelectedItem; // If the selected background dimensions do not match the GMare project's background if (chkWriteTiles.Checked && (App.Room.Backgrounds[0].Image.Width != background.Width || App.Room.Backgrounds[0].Image.Height != background.Height)) { // Give warning, and cancel export DialogResult result = MessageBox.Show("The selected background's size does not match the background used for this room. Please select a background that is the same size as the used background.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1); return(false); } // Copy the room's background, set the game maker background id GMareBackground gmareBackground = App.Room.Backgrounds[0].Clone(); gmareBackground.GameMakerId = background.Id; gmareBackground.Name = background.Name; // Get tile array GMTile[] tiles = App.Room.GMareTilesToGMTiles(_project.LastTileId, gmareBackground, chkOptimizeTiles.Checked); // Set unique names foreach (GMTile tile in tiles) { tile.Name = GetUniqueName(true); } // Set the room's tiles room.Tiles = tiles; } // If the room's instances should be written, write instances if (chkWriteInstances.Checked) { room.Instances = SetInstances(); // If no instances, return unsuccessful if (room.Instances == null) { return(false); } } // Successful return(true); }
/// <summary> /// Ok button clicked /// </summary> private void butExport_Click(object sender, EventArgs e) { try { // Get the currently selected node GMNode node = tvRooms.SelectedNode.Tag as GMNode; // Create a new room GMRoom room; // If the node is a child node if (node.NodeType == GMNodeType.Child) { // Give warning about an overwrite DialogResult result = MessageBox.Show("Are you sure you want to overwrite room: " + node.Name + "?", "GMare", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2); // If not ok, return if (result != DialogResult.Yes) { return; } } // Create a backup of the original project file string filePath = MakeBackup(); // If the backup failed, return, else write the file if (filePath == "") { return; } // If the node is being overwritten, overwrite, else add the node if (node.NodeType == GMNodeType.Child) { // Find the room to overwrite room = _project.Rooms.Find(r => r.Id == node.Id); // Set room properties if (!SetRoomProperties(room, -1)) { // Notify the user that the export failed MessageBox.Show("An error occurred while exporting the room, export aborted.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); return; } } else { // Check for any resource doubles foreach (string asset in _project.Assets) { // If the asset already exists, return if (asset == txtName.Text) { MessageBox.Show("The game resource name already exists. Please use a unique name for this room. Export aborted.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); return; } } // Create a new room room = new GMRoom(); // Set room properties if (!SetRoomProperties(room, _project.Rooms.LastId++)) { // Give warning about an overwrite MessageBox.Show("An error occurred while exporting the room, export aborted.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); return; } // Add the room to the project _project.Rooms.Add(room); // Increase the amount of children for parent node (tvRooms.SelectedNode.Tag as GMNode).Children++; // Create a new tree node TreeNode treeNode = new TreeNode(room.Name); // Create a new Game Maker node GMNode newNode = new GMNode(); newNode.Name = room.Name; newNode.NodeType = GMNodeType.Child; newNode.ResourceType = GMResourceType.Rooms; newNode.ResourceSubType = GMResourceSubType.Room; newNode.Id = room.Id; newNode.FilePath = "rooms\\" + room.Name; // Set the tree node tag to Game Maker node treeNode.Tag = newNode; treeNode.ImageIndex = 2; // Add the new node to the tree tvRooms.SelectedNode.Nodes.Add(treeNode); } // Set room nodes _project.ProjectTree.Nodes[GetResourceIndex(GMResourceType.Rooms)] = GMUtilities.GetGMNodeFromTreeNode(tvRooms.Nodes[0]); // If refactor tiles, refactor if (chkRefactorTiles.Checked == true) { _project.RefactorTileIds(); } // If refactor instances, refactor if (chkRefactorInstances.Checked == true) { _project.RefactorInstanceIds(); } // If a game maker studio project and there is room data, wirte project if (_project.GameMakerVersion == GMVersionType.GameMakerStudio) { // If the room was never created, notify user if (room == null) { MessageBox.Show("There was an error creating the room to export. Export failed.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); } else { // NOTE: Normally I would not do things this way. It should be the data that drives // the project file creation. However, we're only changing the room portion of the // project and it's just safer, as of now, to write only the project file and the // room vs. writing the entire project out. Luckily GM:S is modular and allows that // to happen GameMaker.Resource.GMNode.WriteTreeGMX(_projectPath, ref _project); GameMaker.Resource.GMRoom.WriteRoomGMX(room, Path.GetDirectoryName(_projectPath) + "\\" + "rooms"); } } // Legacy Game Maker project write else { _writer.WriteGMProject(_projectPath, _project, _project.GameMakerVersion); } // Display success message if (MessageBox.Show("Export complete. A backup of the original project was made. Do you want to open the directory it was copied to?", "GMare", MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { Process.Start(filePath); } // Close the form Close(); } catch (Exception) { // Notify the user that the export failed MessageBox.Show("An error occurred while exporting the room, export aborted.", "GMare", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); } }