/// <summary>
        /// Sets the instances
        /// </summary>
        private GMInstance[] SetInstances()
        {
            // Get regular and block instances
            List <GMareInstance> gmareInstances = new List <GMareInstance>();

            gmareInstances.AddRange(App.Room.Instances.ToArray());

            // Create a game maker instance array
            GMInstance[] instances = new GMInstance[gmareInstances.Count];

            // Set room instances
            for (int i = 0; i < gmareInstances.Count; i++)
            {
                bool     studio = _project.GameMakerVersion == GMVersionType.GameMakerStudio;
                GMObject obj    = studio ? _project.Objects.Find(o => o.Name == gmareInstances[i].ObjectName) :
                                  _project.Objects.Find(o => o.Id == gmareInstances[i].ObjectId);

                // If the object does not exist in the target project, abort
                if (obj == null)
                {
                    string objMessage = studio ? gmareInstances[i].ObjectName : gmareInstances[i].Name + "(Id: " + gmareInstances[i].ObjectId + ")";
                    MessageBox.Show("Could not find the object: " + objMessage + " within the target export project.",
                                    "GMare", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    return(null);
                }

                // Get the sprite for the instance offsets
                GMSprite sprite = studio ? _project.Sprites.Find(s => s.Name == obj.SpriteName) :
                                  _project.Sprites.Find(s => obj.SpriteId == obj.SpriteId);

                // If the sprite does not exist in the target project, abort
                if (sprite == null)
                {
                    string spriteMessage = studio ? obj.SpriteName : obj.SpriteId.ToString();
                    MessageBox.Show("Could not find the sprite: " + spriteMessage + " within the target export project.",
                                    "GMare", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    return(null);
                }

                // Increment project last instance id
                _project.LastInstanceId++;

                // Create a new instance
                instances[i]              = new GMInstance();
                instances[i].Name         = GetUniqueName(false);
                instances[i].CreationCode = (string)gmareInstances[i].CreationCode.Clone();
                instances[i].Id           = _project.LastInstanceId;
                instances[i].ObjectName   = gmareInstances[i].ObjectName;
                instances[i].ObjectId     = gmareInstances[i].ObjectId;
                instances[i].X            = gmareInstances[i].X + sprite.OriginX;
                instances[i].Y            = gmareInstances[i].Y + sprite.OriginY;
                instances[i].ScaleX       = gmareInstances[i].ScaleX == 0 ? 1 : gmareInstances[i].ScaleX;
                instances[i].ScaleY       = gmareInstances[i].ScaleY == 0 ? 1 : gmareInstances[i].ScaleY;
                instances[i].Rotation     = gmareInstances[i].Rotation;
            }

            // Return an array of instances
            return(instances);
        }
Beispiel #2
0
        public GMObject(BinaryReader binaryReader, GMWAD w)
        {
            Name        = new GMString(binaryReader);
            SpriteIndex = binaryReader.ReadInt32();
            Sprite      = null;
            if (SpriteIndex > -1)
            {
                Sprite = w.Sprites.Items[SpriteIndex];
            }
            Visible     = ReadBool(binaryReader);
            Solid       = ReadBool(binaryReader);
            Depth       = binaryReader.ReadInt32();
            Persistent  = ReadBool(binaryReader);
            ParentIndex = binaryReader.ReadInt32();
            Parent      = null;
            MaskIndex   = binaryReader.ReadInt32();
            Mask        = null;
            if (MaskIndex > -1)
            {
                Mask = w.Sprites.Items[MaskIndex];
            }

            // It's a list with list with GMGMLEvents...................
            // yoyo nahooya tak hard blyat?

            int count = binaryReader.ReadInt32();

            Debug.Assert(count == 12); // on PSP it should be 12.
            Events = new List <List <GMGMLEvent> >(count);
            long mprev_addr = binaryReader.BaseStream.Position;

            // Thanks to colinator27 for telling me how that works.
            for (int i = 0; i < count; i++)
            {
                uint e_addr    = binaryReader.ReadUInt32();
                long prev_addr = binaryReader.BaseStream.Position;
                binaryReader.BaseStream.Position = e_addr;
                int count2          = binaryReader.ReadInt32();
                List <GMGMLEvent> l = new List <GMGMLEvent>(count2);
                for (int j = 0; j < count2; j++)
                {
                    uint e_addr2    = binaryReader.ReadUInt32();
                    long prev_addr2 = binaryReader.BaseStream.Position;
                    binaryReader.BaseStream.Position = e_addr2;
                    int key = binaryReader.ReadInt32(); // subtype data????
                    var ev  = new GMGMLEvent(binaryReader);
                    ev.Key = key;
                    l.Add(ev);
                    binaryReader.BaseStream.Position = prev_addr2;
                }
                binaryReader.BaseStream.Position = prev_addr;
                Events.Add(l);
            }

            binaryReader.BaseStream.Position = mprev_addr;
        }
Beispiel #3
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);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets objects
        /// </summary>
        /// <param name="file">The path to the Game Maker project file</param>
        public static bool GetObjects(string file)
        {
            // Create a new Game Maker project form
            using (ProjectIOForm form = new ProjectIOForm(file, true))
            {
                // Show the form
                form.ShowDialog();

                // If the project is empty, return
                if (form.GMProject == null || form.GMProject.ProjectTree == null || form.GMProject.ProjectTree.Nodes == null)
                {
                    return(false);
                }

                // The object node index
                int objectIndex = -1;

                // Get the object node
                for (int i = 0; i < form.GMProject.ProjectTree.Nodes.Length; i++)
                {
                    if (form.GMProject.ProjectTree.Nodes[i].ResourceType == GMResourceType.Objects)
                    {
                        objectIndex = i;
                    }
                }

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

                // Check instances for differences
                CheckInstances(form.GMProject);

                // Clear previous objects if any
                App.Room.Objects.Clear();

                // Iterate through project objects
                foreach (GMObject resource in form.GMProject.Objects)
                {
                    // GMare object variables
                    int    originX = 0;
                    int    originY = 0;
                    Bitmap image   = null;

                    // Get the sprite object
                    GMSprite sprite = form.GMProject.Sprites.Find(i => i.Id == resource.SpriteId);

                    // If a sprite was found
                    if (sprite != null)
                    {
                        // Get sprite data
                        originX = sprite.OriginX;
                        originY = sprite.OriginY;

                        // If there are no sub-images, skip image data
                        if (sprite.SubImages.Length <= 0)
                        {
                            // Add new gmare object
                            App.Room.Objects.Add(new GMareObject(resource, image, resource.SpriteId, resource.Depth, originX, originY));
                            continue;
                        }

                        image = GameMaker.Common.GMUtilities.GetBitmap(sprite.SubImages[0]);

                        // Set transparency if needed
                        if (sprite.Transparent && sprite.SubImages[0].Compressed)
                        {
                            image.MakeTransparent(image.GetPixel(0, image.Height - 1));
                        }
                    }

                    // Add new gmare object
                    App.Room.Objects.Add(new GMareObject(resource, image, resource.SpriteId, resource.Depth, originX, originY));
                }

                // Get the object nodes
                App.Room.Nodes = form.GMProject.ProjectTree.Nodes[objectIndex].Nodes;

                // Set textures for loaded objects
                SetTextures();
                return(true);
            }
        }
Beispiel #5
0
        /// <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);
            }
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <summary>
        /// Reads sprites from Game Maker project file.
        /// </summary>
        private GMList<GMSprite> ReadSprites()
        {
            // Get version.
            int version = ReadInt();

            // Check version.
            if (version != 400 && version != 800)
                throw new Exception("Unsupported Pre-Sprite object version.");

            // Create a new list of sprites.
            GMList<GMSprite> sprites = new GMList<GMSprite>();

            // Amount of sprite ids.
            int num = ReadInt();

            // Iterate through sprites.
            for (int i = 0; i < num; i++)
            {
                // If version is 8.0, start inflate.
                if (version == 800)
                    Decompress();

                // If the sprite at index does not exists, continue.
                if (ReadBool() == false)
                {
                    sprites.LastId++;
                    EndDecompress();
                    continue;
                }

                // Create a new sprite object.
                GMSprite sprite = new GMSprite();

                // Set sprite id.
                sprite.Id = i;

                // Read sprite data.
                sprite.Name = ReadString();

                // If version is 8.0, get last changed.
                if (version == 800)
                    sprite.LastChanged = ReadDouble();

                // Get version.
                version = ReadInt();

                // Check version.
                if (version != 400 && version != 542 && version != 800)
                    throw new Exception("Unsupported Sprite object version.");

                // If less than version 8.0.
                if (version < 800)
                {
                    // Read sprite data
                    sprite.Width = ReadInt();
                    sprite.Height = ReadInt();
                    sprite.BoundingBoxLeft = ReadInt();
                    sprite.BoundingBoxRight = ReadInt();
                    sprite.BoundingBoxBottom = ReadInt();
                    sprite.BoundingBoxTop = ReadInt();
                    sprite.Transparent = ReadBool();

                    // Check version.
                    if (version > 400)
                    {
                        // Read sprite data
                        sprite.SmoothEdges = ReadBool();
                        sprite.Preload = ReadBool();
                    }

                    // Read sprite data.
                    sprite.BoundingBoxMode = (BoundingBoxType)ReadInt();
                    sprite.Precise = ReadBool();

                    // Check version.
                    if (version == 400)
                    {
                        // Read sprtie data.
                        sprite.UseVideoMemory = ReadBool();
                        sprite.LoadOnlyOnUse = ReadBool();
                    }

                    // Read sprite data.
                    sprite.OriginX = ReadInt();
                    sprite.OriginY = ReadInt();

                    // Sprite number of sub images
                    sprite.SubImages = new GMImage[ReadInt()];

                    // Iterate through sub-images
                    for (int j = 0; j < sprite.SubImages.Length; j++)
                    {
                        // If the sub-image at index does not exists, continue.
                        if (ReadInt() == -1)
                            continue;

                        // Create a new image object.
                        GMImage image = new GMImage();

                        // Get size of image data.
                        int size = ReadInt();

                        // Get image data.
                        image.Data = ReadBytes(size);

                        // Insert compressed image data.
                        sprite.SubImages[j] = image;
                    }
                }
                else
                {
                    // Read sprite data.
                    sprite.OriginX = ReadInt();
                    sprite.OriginY = ReadInt();

                    // Sprite number of sub images.
                    sprite.SubImages = new GMImage[ReadInt()];

                    // Iterate through sub-images.
                    for (int j = 0; j < sprite.SubImages.Length; j++)
                    {
                        // Get version.
                        version = ReadInt();

                        // Check version.
                        if (version != 800)
                            throw new Exception("Unsupported Sprite object version.");

                        // Get width and height of image.
                        int width = ReadInt();
                        int height = ReadInt();

                        // If the sprite size is not zero.
                        if (width != 0 && height != 0)
                        {
                            // Create a new image object.
                            GMImage image = new GMImage();
                            image.Compressed = false;

                            // Set image data.
                            image.Width = width;
                            image.Height = height;

                            // Get size of image data.
                            int size = ReadInt();

                            // Get image data.
                            image.Data = ReadBytes(size);

                            // Insert compressed image data.
                            sprite.SubImages[j] = image;
                        }
                    }

                    // Read sprite data.
                    sprite.ShapeMode = (ShapeType)ReadInt();
                    sprite.AlphaTolerance = ReadInt();
                    sprite.UseSeperateCollisionMasks = ReadBool();
                    sprite.BoundingBoxMode = (BoundingBoxType)ReadInt();
                    sprite.BoundingBoxLeft = ReadInt();
                    sprite.BoundingBoxRight = ReadInt();
                    sprite.BoundingBoxBottom = ReadInt();
                    sprite.BoundingBoxTop = ReadInt();
                }

                // End object inflate.
                EndDecompress();

                // Add sprite.
                sprites.Add(sprite);
            }

            // Return sprites.
            return sprites;
        }
