예제 #1
0
        private void MaskExport_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSprite sprite = this.DataContext as UndertaleSprite;

            UndertaleSprite.MaskEntry target = (sender as Button).DataContext as UndertaleSprite.MaskEntry;

            SaveFileDialog dlg = new SaveFileDialog();

            dlg.DefaultExt = ".png";
            dlg.Filter     = "PNG files (.png)|*.png|All files|*";

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    BitmapSource     source  = BitmapSource.Create((int)sprite.Width, (int)sprite.Height, 96, 96, PixelFormats.BlackWhite, null, target.Data, (int)((sprite.Width + 7) / 8));
                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(source));
                    using (FileStream stream = new FileStream(dlg.FileName, FileMode.Create))
                    {
                        encoder.Save(stream);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to export file: " + ex.Message, "Failed to export file", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
예제 #2
0
        private void MaskImport_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSprite sprite = this.DataContext as UndertaleSprite;

            UndertaleSprite.MaskEntry target = (sender as Button).DataContext as UndertaleSprite.MaskEntry;

            OpenFileDialog dlg = new OpenFileDialog();

            dlg.DefaultExt = ".png";
            dlg.Filter     = "PNG files (.png)|*.png|All files|*";

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    System.Drawing.Image img = System.Drawing.Image.FromFile(dlg.FileName);
                    if ((sprite.Width != (uint)img.Width) || (sprite.Height != (uint)img.Height))
                    {
                        throw new System.Exception(dlg.FileName + " is not the proper size to be imported! Please correct this before importing! The proper dimensions are width: " + sprite.Width.ToString() + " px, height: " + sprite.Height.ToString() + " px.");
                    }
                    target.Data = TextureWorker.ReadMaskData(dlg.FileName);
                }
                catch (Exception ex)
                {
                    mainWindow.ShowError("Failed to import file: " + ex.Message, "Failed to import file");
                }
            }
        }
