From 4ca35a5e92a02234de2d2dea3cc5a775c66a7ad3 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Wed, 30 Aug 2023 18:42:30 +0200 Subject: [PATCH] AnimationEditor - Added ability to export animation as gif --- PCK-Studio/Forms/Editor/AnimationEditor.cs | 49 +++++++--------------- PCK-Studio/Internal/Animation.cs | 32 +++++++++++++- PCK-Studio/PckStudio.csproj | 3 ++ 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs index 4638c6a3..aae1adf3 100644 --- a/PCK-Studio/Forms/Editor/AnimationEditor.cs +++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs @@ -34,6 +34,7 @@ using PckStudio.Properties; using PckStudio.Internal; using PckStudio.Internal.Json; using PckStudio.Helper; +using AnimatedGif; namespace PckStudio.Forms.Editor { @@ -291,7 +292,6 @@ namespace PckStudio.Forms.Editor diag.Dispose(); } - // Reworked import tool with new Animation classes by Miku private void importJavaAnimationToolStripMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show( @@ -483,40 +483,23 @@ namespace PckStudio.Forms.Editor LoadAnimationTreeView(); } - //[System.Runtime.InteropServices.DllImport("gdi32.dll")] - //public static extern bool DeleteObject(IntPtr hObject); - - private void gifToolStripMenuItem_Click(object sender, EventArgs e) + private void gifToolStripMenuItem_Click(object sender, EventArgs e) { - MessageBox.Show(this, "This feature is still under development", "Coming soon"); - return; + var fileDialog = new SaveFileDialog() + { + FileName = _tileName, + Filter = "GIF file|*.gif" + }; + if (fileDialog.ShowDialog(this) != DialogResult.OK) + return; - // TODO - //var fileDialog = new SaveFileDialog() - //{ - // Filter = "GIF file|*.gif" - //}; - //if (fileDialog.ShowDialog(this) != DialogResult.OK) - // return; - - //GifBitmapEncoder gifBitmapEncoder = new GifBitmapEncoder(); - - //foreach (Bitmap texture in currentAnimation.GetTextures()) - //{ - // var bmp = texture.GetHbitmap(); - // var src = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( - // bmp, - // IntPtr.Zero, - // System.Windows.Int32Rect.Empty, - // BitmapSizeOptions.FromWidthAndHeight(texture.Width, texture.Height)); - // gifBitmapEncoder.Frames.Add(BitmapFrame.Create(src)); - // DeleteObject(bmp); // recommended, handle memory leak - //} - - //using (var fs = fileDialog.OpenFile()) - //{ - // gifBitmapEncoder.Save(fs); - //} + using (var gifWriter = AnimatedGif.AnimatedGif.Create(fileDialog.FileName, Animation.GameTickInMilliseconds, repeat: 0)) + { + foreach (var frame in _animation.GetInterpolatedFrames()) + { + gifWriter.AddFrame(frame.Texture, frame.Ticks * Animation.GameTickInMilliseconds, GifQuality.Bit8); + } + } } private void frameTimeandTicksToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/PCK-Studio/Internal/Animation.cs b/PCK-Studio/Internal/Animation.cs index 21f6793e..2b877380 100644 --- a/PCK-Studio/Internal/Animation.cs +++ b/PCK-Studio/Internal/Animation.cs @@ -21,6 +21,7 @@ using System.Drawing; using PckStudio.Extensions; using System.Text; using System.Collections.ObjectModel; +using System.Linq; namespace PckStudio.Internal { @@ -28,6 +29,8 @@ namespace PckStudio.Internal { public const int MinimumFrameTime = 1; + public const int GameTickInMilliseconds = 50; + public static Animation Empty(AnimationCategory category) { var animation = new Animation(Array.Empty(), string.Empty); @@ -172,7 +175,34 @@ namespace PckStudio.Internal return new ReadOnlyCollection(frames); } - public IReadOnlyCollection GetTextures() + public IReadOnlyCollection GetInterpolatedFrames() + { + if (Interpolate) + { + return new ReadOnlyCollection(InternalGetInterpolatedFrames().ToList()); + } + return GetFrames(); + } + + private IEnumerable InternalGetInterpolatedFrames() + { + for (int i = 0; i < FrameCount; i++) + { + Frame currentFrame = frames[i]; + Frame nextFrame = frames[0]; + if (i + 1 < FrameCount) + nextFrame = frames[i + 1]; + for (int tick = 0; tick < currentFrame.Ticks; tick++) + { + double delta = 1.0f - tick / (double)currentFrame.Ticks; + yield return new Frame(currentFrame.Texture.Interpolate(nextFrame.Texture, delta)); + } + } + yield break; + } + + + public IReadOnlyCollection GetTextures() { return textures; } diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 73092839..3e040c1d 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -691,6 +691,9 @@ + + 1.0.5 + 5.8.0-alpha0098 compile; runtime; build; native; contentfiles; analyzers; buildtransitive