Beispiel #8
0
        public static int[] Generate(Image frame, GMSprite sprite)
        {
            int[] maskArray = new int[frame.Width * frame.Height];
            int   left      = sprite.BBox.X;
            int   right     = sprite.BBox.Y;
            int   bottom    = sprite.BBox.Width;
            int   top       = sprite.BBox.Height;

            int mLeft   = Math.Max(0, Math.Min(frame.Height - 1, top));
            int mBottom = Math.Max(0, Math.Min(frame.Height - 1, bottom));
            int mTop    = Math.Max(0, Math.Min(frame.Width - 1, left));
            int mRight  = Math.Max(0, Math.Min(frame.Width - 1, right));

            if (mLeft != mBottom && mTop != mRight)
            {
                switch (sprite.MaskMode)
                {
                case GMSprite.SpriteMaskMode.RECTANGLE:
                {
                    for (int y = mLeft; y <= mBottom; y++)
                    {
                        for (int x = mTop; x <= mRight; x++)
                        {
                            //maskArray[y * frame.Width + x] |= 1 << 7 - (x & 7);
                            maskArray[y * frame.Width + x]++;
                        }
                    }

                    break;
                }

                case GMSprite.SpriteMaskMode.DISK:
                {
                    float fXYHalf = (left + right) / 2;
                    float fWHHalf = (bottom + top) / 2;
                    float fXYX    = fXYHalf - left + 0.5f;
                    float fWHH    = fWHHalf - top + 0.5f;
                    for (int y = mLeft; y <= mBottom; y++)
                    {
                        for (int x = mTop; x <= mRight; x++)
                        {
                            if (fXYX > 0f && fWHH > 0f && Math.Pow((x - fXYHalf) / fXYX, 2.0) + Math.Pow((y - fWHHalf) / fWHH, 2.0) <= 1.0)
                            {
                                //maskArray[y * frame.Width + x] |= 1 << 7 - (x & 7);
                                maskArray[y * frame.Width + x]++;
                            }
                        }
                    }

                    break;
                }

                case GMSprite.SpriteMaskMode.DIAMOND:
                {
                    float fXYHalf = (left + right) / 2;
                    float fWHHalf = (bottom + top) / 2;
                    float fXYX    = fXYHalf - left + 0.5f;
                    float fWHH    = fWHHalf - top + 0.5f;
                    for (int y = mLeft; y <= mBottom; y++)
                    {
                        for (int x = mTop; x <= mRight; x++)
                        {
                            if (fXYX > 0f && fWHH > 0f && Math.Abs((x - fXYHalf) / fXYX) + Math.Abs((y - fWHHalf) / fWHH) <= 1f)
                            {
                                //maskArray[y * frame.Width + x] |= 1 << 7 - (x & 7);
                                maskArray[y * frame.Width + x]++;
                            }
                        }
                    }

                    break;
                }

                case GMSprite.SpriteMaskMode.PRECISE:
                {
                    for (int y = mLeft; y <= mBottom; y++)
                    {
                        for (int x = mTop; x <= mRight; x++)
                        {
                            if (((Bitmap)frame).GetPixel(x, y).A > sprite.AlphaTolerance)
                            {
                                //maskArray[y * frame.Width + x] |= 1 << 7 - (x & 7);
                                maskArray[y * frame.Width + x]++;
                            }
                        }
                    }

                    break;
                }
                }
            }

            //DumpIntArray(maskArray);

            return(maskArray);
        }
