mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-05-22 01:06:35 +00:00
AnimationExtensions - Move common serialization functions to animation serializer
This commit is contained in:
@@ -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<Image> textures = animation.GetTextures();
|
||||
Size size = textures.First().Size;
|
||||
if (size.Width != size.Height)
|
||||
throw new Exception("Invalid size");
|
||||
|
||||
return textures.Combine(ImageLayoutDirection.Vertical);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,12 +24,50 @@ namespace PckStudio.Internal.Deserializer
|
||||
Image texture = asset.GetTexture();
|
||||
IEnumerable<Image> 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<Image> textures = texture.Split(ImageLayoutDirection.Vertical);
|
||||
|
||||
@@ -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<Image> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user