예제 #3
0
        private void ExportAll_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSprite sprite = this.DataContext as UndertaleSprite;

            SaveFileDialog dlg = new SaveFileDialog();

            dlg.FileName   = sprite.Name.Content + ".png";
            dlg.DefaultExt = ".png";
            dlg.Filter     = "PNG files (.png)|*.png|All files|*";

            TextureWorker worker = new TextureWorker();

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    if (sprite.Textures.Count > 1)
                    {
                        string dir  = System.IO.Path.GetDirectoryName(dlg.FileName);
                        string name = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);
                        string path = System.IO.Path.Combine(dir, name);
                        string ext  = System.IO.Path.GetExtension(dlg.FileName);

                        Directory.CreateDirectory(path);
                        foreach (var tex in sprite.Textures.Select((tex, id) => new { id, tex }))
                        {
                            try
                            {
                                worker.ExportAsPNG(tex.tex.Texture, System.IO.Path.Combine(path, tex.id + ext));
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("Failed to export file: " + ex.Message, "Failed to export file", MessageBoxButton.OK, MessageBoxImage.Error);
                            }
                        }
                    }
                    else if (sprite.Textures.Count == 1)
                    {
                        try
                        {
                            worker.ExportAsPNG(sprite.Textures[0].Texture, dlg.FileName);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("Failed to export file: " + ex.Message, "Failed to export file", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                    else
                    {
                        MessageBox.Show("No frames to export", "Failed to export sprite", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to export: " + ex.Message, "Failed to export sprite", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

            worker.Cleanup();
        }
예제 #4
0
        private void MaskList_AddingNewItem(object sender, AddingNewItemEventArgs e)
        {
            UndertaleSprite.MaskEntry obj    = new UndertaleSprite.MaskEntry();
            UndertaleSprite           sprite = this.DataContext as UndertaleSprite;
            uint len = (sprite.Width + 7) / 8 * sprite.Height;

            obj.Data  = new byte[len];
            e.NewItem = obj;
        }
예제 #5
0
        public static Bitmap GetCollisionMaskImage(UndertaleSprite sprite, UndertaleSprite.MaskEntry mask)
        {
            byte[] maskData = mask.Data;
            Bitmap bitmap   = new Bitmap((int)sprite.Width, (int)sprite.Height, PixelFormat.Format32bppArgb); // Ugh. I want to use 1bpp, but for some BS reason C# doesn't allow SetPixel in that mode.

            for (int y = 0; y < sprite.Height; y++)
            {
                int rowStart = y * (int)((sprite.Width + 7) / 8);
                for (int x = 0; x < sprite.Width; x++)
                {
                    byte temp     = maskData[rowStart + (x / 8)];
                    bool pixelBit = (temp & (0b1 << (7 - (x % 8)))) != 0b0;
                    bitmap.SetPixel(x, y, pixelBit ? Color.White : Color.Black);
                }
            }

            return(bitmap);
        }
예제 #6
0
        private void ExportAllSpine(SaveFileDialog dlg, UndertaleSprite sprite)
        {
            mainWindow.ShowWarning("This seems to be a Spine sprite, .json and .atlas files will be exported together with the frames. " +
                                   "PLEASE EDIT THEM CAREFULLY! SOME MANUAL EDITING OF THE JSON MAY BE REQUIRED! THE DATA IS EXPORTED AS-IS.", "Spine warning");

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    string dir  = System.IO.Path.GetDirectoryName(dlg.FileName);
                    string name = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);
                    string path = System.IO.Path.Combine(dir, name);
                    string ext  = System.IO.Path.GetExtension(dlg.FileName);

                    if (sprite.SpineTextures.Count > 0)
                    {
                        Directory.CreateDirectory(path);

                        // textures
                        foreach (var tex in sprite.SpineTextures.Select((tex, id) => new { id, tex }))
                        {
                            try
                            {
                                File.WriteAllBytes(System.IO.Path.Combine(path, tex.id + ext), tex.tex.PNGBlob);
                            }
                            catch (Exception ex)
                            {
                                mainWindow.ShowError("Failed to export file: " + ex.Message, "Failed to export file");
                            }
                        }

                        // json and atlas
                        File.WriteAllText(System.IO.Path.Combine(path, "spine.json"), sprite.SpineJSON);
                        File.WriteAllText(System.IO.Path.Combine(path, "spine.atlas"), sprite.SpineAtlas);
                    }
                }
                catch (Exception ex)
                {
                    mainWindow.ShowError("Failed to export: " + ex.Message, "Failed to export sprite");
                }
            }
        }
예제 #7
0
        private void MaskImport_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSprite sprite = this.DataContext as UndertaleSprite;

            UndertaleSprite.MaskEntry target = (sender as Button).DataContext as UndertaleSprite.MaskEntry;

            OpenFileDialog dlg = new OpenFileDialog();

            dlg.DefaultExt = ".png";
            dlg.Filter     = "PNG files (.png)|*.png|All files|*";

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    using (FileStream stream = new FileStream(dlg.FileName, FileMode.Open))
                    {
                        PngBitmapDecoder decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                        BitmapSource     source  = decoder.Frames[0];
                        if (source.Format.BitsPerPixel != 1)
                        {
                            throw new Exception("Must be a 1 bit-per-pixel image");
                        }
                        if (source.PixelWidth != sprite.Width || source.PixelHeight != sprite.Height)
                        {
                            throw new Exception("Mask size doesn't match sprite size");
                        }
                        int    stride = (int)((sprite.Width + 7) / 8);
                        byte[] data   = new byte[source.PixelHeight * stride];
                        source.CopyPixels(data, stride, 0);
                        target.Data = data;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to import file: " + ex.Message, "Failed to import file", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
예제 #8
0
        private void MaskExport_Click(object sender, RoutedEventArgs e)
        {
            UndertaleSprite sprite = this.DataContext as UndertaleSprite;

            UndertaleSprite.MaskEntry target = (sender as Button).DataContext as UndertaleSprite.MaskEntry;

            SaveFileDialog dlg = new SaveFileDialog();

            dlg.DefaultExt = ".png";
            dlg.Filter     = "PNG files (.png)|*.png|All files|*";

            if (dlg.ShowDialog() == true)
            {
                try
                {
                    TextureWorker.ExportCollisionMaskPNG(sprite, target, dlg.FileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to export file: " + ex.Message, "Failed to export file", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
예제 #9
0
 public static void ExportCollisionMaskPNG(UndertaleSprite sprite, UndertaleSprite.MaskEntry mask, string fullPath)
 {
     SaveImageToFile(fullPath, GetCollisionMaskImage(sprite, mask));
 }
예제 #10
0
        public static void SpeedrunPatches(UndertaleData data)
        {
            UndertaleScript setboi = new UndertaleScript();

            setboi.Name      = data.Strings.MakeString("set_speedrun_category");
            setboi.Code      = new UndertaleCode();
            setboi.Code.Name = data.Strings.MakeString("gml_Script_set_speedrun_category");
            setboi.Code.ReplaceGML(RabbitRunCode.set_speedrun_category, data);
            data.Code.Add(setboi.Code);
            data.Scripts.Add(setboi);

            UndertaleScript sprun = new UndertaleScript();

            sprun.Name = new UndertaleString("menu_speedrun_script");
            data.Strings.Add(sprun.Name);
            sprun.Code = new UndertaleCode();
            data.Code.Add(sprun.Code);
            sprun.Code.Name = new UndertaleString("gml_Script_menu_speedrun_script");
            data.Strings.Add(sprun.Code.Name);
            sprun.Code.ReplaceGML(RabbitRunCode.menu_speedrun_script, data);
            sprun.Code.UpdateAddresses();
            data.Scripts.Add(sprun);

            UndertaleCode ae = data.Code.ByName("gml_Script_setfile");

            ae.AppendGML(RabbitRunCode.gml_Script_setfile, data);
            ae.UpdateAddresses();

            UndertaleCode ee = data.Code.ByName("gml_Object_obj_mainmenus_Create_0");

            ReplaceInGML("GAME\", 1, 8],", "GAME\", 1, 8], [\"SPEEDBUN\", 1, 19], ", ee, data);
            ee.UpdateAddresses();
            ReplaceInGML("i = 0", RabbitRunCode.speedrunMenuInit, ee, data);

            UndertaleCode ie = data.Code.ByName("gml_Script_cKeys_beginstep");

            ie.AppendGML(RabbitRunCode.tasBeginStepInput, data);

            UndertaleCode oe = data.Code.ByName("gml_Object_obj_init_Create_0");

            oe.AppendGML(@"global.playRun = false;
global.watchRun = false;
global.speedrunning = true;
global.inrun = false;
global.onehun = false;//one hundred percent
global.allbun = false;//all cuties
global.anyper = false;//any percent", data);

            UndertaleCode ue = data.Code.ByName("gml_Script_SaveStringToFile");

            ue.ReplaceGML(RabbitRunCode.saveStringFile, data);

            UndertaleSprite mico = data.Sprites.ByName("spr_menuicons");

            UndertaleSprite.TextureEntry te = new UndertaleSprite.TextureEntry();
            UndertaleTexturePageItem     ti = mico.Textures[1].Texture;
            UndertaleTexturePageItem     to = data.Sprites.ByName("spr_antibunidle").Textures[0].Texture;

            te.Texture                = new UndertaleTexturePageItem();
            te.Texture.TargetX        = ti.TargetX;
            te.Texture.TargetY        = ti.TargetY;
            te.Texture.SourceX        = to.SourceX;
            te.Texture.SourceY        = to.SourceY;
            te.Texture.BoundingHeight = ti.BoundingHeight;
            te.Texture.BoundingWidth  = ti.BoundingWidth;
            te.Texture.SourceWidth    = 16;
            te.Texture.TargetWidth    = 16;
            te.Texture.SourceHeight   = 15;
            te.Texture.TargetHeight   = 15;
            te.Texture.TexturePage    = to.TexturePage;
            data.TexturePageItems.Add(te.Texture);
            mico.Textures.Insert(2, te);
        }