Beispiel #9
0
        public static AssetSprite.CollisionMaskInfo GetInfoForSprite(ProjectFile pf, GMSprite spr, out List <Bitmap> bitmaps, bool suggestPrecise = false)
        {
            bitmaps = new List <Bitmap>(spr.TextureItems.Count);

            var info = new AssetSprite.CollisionMaskInfo
            {
                Mode = (MaskMode)spr.BBoxMode
            };

            if (spr.SepMasks == GMSprite.SepMaskType.AxisAlignedRect)
            {
                info.Type = MaskType.Rectangle;
            }
            else if (spr.SepMasks == GMSprite.SepMaskType.RotatedRect)
            {
                info.Type = MaskType.RectangleWithRotation;
            }

            // Some basic conditions to bail
            if (spr.CollisionMasks.Count != 1 && spr.CollisionMasks.Count != spr.TextureItems.Count)
            {
                return(info);
            }
            if (spr.CollisionMasks.Count == 0)
            {
                return(info);
            }

            // Get bitmaps from frames
            bitmaps = GetBitmaps(pf, spr.Width, spr.Height, spr.TextureItems);
            List <BitmapData> bitmapData = new List <BitmapData>(bitmaps.Count);

            foreach (var item in bitmaps)
            {
                bitmapData.Add(item.BasicLockBits());
            }

            int boundLeft   = Math.Clamp(spr.MarginLeft, 0, spr.Width),
                boundRight  = Math.Clamp(spr.MarginRight, 0, spr.Width - 1),
                boundTop    = Math.Clamp(spr.MarginTop, 0, spr.Height),
                boundBottom = Math.Clamp(spr.MarginBottom, 0, spr.Height - 1);

            switch (spr.SepMasks)
            {
            case GMSprite.SepMaskType.AxisAlignedRect:
            case GMSprite.SepMaskType.RotatedRect:
                switch (info.Mode)
                {
                case MaskMode.Automatic:
                    // Scan for the lowest alpha value in the bounding box
                    // When comparing each pixel, compare to the one in that spot with the highest alpha in every frame

                    bool foundNonzero = false;
                    byte lowest       = 0;
                    byte highest      = 0;

                    int stride = ((spr.Width + 7) / 8) * 8;

                    FastBitArray mask         = new FastBitArray(spr.CollisionMasks[0].Memory.Span);
                    int          strideFactor = boundTop * stride;

                    for (int y = boundTop; y <= boundBottom; y++)
                    {
                        for (int x = boundLeft; x <= boundRight; x++)
                        {
                            if (mask.GetReverse(x + strideFactor))
                            {
                                byte highestAlpha = GetHighestAlphaAt(bitmapData, x, y);
                                if (highestAlpha > highest)
                                {
                                    highest = highestAlpha;
                                }
                                if (highestAlpha != 0 && (!foundNonzero || highestAlpha < lowest))
                                {
                                    lowest       = highestAlpha;
                                    foundNonzero = true;
                                }
                            }
                        }

                        strideFactor += stride;
                    }

                    if (foundNonzero)
                    {
                        if (lowest == highest)
                        {
                            lowest = 0;         // Could be anything
                        }
                        else
                        {
                            --lowest;
                        }
                    }
                    info.AlphaTolerance = lowest;
                    break;

                case MaskMode.Manual:
                    info.Left   = spr.MarginLeft;
                    info.Right  = spr.MarginRight;
                    info.Top    = spr.MarginTop;
                    info.Bottom = spr.MarginBottom;
                    break;
                }
                break;

            case GMSprite.SepMaskType.Precise:
            {
                int stride = ((spr.Width + 7) / 8) * 8;

                bool foundNonzero = false;
                byte lowest       = 0;
                byte highest      = 0;

                if (spr.CollisionMasks.Count > 1 && spr.CollisionMasks.Count == spr.TextureItems.Count)
                {
                    info.Type = MaskType.PrecisePerFrame;

                    unsafe
                    {
                        for (int i = 0; i < spr.CollisionMasks.Count; i++)
                        {
                            BitmapData   item         = bitmapData[i];
                            FastBitArray mask         = new FastBitArray(spr.CollisionMasks[i].Memory.Span);
                            int          strideFactor = boundTop * stride;
                            for (int y = boundTop; y <= boundBottom; y++)
                            {
                                for (int x = boundLeft; x <= boundRight; x++)
                                {
                                    if (mask.GetReverse(x + strideFactor))
                                    {
                                        byte val = *((byte *)item.Scan0 + (x * 4) + (y * item.Stride) + 3);
                                        if (val > highest)
                                        {
                                            highest = val;
                                        }
                                        if (val != 0 && (!foundNonzero || val < lowest))
                                        {
                                            lowest       = val;
                                            foundNonzero = true;
                                        }
                                    }
                                }

                                strideFactor += stride;
                            }
                        }
                    }
                }
                else
                {
                    info.Type = MaskType.Precise;

                    // Scan for highest alpha, as well as diamond/ellipses
                    FastBitArray mask = new FastBitArray(spr.CollisionMasks[0].Memory.Span);

                    bool  isDiamond = true, isEllipse = true;
                    float centerX = ((spr.MarginLeft + spr.MarginRight) / 2);
                    float centerY = ((spr.MarginTop + spr.MarginBottom) / 2);
                    float radiusX = centerX - spr.MarginLeft + 0.5f;
                    float radiusY = centerY - spr.MarginTop + 0.5f;

                    int strideFactor = boundTop * stride;

                    if (!suggestPrecise && radiusX > 0f && radiusY > 0f)
                    {
                        for (int y = boundTop; y <= boundBottom; y++)
                        {
                            for (int x = boundLeft; x <= boundRight; x++)
                            {
                                float normalX   = (x - centerX) / radiusX;
                                float normalY   = (y - centerY) / radiusY;
                                bool  inDiamond = Math.Abs(normalX) + Math.Abs(normalY) <= 1f;
                                bool  inEllipse = Math.Pow(normalX, 2.0d) + Math.Pow(normalY, 2.0d) <= 1.0d;

                                if (mask.GetReverse(x + strideFactor))
                                {
                                    isDiamond &= inDiamond;
                                    isEllipse &= inEllipse;

                                    byte highestAlpha = GetHighestAlphaAt(bitmapData, x, y);
                                    if (highestAlpha > highest)
                                    {
                                        highest = highestAlpha;
                                    }
                                    if (highestAlpha != 0 && (!foundNonzero || highestAlpha < lowest))
                                    {
                                        lowest       = highestAlpha;
                                        foundNonzero = true;
                                    }
                                }
                                // Can't eliminate based on this, they can be split into pieces with multiple frames
                                //else
                                //{
                                //    isDiamond &= !inDiamond;
                                //    isEllipse &= !inEllipse;
                                //}
                            }

                            strideFactor += stride;
                        }
                    }
                    else
                    {
                        // Version without diamond/ellipse checks
                        isDiamond = false;
                        isEllipse = false;

                        for (int y = boundTop; y <= boundBottom; y++)
                        {
                            for (int x = boundLeft; x <= boundRight; x++)
                            {
                                if (mask.GetReverse(x + strideFactor))
                                {
                                    byte highestAlpha = GetHighestAlphaAt(bitmapData, x, y);
                                    if (highestAlpha > highest)
                                    {
                                        highest = highestAlpha;
                                    }
                                    if (highestAlpha != 0 && (!foundNonzero || highestAlpha < lowest))
                                    {
                                        lowest       = highestAlpha;
                                        foundNonzero = true;
                                    }
                                }
                            }

                            strideFactor += stride;
                        }
                    }

                    if (isDiamond)
                    {
                        info.Type = MaskType.Diamond;
                    }
                    else if (isEllipse)
                    {
                        info.Type = MaskType.Ellipse;
                    }
                }

                if (info.Mode == MaskMode.Manual ||
                    (info.Mode == MaskMode.Automatic && info.Type != MaskType.Precise && info.Type != MaskType.PrecisePerFrame))
                {
                    info.Left   = spr.MarginLeft;
                    info.Right  = spr.MarginRight;
                    info.Top    = spr.MarginTop;
                    info.Bottom = spr.MarginBottom;
                }

                if (info.Mode == MaskMode.Automatic || info.Type == MaskType.Precise ||
                    (info.Mode == MaskMode.Manual && info.Type == MaskType.PrecisePerFrame))
                {
                    if (foundNonzero)
                    {
                        if (lowest == highest)
                        {
                            lowest = 0;         // Could be anything
                        }
                        else
                        {
                            --lowest;
                        }
                    }
                    info.AlphaTolerance = lowest;
                }
            }
            break;
            }

            for (int i = 0; i < bitmaps.Count; i++)
            {
                bitmaps[i].UnlockBits(bitmapData[i]);
            }

            return(info);
        }
