From f9826d8fc6039fb1829dc9752a1c4fb400f8a357 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Sat, 20 Jul 2024 17:47:53 +0200 Subject: [PATCH] AnimationExtensions - Move common serialization functions to animation serializer --- PCK-Studio/Extensions/AnimationExtensions.cs | 76 ------------------- PCK-Studio/Forms/Editor/AnimationEditor.cs | 7 +- .../Deserializer/AnimationDeserializer.cs | 40 +++++++++- .../Serializer/AnimationSerializer.cs | 47 +++++++++++- 4 files changed, 88 insertions(+), 82 deletions(-) diff --git a/PCK-Studio/Extensions/AnimationExtensions.cs b/PCK-Studio/Extensions/AnimationExtensions.cs index 7742b0ef..a16aa28f 100644 --- a/PCK-Studio/Extensions/AnimationExtensions.cs +++ b/PCK-Studio/Extensions/AnimationExtensions.cs @@ -29,81 +29,5 @@ namespace PckStudio.Extensions ms.Position = 0; return Image.FromStream(ms); } - - internal static JObject ConvertToJavaAnimation(this Animation animation) - { - JObject janimation = new JObject(); - JObject mcmeta = new JObject(); - mcmeta["comment"] = $"Animation converted with {Application.ProductName}"; - mcmeta["animation"] = janimation; - JArray jframes = new JArray(); - foreach (Animation.Frame frame in animation.GetFrames()) - { - JObject jframe = new JObject(); - jframe["index"] = animation.GetTextureIndex(frame.Texture); - jframe["time"] = frame.Ticks; - jframes.Add(jframe); - } - janimation["interpolation"] = animation.Interpolate; - janimation["frames"] = jframes; - return mcmeta; - } - - internal static bool ApplyAnim(this Animation animation, string animString) - { - if (string.IsNullOrEmpty(animString)) - { - Trace.TraceError($"[{nameof(AnimationExtensions)}:{nameof(ApplyAnim)}] Failed to parse anim. anim was null or empty."); - return false; - } - animString = animString.Trim(); - - animation.Interpolate = animString.StartsWith("#"); - animString = animation.Interpolate ? animString.Substring(1) : animString; - - string[] animData = animString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - if (animData.Length <= 0) - { - Trace.TraceError($"[{nameof(AnimationExtensions)}:{nameof(ApplyAnim)}] Failed to parse anim. animData was empty."); - return false; - } - - int lastFrameTime = Animation.MinimumFrameTime; - foreach (string frameInfo in animData) - { - string[] frameData = frameInfo.Split('*'); - int currentFrameIndex = 0; - int.TryParse(frameData[0], out currentFrameIndex); - - // Some textures like the Halloween 2015's Lava texture don't have a - // frame time parameter for certain frames. - // This will detect that and place the last frame time in its place. - // This is accurate to console edition behavior. - // - MattNL - int currentFrameTime = frameData.Length < 2 || string.IsNullOrEmpty(frameData[1]) ? lastFrameTime : int.Parse(frameData[1]); - animation.AddFrame(currentFrameIndex, currentFrameTime); - lastFrameTime = currentFrameTime; - } - return true; - } - - internal static string BuildAnim(this Animation animation) - { - StringBuilder stringBuilder = new StringBuilder(animation.Interpolate ? "#" : string.Empty); - foreach (Animation.Frame frame in animation.GetFrames()) - stringBuilder.Append($"{animation.GetTextureIndex(frame.Texture)}*{frame.Ticks},"); - return stringBuilder.ToString(0, stringBuilder.Length - 1); - } - - internal static Image BuildTexture(this Animation animation) - { - IReadOnlyCollection textures = animation.GetTextures(); - Size size = textures.First().Size; - if (size.Width != size.Height) - throw new Exception("Invalid size"); - - return textures.Combine(ImageLayoutDirection.Vertical); - } - } } diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs index 7ef4d29b..e5ba5639 100644 --- a/PCK-Studio/Forms/Editor/AnimationEditor.cs +++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs @@ -33,6 +33,7 @@ using PckStudio.Extensions; using PckStudio.Properties; using PckStudio.Internal; using PckStudio.Internal.Deserializer; +using PckStudio.Internal.Serializer; namespace PckStudio.Forms.Editor { @@ -353,11 +354,11 @@ namespace PckStudio.Forms.Editor fileDialog.Filter = "Animation Scripts (*.mcmeta)|*.png.mcmeta"; if (fileDialog.ShowDialog(this) == DialogResult.OK) { - JObject mcmeta = _animation.ConvertToJavaAnimation(); + JObject mcmeta = AnimationSerializer.SerializeJavaAnimation(_animation); string jsondata = JsonConvert.SerializeObject(mcmeta, Formatting.Indented); string filename = fileDialog.FileName; File.WriteAllText(filename, jsondata); - Image finalTexture = _animation.BuildTexture(); + Image finalTexture = AnimationSerializer.SerializeTexture(_animation); // removes ".mcmeta" from filename string texturePath = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename)); finalTexture.Save(texturePath); @@ -421,7 +422,7 @@ namespace PckStudio.Forms.Editor return; } - var oldResolution = _animation.BuildTexture().Width; + var oldResolution = _animation.GetFrame(0).Texture.Width; FrameDimension dimension = new FrameDimension(gif.FrameDimensionsList[0]); int frameCount = gif.GetFrameCount(dimension); diff --git a/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs b/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs index 62086e22..51e6e580 100644 --- a/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs +++ b/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs @@ -24,12 +24,50 @@ namespace PckStudio.Internal.Deserializer Image texture = asset.GetTexture(); IEnumerable frameTextures = texture.Split(ImageLayoutDirection.Vertical); Animation animation = new Animation(frameTextures); - animation.ApplyAnim(asset.GetProperty("ANIM")); + DeserializeAnimationAnim(ref animation, asset.GetProperty("ANIM")); return animation; } return Animation.CreateEmpty(); } + private static bool DeserializeAnimationAnim(ref Animation animation, string animString) + { + if (string.IsNullOrEmpty(animString)) + { + Trace.TraceError($"[{nameof(AnimationExtensions)}:{nameof(DeserializeAnimationAnim)}] Failed to parse anim. anim was null or empty."); + return false; + } + animString = animString.Trim(); + + animation.Interpolate = animString.StartsWith("#"); + animString = animation.Interpolate ? animString.Substring(1) : animString; + + string[] animData = animString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + if (animData.Length <= 0) + { + Trace.TraceError($"[{nameof(AnimationExtensions)}:{nameof(DeserializeAnimationAnim)}] Failed to parse anim. animData was empty."); + return false; + } + + int lastFrameTime = Animation.MinimumFrameTime; + foreach (string frameInfo in animData) + { + string[] frameData = frameInfo.Split('*'); + int currentFrameIndex = 0; + int.TryParse(frameData[0], out currentFrameIndex); + + // Some textures like the Halloween 2015's Lava texture don't have a + // frame time parameter for certain frames. + // This will detect that and place the last frame time in its place. + // This is accurate to console edition behavior. + // - MattNL + int currentFrameTime = frameData.Length < 2 || string.IsNullOrEmpty(frameData[1]) ? lastFrameTime : int.Parse(frameData[1]); + animation.AddFrame(currentFrameIndex, currentFrameTime); + lastFrameTime = currentFrameTime; + } + return true; + } + public Animation DeserializeJavaAnimation(JObject jsonObject, Image texture) { IEnumerable textures = texture.Split(ImageLayoutDirection.Vertical); diff --git a/PCK-Studio/Internal/Serializer/AnimationSerializer.cs b/PCK-Studio/Internal/Serializer/AnimationSerializer.cs index fa209fe3..08e08272 100644 --- a/PCK-Studio/Internal/Serializer/AnimationSerializer.cs +++ b/PCK-Studio/Internal/Serializer/AnimationSerializer.cs @@ -15,10 +15,16 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ +using System.Collections.Generic; +using System; using System.Drawing; +using System.Text; using OMI.Formats.Pck; using PckStudio.Extensions; using PckStudio.Interfaces; +using System.Linq; +using Newtonsoft.Json.Linq; +using System.Windows.Forms; namespace PckStudio.Internal.Serializer { @@ -28,10 +34,47 @@ namespace PckStudio.Internal.Serializer public void Serialize(Animation animation, ref PckAsset asset) { - string anim = animation.BuildAnim(); + string anim = SerializeAnim(animation); asset.SetProperty("ANIM", anim); - Image texture = animation.BuildTexture(); + Image texture = SerializeTexture(animation); asset.SetTexture(texture); } + + private static string SerializeAnim(Animation animation) + { + StringBuilder stringBuilder = new StringBuilder(animation.Interpolate ? "#" : string.Empty); + foreach (Animation.Frame frame in animation.GetFrames()) + stringBuilder.Append($"{animation.GetTextureIndex(frame.Texture)}*{frame.Ticks},"); + return stringBuilder.ToString(0, stringBuilder.Length - 1); + } + + internal static Image SerializeTexture(Animation animation) + { + IReadOnlyCollection textures = animation.GetTextures(); + Size size = textures.First().Size; + if (size.Width != size.Height) + throw new Exception("Invalid size"); + + return textures.Combine(ImageLayoutDirection.Vertical); + } + + internal static JObject SerializeJavaAnimation(Animation animation) + { + JObject janimation = new JObject(); + JObject mcmeta = new JObject(); + mcmeta["comment"] = $"Animation converted with {Application.ProductName}"; + mcmeta["animation"] = janimation; + JArray jframes = new JArray(); + foreach (Animation.Frame frame in animation.GetFrames()) + { + JObject jframe = new JObject(); + jframe["index"] = animation.GetTextureIndex(frame.Texture); + jframe["time"] = frame.Ticks; + jframes.Add(jframe); + } + janimation["interpolation"] = animation.Interpolate; + janimation["frames"] = jframes; + return mcmeta; + } } }