From 243c3fda0e87983da47aff63f4d20dc244e146ad Mon Sep 17 00:00:00 2001
From: miku-666 <74728189+NessieHax@users.noreply.github.com>
Date: Sat, 20 Jul 2024 13:20:52 +0200
Subject: [PATCH 1/3] GRF/AddParameter - Add auto complete to param promt and
remove combobox option
---
PCK-Studio/App.config | 3 --
.../Grf/AddParameter.Designer.cs | 32 +++++--------------
.../Additional-Popups/Grf/AddParameter.cs | 27 ++--------------
PCK-Studio/Forms/AppSettingsForm.cs | 1 -
PCK-Studio/Properties/Settings.Designer.cs | 14 +-------
PCK-Studio/Properties/Settings.settings | 3 --
6 files changed, 12 insertions(+), 68 deletions(-)
diff --git a/PCK-Studio/App.config b/PCK-Studio/App.config
index f3cb4efa..c3b1b2f6 100644
--- a/PCK-Studio/App.config
+++ b/PCK-Studio/App.config
@@ -77,9 +77,6 @@
False
-
- False
-
diff --git a/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.Designer.cs b/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.Designer.cs
index 78eb47ae..7da3b34f 100644
--- a/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.Designer.cs
+++ b/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.Designer.cs
@@ -35,7 +35,6 @@
this.ValueTextBox = new MetroFramework.Controls.MetroTextBox();
this.CancelBtn = new MetroFramework.Controls.MetroButton();
this.ConfirmBtn = new MetroFramework.Controls.MetroButton();
- this.availableComboBox = new MetroFramework.Controls.MetroComboBox();
metroLabel1 = new MetroFramework.Controls.MetroLabel();
metroLabel2 = new MetroFramework.Controls.MetroLabel();
this.SuspendLayout();
@@ -46,7 +45,7 @@
metroLabel1.Location = new System.Drawing.Point(18, 27);
metroLabel1.Name = "metroLabel1";
metroLabel1.Size = new System.Drawing.Size(48, 19);
- metroLabel1.TabIndex = 0;
+ metroLabel1.TabIndex = 4;
metroLabel1.Text = "Name:";
metroLabel1.Theme = MetroFramework.MetroThemeStyle.Dark;
//
@@ -56,12 +55,14 @@
metroLabel2.Location = new System.Drawing.Point(17, 56);
metroLabel2.Name = "metroLabel2";
metroLabel2.Size = new System.Drawing.Size(42, 19);
- metroLabel2.TabIndex = 1;
+ metroLabel2.TabIndex = 5;
metroLabel2.Text = "Value:";
metroLabel2.Theme = MetroFramework.MetroThemeStyle.Dark;
//
// NameTextBox
//
+ this.NameTextBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
+ this.NameTextBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
//
//
//
@@ -86,7 +87,7 @@
this.NameTextBox.ShortcutsEnabled = true;
this.NameTextBox.Size = new System.Drawing.Size(165, 23);
this.NameTextBox.Style = MetroFramework.MetroColorStyle.White;
- this.NameTextBox.TabIndex = 2;
+ this.NameTextBox.TabIndex = 0;
this.NameTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
this.NameTextBox.UseSelectable = true;
this.NameTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
@@ -117,8 +118,7 @@
this.ValueTextBox.SelectionStart = 0;
this.ValueTextBox.ShortcutsEnabled = true;
this.ValueTextBox.Size = new System.Drawing.Size(165, 23);
- this.ValueTextBox.Style = MetroFramework.MetroColorStyle.White;
- this.ValueTextBox.TabIndex = 3;
+ this.ValueTextBox.TabIndex = 1;
this.ValueTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
this.ValueTextBox.UseSelectable = true;
this.ValueTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
@@ -131,7 +131,7 @@
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.Size = new System.Drawing.Size(95, 23);
this.CancelBtn.Style = MetroFramework.MetroColorStyle.White;
- this.CancelBtn.TabIndex = 4;
+ this.CancelBtn.TabIndex = 2;
this.CancelBtn.Text = "Cancel";
this.CancelBtn.Theme = MetroFramework.MetroThemeStyle.Dark;
this.CancelBtn.UseSelectable = true;
@@ -142,33 +142,18 @@
this.ConfirmBtn.Name = "ConfirmBtn";
this.ConfirmBtn.Size = new System.Drawing.Size(96, 23);
this.ConfirmBtn.Style = MetroFramework.MetroColorStyle.White;
- this.ConfirmBtn.TabIndex = 5;
+ this.ConfirmBtn.TabIndex = 3;
this.ConfirmBtn.Text = "Confirm";
this.ConfirmBtn.Theme = MetroFramework.MetroThemeStyle.Dark;
this.ConfirmBtn.UseSelectable = true;
this.ConfirmBtn.Click += new System.EventHandler(this.ConfirmButton_Click);
//
- // availableComboBox
- //
- this.availableComboBox.FormattingEnabled = true;
- this.availableComboBox.ItemHeight = 23;
- this.availableComboBox.Location = new System.Drawing.Point(72, 21);
- this.availableComboBox.Name = "availableComboBox";
- this.availableComboBox.Size = new System.Drawing.Size(165, 29);
- this.availableComboBox.Style = MetroFramework.MetroColorStyle.Silver;
- this.availableComboBox.TabIndex = 6;
- this.availableComboBox.Theme = MetroFramework.MetroThemeStyle.Dark;
- this.availableComboBox.UseSelectable = true;
- this.availableComboBox.Visible = false;
- this.availableComboBox.SelectedIndexChanged += new System.EventHandler(this.availableComboBox_SelectedIndexChanged);
- //
// AddParameter
//
this.AcceptButton = this.ConfirmBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(264, 126);
- this.Controls.Add(this.availableComboBox);
this.Controls.Add(this.ConfirmBtn);
this.Controls.Add(this.CancelBtn);
this.Controls.Add(this.ValueTextBox);
@@ -192,6 +177,5 @@
private MetroFramework.Controls.MetroButton CancelBtn;
private MetroFramework.Controls.MetroButton ConfirmBtn;
private MetroFramework.Controls.MetroTextBox NameTextBox;
- private MetroFramework.Controls.MetroComboBox availableComboBox;
}
}
\ No newline at end of file
diff --git a/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.cs b/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.cs
index ee5795d6..58ca66d0 100644
--- a/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.cs
+++ b/PCK-Studio/Forms/Additional-Popups/Grf/AddParameter.cs
@@ -1,7 +1,6 @@
using System;
using System.Windows.Forms;
using OMI.Formats.GameRule;
-using PckStudio.Properties;
namespace PckStudio.Forms.Additional_Popups.Grf
{
@@ -10,25 +9,12 @@ namespace PckStudio.Forms.Additional_Popups.Grf
public string ParameterName => NameTextBox.Text;
public string ParameterValue => ValueTextBox.Text;
- private bool _useComboBox
- {
- get
- {
- return availableComboBox.Visible && !NameTextBox.Visible;
- }
- set
- {
- NameTextBox.Visible = !value;
- availableComboBox.Visible = value;
- }
- }
public AddParameter()
{
InitializeComponent();
- availableComboBox.Items.Clear();
- availableComboBox.Items.AddRange(GameRuleFile.GameRule.ValidParameters);
- _useComboBox = Settings.Default.UseComboBoxForGRFParameter;
+ NameTextBox.AutoCompleteCustomSource = new AutoCompleteStringCollection();
+ NameTextBox.AutoCompleteCustomSource.AddRange(GameRuleFile.GameRule.ValidParameters);
}
public AddParameter(string parameterName, string parameterValue, bool isKeyReadonly = true) : this()
@@ -36,23 +22,16 @@ namespace PckStudio.Forms.Additional_Popups.Grf
NameTextBox.Text = parameterName;
ValueTextBox.Text = parameterValue;
NameTextBox.Enabled = isKeyReadonly;
- availableComboBox.Enabled = isKeyReadonly;
- availableComboBox.SelectedItem = parameterName;
}
private void ConfirmButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(ParameterName) || string.IsNullOrWhiteSpace(ParameterValue))
{
- MessageBox.Show(this, "Name and Value need valid values");
+ MessageBox.Show(this, "Name or value can't be empty.", "Empty value", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
return;
}
DialogResult = DialogResult.OK;
}
-
- private void availableComboBox_SelectedIndexChanged(object sender, EventArgs e)
- {
- NameTextBox.Text = availableComboBox.SelectedItem.ToString();
- }
}
}
diff --git a/PCK-Studio/Forms/AppSettingsForm.cs b/PCK-Studio/Forms/AppSettingsForm.cs
index 8d1927bb..f9aa41d5 100644
--- a/PCK-Studio/Forms/AppSettingsForm.cs
+++ b/PCK-Studio/Forms/AppSettingsForm.cs
@@ -33,7 +33,6 @@ namespace PckStudio.Forms
["AutoUpdate"] = "Auto Update",
["LoadSubPcks"] = "Load Sub Pcks",
["UsePrerelease"] = "Use Prerelease",
- ["UseComboBoxForGRFParameter"] = "Easy Grf Param",
};
private void CheckBox_CheckedChanged(object sender, EventArgs e)
diff --git a/PCK-Studio/Properties/Settings.Designer.cs b/PCK-Studio/Properties/Settings.Designer.cs
index 8acf7cc9..0f286e3c 100644
--- a/PCK-Studio/Properties/Settings.Designer.cs
+++ b/PCK-Studio/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace PckStudio.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -104,18 +104,6 @@ namespace PckStudio.Properties {
}
}
- [global::System.Configuration.UserScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("False")]
- public bool UseComboBoxForGRFParameter {
- get {
- return ((bool)(this["UseComboBoxForGRFParameter"]));
- }
- set {
- this["UseComboBoxForGRFParameter"] = value;
- }
- }
-
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Collections.Specialized.StringCollection RecentFiles {
diff --git a/PCK-Studio/Properties/Settings.settings b/PCK-Studio/Properties/Settings.settings
index 1003231b..a32cf0c7 100644
--- a/PCK-Studio/Properties/Settings.settings
+++ b/PCK-Studio/Properties/Settings.settings
@@ -23,9 +23,6 @@
False
-
- False
-
From bb6209105c2493003885b61a2ee33665ddcb1a69 Mon Sep 17 00:00:00 2001
From: miku-666 <74728189+NessieHax@users.noreply.github.com>
Date: Sat, 20 Jul 2024 14:58:41 +0200
Subject: [PATCH 2/3] Animation - Move anim parsing away from class and add
option for generating frame by texture
---
PCK-Studio/Extensions/AnimationExtensions.cs | 63 +++++++++++++++++-
PCK-Studio/Extensions/ImageExtensions.cs | 27 ++++----
PCK-Studio/Forms/Editor/AnimationEditor.cs | 10 +--
PCK-Studio/Internal/Animation.cs | 66 ++-----------------
.../Deserializer/AnimationDeserializer.cs | 5 +-
5 files changed, 86 insertions(+), 85 deletions(-)
diff --git a/PCK-Studio/Extensions/AnimationExtensions.cs b/PCK-Studio/Extensions/AnimationExtensions.cs
index b9270538..7742b0ef 100644
--- a/PCK-Studio/Extensions/AnimationExtensions.cs
+++ b/PCK-Studio/Extensions/AnimationExtensions.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
@@ -21,7 +22,7 @@ namespace PckStudio.Extensions
}
var ms = new System.IO.MemoryStream();
var generateor = new AnimatedGifCreator(ms, GameConstants.GameTickInMilliseconds, 0);
- foreach (var frame in animation.GetInterpolatedFrames())
+ foreach (Animation.Frame frame in animation.GetInterpolatedFrames())
{
generateor.AddFrame(frame.Texture, frame.Ticks * GameConstants.GameTickInMilliseconds, GifQuality.Bit8);
}
@@ -36,17 +37,73 @@ namespace PckStudio.Extensions
mcmeta["comment"] = $"Animation converted with {Application.ProductName}";
mcmeta["animation"] = janimation;
JArray jframes = new JArray();
- foreach (var frame in animation.GetFrames())
+ 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/Extensions/ImageExtensions.cs b/PCK-Studio/Extensions/ImageExtensions.cs
index f1c57cd8..76f104e5 100644
--- a/PCK-Studio/Extensions/ImageExtensions.cs
+++ b/PCK-Studio/Extensions/ImageExtensions.cs
@@ -87,40 +87,41 @@ namespace PckStudio.Extensions
yield break;
}
- internal static Image Combine(this IList sources, ImageLayoutDirection layoutDirection)
+ internal static Image Combine(this IEnumerable sources, ImageLayoutDirection layoutDirection)
{
Size imageSize = CalculateImageSize(sources, layoutDirection);
var image = new Bitmap(imageSize.Width, imageSize.Height);
using (var graphic = Graphics.FromImage(image))
{
- foreach (var (i, texture) in sources.enumerate())
+ foreach ((int i, Image texture) in sources.enumerate())
{
var info = new ImageSection(texture.Size, i, layoutDirection);
graphic.DrawImage(texture, info.Point);
- };
+ }
}
return image;
}
- private static Size CalculateImageSize(IList sources, ImageLayoutDirection layoutDirection)
+ private static Size CalculateImageSize(IEnumerable sources, ImageLayoutDirection layoutDirection)
{
- if (sources.Count < 2)
- {
- return sources.Count < 1 ? Size.Empty : sources[0].Size;
- }
- var horizontal = layoutDirection == ImageLayoutDirection.Horizontal;
+ Size size = sources.First().Size;
+ int width = size.Width;
+ int height = size.Height;
+ int count = sources.Count();
- int width = sources[0].Width;
- int height = sources[0].Height;
+ if (count < 2)
+ return count < 1 ? Size.Empty : size;
+
+ var horizontal = layoutDirection == ImageLayoutDirection.Horizontal;
if (!sources.All(img => img.Width.Equals(width) && img.Height.Equals(height)))
throw new InvalidOperationException("Images must have the same width and height.");
if (horizontal)
- width *= sources.Count;
+ width *= count;
else
- height *= sources.Count;
+ height *= count;
return new Size(width, height);
}
diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs
index 0446c80e..7ef4d29b 100644
--- a/PCK-Studio/Forms/Editor/AnimationEditor.cs
+++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs
@@ -336,7 +336,6 @@ namespace PckStudio.Forms.Editor
var img = Image.FromFile(textureFile);
JObject mcmeta = JObject.Parse(File.ReadAllText(fileDialog.FileName));
Animation javaAnimation = AnimationDeserializer.DefaultDeserializer.DeserializeJavaAnimation(mcmeta, img);
- //javaAnimation.Category = _animation.Category;
_animation = javaAnimation;
LoadAnimationTreeView();
}
@@ -436,10 +435,7 @@ namespace PckStudio.Forms.Editor
textures.Add(new Bitmap(gif, oldResolution, oldResolution));
}
- // TODO: Add function or a other way to initialize the frames by textures.
- // Currently single frames only get added when an anim has an invalid format or is empty.
- // -Miku
- _animation = new Animation(textures, "");
+ _animation = new Animation(textures, initFramesFromTextures: true);
_animation.Interpolate = InterpolationCheckbox.Checked;
LoadAnimationTreeView();
}
@@ -453,9 +449,9 @@ namespace PckStudio.Forms.Editor
};
if (ofd.ShowDialog(this) != DialogResult.OK)
return;
- Image img = Image.FromFile(ofd.FileName);
+ using Image img = Image.FromFile(ofd.FileName);
IEnumerable textures = img.Split(ImageLayoutDirection.Vertical);
- _animation = new Animation(textures, string.Empty);
+ _animation = new Animation(textures, initFramesFromTextures: true);
LoadAnimationTreeView();
}
diff --git a/PCK-Studio/Internal/Animation.cs b/PCK-Studio/Internal/Animation.cs
index 3d37d509..8b1c9966 100644
--- a/PCK-Studio/Internal/Animation.cs
+++ b/PCK-Studio/Internal/Animation.cs
@@ -22,6 +22,7 @@ using PckStudio.Extensions;
using System.Text;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Diagnostics;
namespace PckStudio.Internal
{
@@ -41,17 +42,13 @@ namespace PckStudio.Internal
private object _syncLock = new object();
- public Animation(IEnumerable textures)
+ public Animation(IEnumerable textures, bool initFramesFromTextures = false)
{
_textures = new List(textures);
+ if (initFramesFromTextures)
+ AddTexturesAsFrames(MinimumFrameTime);
}
- public Animation(IEnumerable textures, string ANIM)
- : this(textures)
- {
- ParseAnim(ANIM);
- }
-
public class Frame
{
public readonly Image Texture;
@@ -83,47 +80,12 @@ namespace PckStudio.Internal
}
}
- private void ParseAnim(string anim)
- {
- if (string.IsNullOrEmpty(anim))
- {
- AddSingleFrames();
- return;
- }
- anim = anim.Trim();
- anim = (Interpolate = anim.StartsWith("#")) ? anim.Substring(1) : anim;
- string[] animData = anim.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- int lastFrameTime = MinimumFrameTime;
- if (animData.Length <= 0)
- {
- AddSingleFrames();
- return;
- }
-
- 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]);
- AddFrame(currentFrameIndex, currentFrameTime);
- lastFrameTime = currentFrameTime;
- }
- }
-
private void CheckTextureIndex(int index)
{
if (!_textures.IndexInRange(index))
throw new ArgumentOutOfRangeException(nameof(index));
}
- public Frame AddFrame(int textureIndex) => AddFrame(textureIndex, MinimumFrameTime);
public Frame AddFrame(int textureIndex, int frameTime)
{
CheckTextureIndex(textureIndex);
@@ -132,11 +94,11 @@ namespace PckStudio.Internal
return frame;
}
- private void AddSingleFrames()
+ private void AddTexturesAsFrames(int frameTime)
{
for (int i = 0; i < TextureCount; i++)
{
- AddFrame(i);
+ AddFrame(i, frameTime);
}
}
@@ -205,22 +167,6 @@ namespace PckStudio.Internal
SetFrame(frameIndex, new Frame(_textures[textureIndex], frameTime));
}
- public string BuildAnim()
- {
- StringBuilder stringBuilder = new StringBuilder(Interpolate ? "#" : string.Empty);
- foreach (Frame frame in _frames)
- stringBuilder.Append($"{GetTextureIndex(frame.Texture)}*{frame.Ticks},");
- return stringBuilder.ToString(0, stringBuilder.Length - 1);
- }
-
- public Image BuildTexture()
- {
- if (_textures[0].Width != _textures[0].Height)
- throw new Exception("Invalid size");
-
- return _textures.Combine(ImageLayoutDirection.Vertical);
- }
-
internal void SetFrameTicks(int ticks)
{
lock(_syncLock)
diff --git a/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs b/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs
index 3c0c0e54..62086e22 100644
--- a/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs
+++ b/PCK-Studio/Internal/Deserializer/AnimationDeserializer.cs
@@ -23,8 +23,9 @@ namespace PckStudio.Internal.Deserializer
{
Image texture = asset.GetTexture();
IEnumerable frameTextures = texture.Split(ImageLayoutDirection.Vertical);
- var _animation = new Animation(frameTextures, asset.GetProperty("ANIM"));
- return _animation;
+ Animation animation = new Animation(frameTextures);
+ animation.ApplyAnim(asset.GetProperty("ANIM"));
+ return animation;
}
return Animation.CreateEmpty();
}
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 3/3] 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;
+ }
}
}