Beispiel #10
0
        public override void ConvertData(ProjectFile pf, int index)
        {
            GMSprite asset = (GMSprite)pf.Sprites[index].DataAsset;

            AssetSprite projectAsset = new AssetSprite()
            {
                Name         = asset.Name?.Content,
                Transparent  = asset.Transparent,
                Smooth       = asset.Smooth,
                Preload      = asset.Preload,
                Width        = asset.Width,
                Height       = asset.Height,
                OriginX      = asset.OriginX,
                OriginY      = asset.OriginY,
                TextureItems = asset.TextureItems.ToList()
            };

            projectAsset.TextureItems.RemoveAll(i => i == null);

            // Determine texture group
            if (projectAsset.TextureItems.Count == 0)
            {
                projectAsset.TextureGroup = null;
            }
            else
            {
                var group = pf.Textures.TextureGroups[
                    pf.Textures.PageToGroup[projectAsset.TextureItems[0].TexturePageID]];

                // If this group only has this sprite, and also has a page for
                // each item, then this is a separate group
                if (new HashSet <GMTextureItem>(group.Items).SetEquals(projectAsset.TextureItems) &&
                    group.Pages.Count == projectAsset.TextureItems.Count)
                {
                    projectAsset.SeparateTextureGroup = true;
                }

                projectAsset.TextureGroup = group.Name;
            }

            // Determine collision mask info
            List <Bitmap> bitmaps;

            projectAsset.CollisionMask = CollisionMasks.GetInfoForSprite(pf, asset, out bitmaps);
            List <BufferRegion> regenerated = CollisionMasks.GetMasksForSprite(pf, projectAsset, out _, bitmaps);

            if (!CollisionMasks.CompareMasks(asset.CollisionMasks, regenerated))
            {
                bool manual = true;
                if (projectAsset.CollisionMask.Type == AssetSprite.CollisionMaskInfo.MaskType.Diamond ||
                    projectAsset.CollisionMask.Type == AssetSprite.CollisionMaskInfo.MaskType.Ellipse)
                {
                    // This may be a false positive diamond/ellipse, try suggesting Precise
                    projectAsset.CollisionMask = CollisionMasks.GetInfoForSprite(pf, asset, out bitmaps, true);
                    regenerated = CollisionMasks.GetMasksForSprite(pf, projectAsset, out _, bitmaps);
                    manual      = !CollisionMasks.CompareMasks(asset.CollisionMasks, regenerated);
                }

                if (manual)
                {
                    // Need to generate manually
                    projectAsset.CollisionMask.Mode           = (AssetSprite.CollisionMaskInfo.MaskMode)(-1 - (int)projectAsset.CollisionMask.Mode);
                    projectAsset.CollisionMask.AlphaTolerance = null;
                    projectAsset.CollisionMask.Left           = asset.MarginLeft;
                    projectAsset.CollisionMask.Top            = asset.MarginTop;
                    projectAsset.CollisionMask.Right          = asset.MarginRight;
                    projectAsset.CollisionMask.Bottom         = asset.MarginBottom;
                    projectAsset.CollisionMask.RawMasks       = asset.CollisionMasks;
                }
            }

            // Fix incorrect sizes resulting from mods:
            //  - If a texture entry's source width/height are greater than bound width/height, scale the bound width/height
            //  - Check for largest bound width/height, max them with sprite width/height, store in sprite width/height and all bound width/heights
            bool resized = false;
            int  largestWidth = projectAsset.Width, largestHeight = projectAsset.Height;

            foreach (var item in projectAsset.TextureItems)
            {
                if (item == null)
                {
                    continue;
                }

                if (item.SourceWidth > item.BoundWidth)
                {
                    item.BoundWidth = item.SourceWidth;
                }
                if (item.SourceHeight > item.BoundHeight)
                {
                    item.BoundHeight = item.SourceHeight;
                }

                largestWidth  = Math.Max(largestWidth, item.BoundWidth);
                largestHeight = Math.Max(largestHeight, item.BoundHeight);
            }

            if (largestWidth > projectAsset.Width)
            {
                resized            = true;
                projectAsset.Width = largestWidth;
            }
            if (largestHeight > projectAsset.Height)
            {
                resized             = true;
                projectAsset.Height = largestHeight;
            }

            if (resized)
            {
                foreach (var item in projectAsset.TextureItems)
                {
                    if (item == null)
                    {
                        continue;
                    }

                    item.BoundWidth  = (ushort)projectAsset.Width;
                    item.BoundHeight = (ushort)projectAsset.Height;
                }

                if ((int)projectAsset.CollisionMask.Mode < 0)
                {
                    // Can't use the raw data; it's a different size
                    projectAsset.CollisionMask.Mode     = (AssetSprite.CollisionMaskInfo.MaskMode)(-(1 + (int)projectAsset.CollisionMask.Mode));
                    projectAsset.CollisionMask.RawMasks = null;
                }
            }

            // Now just handle special data
            if (asset.SpecialOrGMS2)
            {
                projectAsset.SpecialInfo = new AssetSprite.SpriteSpecialInfo()
                {
                    SpriteType = asset.S_SpriteType
                };

                if (asset.S_SpriteType != GMSprite.SpriteType.Normal)
                {
                    projectAsset.SpecialInfo.Buffer         = "buffer.bin";
                    projectAsset.SpecialInfo.InternalBuffer = asset.S_Buffer;
                }

                if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2))
                {
                    projectAsset.SpecialInfo.GMS2PlaybackSpeed     = asset.GMS2_PlaybackSpeed;
                    projectAsset.SpecialInfo.GMS2PlaybackSpeedType = asset.GMS2_PlaybackSpeedType;

                    if (asset.GMS2_3_Sequence != null)
                    {
                        var seq = asset.GMS2_3_Sequence.Sequence;

                        List <AssetSprite.SpriteSpecialInfo.SequenceInfo.Frame> frames = new();
                        foreach (var keyframe in
                                 (seq.Tracks[0].Keyframes as GMSequence.Track.ValueKeyframes).List)
                        {
                            frames.Add(new()
                            {
                                Position = keyframe.Key,
                                Length   = keyframe.Length,
                                Index    = keyframe.Channels.Values.First().Value
                            });
                        }

                        List <AssetSprite.SpriteSpecialInfo.SequenceInfo.BroadcastMessage> broadcastMessages = new();
                        foreach (var message in seq.BroadcastMessages)
                        {
                            broadcastMessages.Add(new()
                            {
                                Position = message.Key,
                                Message  = message.Channels.Values.First().List.First().Content
                            });
                        }

                        projectAsset.SpecialInfo.Sequence = new AssetSprite.SpriteSpecialInfo.SequenceInfo()
                        {
                            Name              = seq.Name?.Content,
                            Frames            = frames,
                            BroadcastMessages = broadcastMessages
                        };
                    }

                    if (asset.GMS2_3_2_NineSlice != null)
                    {
                        projectAsset.SpecialInfo.NineSlice = new AssetSprite.SpriteSpecialInfo.NineSliceInfo()
                        {
                            Left      = asset.GMS2_3_2_NineSlice.Left,
                            Top       = asset.GMS2_3_2_NineSlice.Top,
                            Right     = asset.GMS2_3_2_NineSlice.Right,
                            Bottom    = asset.GMS2_3_2_NineSlice.Bottom,
                            Enabled   = asset.GMS2_3_2_NineSlice.Enabled,
                            TileModes = asset.GMS2_3_2_NineSlice.TileModes.ToList()
                        };
                    }
                }
            }

            pf.Sprites[index].Asset = projectAsset;
        }
Beispiel #11
0
        public override void ConvertProject(ProjectFile pf)
        {
            var dataAssets = pf.DataHandle.GetChunk <GMChunkSPRT>().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 <GMSprite> newList = new List <GMSprite>();

            for (int i = 0; i < pf.Sprites.Count; i++)
            {
                AssetSprite projectAsset = pf.Sprites[i].Asset;
                if (projectAsset == null)
                {
                    // This asset was never converted
                    newList.Add((GMSprite)pf.Sprites[i].DataAsset);
                    continue;
                }

                // Add texture items to group
                if (!projectAsset.SeparateTextureGroup &&
                    projectAsset.TextureGroup != null &&
                    groupNames.TryGetValue(projectAsset.TextureGroup, out var group))
                {
                    foreach (var item in projectAsset.TextureItems)
                    {
                        if (item != null)
                        {
                            group.AddNewEntry(pf.Textures, item);
                        }
                    }
                }
                else
                {
                    if (projectAsset.SeparateTextureGroup)
                    {
                        // Export each frame to a separate texture page
                        foreach (var item in projectAsset.TextureItems)
                        {
                            if (item == null)
                            {
                                continue;
                            }

                            var g = new Textures.Group()
                            {
                                Dirty     = true,
                                Border    = 0,
                                AllowCrop = false,
                                Name      = $"__DS_AUTO_GEN_{projectAsset.Name}__{pf.Textures.TextureGroups.Count}",
                                FillTGIN  = false // Apparently
                            };
                            g.AddNewEntry(pf.Textures, item);
                            pf.Textures.TextureGroups.Add(g);
                        }
                    }
                    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}",
                            FillTGIN  = false // Apparently
                        };
                        foreach (var item in projectAsset.TextureItems)
                        {
                            if (item != null)
                            {
                                g.AddNewEntry(pf.Textures, item);
                            }
                        }
                        pf.Textures.TextureGroups.Add(g);
                    }
                }

                CollisionMasks.Rect outbbox;

                GMSprite dataAsset = new GMSprite()
                {
                    Name           = pf.DataHandle.DefineString(projectAsset.Name),
                    Transparent    = projectAsset.Transparent,
                    Smooth         = projectAsset.Smooth,
                    Preload        = projectAsset.Preload,
                    Width          = projectAsset.Width,
                    Height         = projectAsset.Height,
                    OriginX        = projectAsset.OriginX,
                    OriginY        = projectAsset.OriginY,
                    TextureItems   = new GMRemotePointerList <GMTextureItem>(),
                    CollisionMasks = CollisionMasks.GetMasksForSprite(pf, projectAsset, out outbbox)
                };

                // Get collision mask info
                var colInfo = projectAsset.CollisionMask;
                if (colInfo.Left == null || colInfo.Top == null || colInfo.Right == null || colInfo.Bottom == null)
                {
                    dataAsset.MarginLeft   = outbbox.Left;
                    dataAsset.MarginTop    = outbbox.Top;
                    dataAsset.MarginRight  = outbbox.Right;
                    dataAsset.MarginBottom = outbbox.Bottom;
                }
                else
                {
                    dataAsset.MarginLeft   = (int)colInfo.Left;
                    dataAsset.MarginTop    = (int)colInfo.Top;
                    dataAsset.MarginRight  = (int)colInfo.Right;
                    dataAsset.MarginBottom = (int)colInfo.Bottom;
                }

                if ((int)colInfo.Mode < 0)
                {
                    dataAsset.BBoxMode = (uint)(-(1 + (int)colInfo.Mode));
                    dataAsset.SepMasks = GMSprite.SepMaskType.Precise;
                }
                else
                {
                    dataAsset.BBoxMode = (uint)colInfo.Mode;
                    switch (colInfo.Type)
                    {
                    case AssetSprite.CollisionMaskInfo.MaskType.Rectangle:
                        dataAsset.SepMasks = GMSprite.SepMaskType.AxisAlignedRect;
                        break;

                    case AssetSprite.CollisionMaskInfo.MaskType.RectangleWithRotation:
                        dataAsset.SepMasks = GMSprite.SepMaskType.RotatedRect;
                        break;

                    case AssetSprite.CollisionMaskInfo.MaskType.Precise:
                    case AssetSprite.CollisionMaskInfo.MaskType.Diamond:
                    case AssetSprite.CollisionMaskInfo.MaskType.Ellipse:
                    case AssetSprite.CollisionMaskInfo.MaskType.PrecisePerFrame:
                        dataAsset.SepMasks = GMSprite.SepMaskType.Precise;
                        break;
                    }
                }

                // Actually add the texture items
                foreach (var item in projectAsset.TextureItems)
                {
                    dataAsset.TextureItems.Add(item);
                }

                if (projectAsset.SpecialInfo != null)
                {
                    var info = projectAsset.SpecialInfo;

                    dataAsset.SpecialOrGMS2 = true;
                    dataAsset.S_SpriteType  = info.SpriteType;
                    if (info.SpriteType != GMSprite.SpriteType.Normal)
                    {
                        dataAsset.S_Buffer = info.InternalBuffer;
                    }

                    if (info.GMS2PlaybackSpeed != null)
                    {
                        dataAsset.GMS2_PlaybackSpeed     = (float)info.GMS2PlaybackSpeed;
                        dataAsset.GMS2_PlaybackSpeedType = (GMSprite.AnimSpeedType)info.GMS2PlaybackSpeedType;
                    }

                    if (projectAsset.SpecialInfo.Sequence != null)
                    {
                        var seq    = projectAsset.SpecialInfo.Sequence;
                        var newSeq = new GMSequence()
                        {
                            Name              = pf.DataHandle.DefineString(seq.Name),
                            PlaybackType      = GMSequence.PlaybackTypeEnum.Loop,
                            PlaybackSpeed     = dataAsset.GMS2_PlaybackSpeed,
                            PlaybackSpeedType = dataAsset.GMS2_PlaybackSpeedType,
                            Length            = seq.Frames.Max(f => f.Position + f.Length),
                            OriginX           = dataAsset.OriginX,
                            OriginY           = dataAsset.OriginY,
                            Volume            = 1,
                            BroadcastMessages = new(),
                            Tracks            = new()
                            {
                                new()
                                {
                                    BuiltinName     = 0,
                                    IsCreationTrack = false,
                                    Keyframes       = new GMSequence.Track.ValueKeyframes()
                                    {
                                        List = new()
                                    },
                                    ModelName          = pf.DataHandle.DefineString("GMSpriteFramesTrack"),
                                    Name               = pf.DataHandle.DefineString("frames"),
                                    OwnedResources     = new(),
                                    OwnedResourceTypes = new(),
                                    Tags               = new(),
                                    Tracks             = new(),
                                    Traits             = GMSequence.Track.TraitsEnum.Unknown1
                                }
                            },
Beispiel #12
0
        /// <summary>
        /// Gets a .net tree node from a GM node. Stores original GM node data in tag property.
        /// </summary>
        /// <param name="node">The GM node to convert to treenode.</param>
        /// <returns>A tree node version of the GM node.</returns>
        public static TreeNode GetTreeNodeFromGMNode(GMProject project, GMNode node, List <Image> images)
        {
            // Set-up tree node.
            TreeNode treeNode = new TreeNode();

            treeNode.Text = node.Name;
            treeNode.Tag  = node;

            // If the list does not have the folder graphics, add them.
            if (images != null && images.Count < 2)
            {
                images.Add((Image)GMare.Properties.Resources.file_close.Clone());
                images.Add((Image)GMare.Properties.Resources.file_open.Clone());
                images.Add((Image)GMare.Properties.Resources.instance.Clone());
            }

            switch (node.NodeType)
            {
            // If a child node, get appropriate resource key.
            case GMNodeType.Child:

                // Do action based on object type.
                switch (node.ResourceType)
                {
                // Sprites.
                case GMResourceType.Sprites:

                    // If no images to load, break.
                    if (images == null)
                    {
                        break;
                    }

                    // Get sprite.
                    GMSprite sprite = project.Sprites.Find(delegate(GMSprite s) { return(s.Id == node.Id); });

                    // If a sprite was found.
                    if (sprite != null)
                    {
                        // Get image.
                        Bitmap image = GMUtilities.GetBitmap(sprite.SubImages[0]);

                        // Set transparency if needed.
                        if (sprite.Transparent && sprite.SubImages[0].Compressed)
                        {
                            image.MakeTransparent(image.GetPixel(0, image.Height - 1));
                        }

                        images.Add(image);
                        treeNode.ImageIndex         = images.Count - 1;
                        treeNode.SelectedImageIndex = images.Count - 1;
                    }
                    else
                    {
                        treeNode.ImageIndex         = 2;
                        treeNode.SelectedImageIndex = 2;
                    }

                    break;

                // Objects.
                case GMResourceType.Objects:

                    // If no images to load, break.
                    if (images == null)
                    {
                        break;
                    }

                    // Get the object id, use it to get the sprite id.
                    GMObject obj = project.Objects.Find(delegate(GMObject o) { return(o.Id == node.Id); });
                    GMSprite spt = project.Sprites.Find(delegate(GMSprite s) { return(s.Id == obj.SpriteId); });

                    // If a sprite was found.
                    if (spt != null && spt.SubImages != null && spt.SubImages.Length > 0)
                    {
                        // Get image.
                        Bitmap image = GMUtilities.GetBitmap(spt.SubImages[0]);

                        // Set transparency if needed.
                        if (spt.Transparent && spt.SubImages[0].Compressed)
                        {
                            image.MakeTransparent(image.GetPixel(0, image.Height - 1));
                        }

                        images.Add(image);
                        treeNode.ImageIndex         = images.Count - 1;
                        treeNode.SelectedImageIndex = images.Count - 1;
                    }
                    else
                    {
                        treeNode.ImageIndex         = 2;
                        treeNode.SelectedImageIndex = 2;
                    }

                    break;

                // Rooms.
                case GMResourceType.Rooms:
                    treeNode.ImageKey         = ImageKeyRoom;
                    treeNode.SelectedImageKey = ImageKeyRoomSelected;
                    break;
                }

                break;

            // Folders or parents.
            default:
                treeNode.ImageIndex         = 0;
                treeNode.SelectedImageIndex = 1;
                treeNode.ImageKey           = ImageKeyGroup;
                treeNode.SelectedImageKey   = ImageKeyGroupSelected;
                break;
            }

            // If no child nodes, return the top node.
            if (node.Nodes == null)
            {
                return(treeNode);
            }

            // Iterate through nodes.
            for (int i = 0; i < node.Children; i++)
            {
                // Set the node.
                treeNode.Nodes.Add(GetTreeNodeFromGMNode(project, node.Nodes[i], images));
            }

            // Return a .net tree node.
            return(treeNode);
        }