mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-19 19:31:59 +00:00
Add IPckSerializer and IPckDeserializer and Update Animation/AnimationEditor
This commit is contained in:
@@ -9,6 +9,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OMI.Formats.Pck;
|
||||
using OMI.Workers;
|
||||
using PckStudio.Interfaces;
|
||||
using PckStudio.IO.TGA;
|
||||
|
||||
namespace PckStudio.Extensions
|
||||
@@ -45,6 +46,22 @@ namespace PckStudio.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
internal static T Get<T>(this PckFileData file, IPckDeserializer<T> deserializer)
|
||||
{
|
||||
return deserializer.Deserialize(file);
|
||||
}
|
||||
|
||||
internal static T Get<T>(this PckFileData file, IDataFormatReader<T> deserializer) where T : class
|
||||
{
|
||||
using var ms = new MemoryStream(file.Data);
|
||||
return deserializer.FromStream(ms);
|
||||
}
|
||||
|
||||
internal static void SetData<T>(this PckFileData file, T obj, IPckFileSerializer<T> serializer)
|
||||
{
|
||||
serializer.Serialize(obj, ref file);
|
||||
}
|
||||
|
||||
internal static void SetData(this PckFileData file, IDataFormatWriter writer)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace PckStudio.Forms.Additional_Popups.Animation
|
||||
{
|
||||
internal partial class ChangeTile : MetroForm
|
||||
{
|
||||
string selectedTile = "";
|
||||
AnimationCategory category = AnimationCategory.Blocks;
|
||||
private JsonTileInfo selectedTile;
|
||||
private ResourceCategory category = ResourceCategory.BlockAnimation;
|
||||
|
||||
public string SelectedTile => selectedTile;
|
||||
public AnimationCategory Category => category;
|
||||
public JsonTileInfo SelectedTile => selectedTile;
|
||||
public ResourceCategory Category => category;
|
||||
|
||||
List<TreeNode> treeViewBlockCache = new List<TreeNode>();
|
||||
List<TreeNode> treeViewItemCache = new List<TreeNode>();
|
||||
@@ -31,8 +31,8 @@ namespace PckStudio.Forms.Additional_Popups.Animation
|
||||
private void InitializeTreeviews()
|
||||
{
|
||||
Profiler.Start();
|
||||
GetTileDataToView(AnimationCategory.Blocks, treeViewBlocks.Nodes, treeViewBlockCache.Add);
|
||||
GetTileDataToView(AnimationCategory.Items, treeViewItems.Nodes, treeViewItemCache.Add);
|
||||
GetTileDataToView(ResourceCategory.BlockAnimation, treeViewBlocks.Nodes, treeViewBlockCache.Add);
|
||||
GetTileDataToView(ResourceCategory.ItemAnimation, treeViewItems.Nodes, treeViewItemCache.Add);
|
||||
Profiler.Stop();
|
||||
}
|
||||
|
||||
@@ -40,19 +40,19 @@ namespace PckStudio.Forms.Additional_Popups.Animation
|
||||
{
|
||||
if (e.Node.Tag is JsonTileInfo tileData)
|
||||
{
|
||||
selectedTile = tileData.InternalName;
|
||||
selectedTile = tileData;
|
||||
category = e.Node.TreeView == treeViewItems
|
||||
? AnimationCategory.Items
|
||||
: AnimationCategory.Blocks;
|
||||
? ResourceCategory.ItemAnimation
|
||||
: ResourceCategory.BlockAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetTileDataToView(AnimationCategory key, TreeNodeCollection collection, Action<TreeNode> additionalAction)
|
||||
private void GetTileDataToView(ResourceCategory key, TreeNodeCollection collection, Action<TreeNode> additionalAction)
|
||||
{
|
||||
List<JsonTileInfo> textureInfos = key switch
|
||||
{
|
||||
AnimationCategory.Blocks => Tiles.BlockTileInfos,
|
||||
AnimationCategory.Items => Tiles.ItemTileInfos,
|
||||
ResourceCategory.BlockAnimation => Tiles.BlockTileInfos,
|
||||
ResourceCategory.ItemAnimation => Tiles.ItemTileInfos,
|
||||
_ => throw new InvalidOperationException(nameof(key))
|
||||
};
|
||||
Profiler.Start();
|
||||
@@ -126,7 +126,7 @@ namespace PckStudio.Forms.Additional_Popups.Animation
|
||||
|
||||
private void AcceptBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedTile))
|
||||
if (string.IsNullOrEmpty(selectedTile.InternalName))
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
return;
|
||||
|
||||
13
PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs
generated
13
PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs
generated
@@ -48,7 +48,6 @@
|
||||
this.gifToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.bulkAnimationSpeedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.changeTileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.frameTimeandTicksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.howToInterpolation = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -215,8 +214,7 @@
|
||||
// editToolStripMenuItem
|
||||
//
|
||||
this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.bulkAnimationSpeedToolStripMenuItem,
|
||||
this.changeTileToolStripMenuItem});
|
||||
this.bulkAnimationSpeedToolStripMenuItem});
|
||||
this.editToolStripMenuItem.ForeColor = System.Drawing.Color.White;
|
||||
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
|
||||
this.editToolStripMenuItem.Size = new System.Drawing.Size(46, 20);
|
||||
@@ -229,13 +227,6 @@
|
||||
this.bulkAnimationSpeedToolStripMenuItem.Text = "Set Bulk Animation Speed";
|
||||
this.bulkAnimationSpeedToolStripMenuItem.Click += new System.EventHandler(this.bulkAnimationSpeedToolStripMenuItem_Click);
|
||||
//
|
||||
// changeTileToolStripMenuItem
|
||||
//
|
||||
this.changeTileToolStripMenuItem.Name = "changeTileToolStripMenuItem";
|
||||
this.changeTileToolStripMenuItem.Size = new System.Drawing.Size(210, 22);
|
||||
this.changeTileToolStripMenuItem.Text = "Change Tile";
|
||||
this.changeTileToolStripMenuItem.Click += new System.EventHandler(this.changeTileToolStripMenuItem_Click);
|
||||
//
|
||||
// helpToolStripMenuItem
|
||||
//
|
||||
this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@@ -337,7 +328,6 @@
|
||||
this.animationPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.animationPictureBox.TabIndex = 16;
|
||||
this.animationPictureBox.TabStop = false;
|
||||
this.animationPictureBox.UseBlendColor = false;
|
||||
//
|
||||
// AnimationEditor
|
||||
//
|
||||
@@ -382,7 +372,6 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem bulkAnimationSpeedToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem changeTileToolStripMenuItem;
|
||||
private MetroFramework.Controls.MetroLabel tileLabel;
|
||||
private System.Windows.Forms.ToolStripMenuItem howToInterpolation;
|
||||
private System.Windows.Forms.ToolStripMenuItem editorControlsToolStripMenuItem;
|
||||
|
||||
@@ -40,35 +40,27 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
public partial class AnimationEditor : MetroForm
|
||||
{
|
||||
public Animation Result => _animation;
|
||||
|
||||
private Animation _animation;
|
||||
|
||||
private string _tileName = string.Empty;
|
||||
|
||||
public string FinalPath => $"res/textures/{_animation.CategoryString}/{_tileName}.png";
|
||||
|
||||
private static readonly string[] specialTileNames = { "clock", "compass" };
|
||||
|
||||
private static bool IsSpecialTile(string name)
|
||||
{
|
||||
return name.ToLower().EqualsAny(specialTileNames);
|
||||
}
|
||||
|
||||
private bool _isSpecialTile;
|
||||
private AnimationEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
toolStripSeparator1.Visible = saveToolStripMenuItem1.Visible = !Settings.Default.AutoSaveChanges;
|
||||
}
|
||||
|
||||
internal AnimationEditor(Animation animation, string name)
|
||||
internal AnimationEditor(Animation animation, string displayName, bool isSpecialTile = false)
|
||||
: this()
|
||||
{
|
||||
_ = animation ?? throw new ArgumentNullException(nameof(animation));
|
||||
_animation = animation;
|
||||
_tileName = name;
|
||||
tileLabel.Text = displayName;
|
||||
_isSpecialTile = isSpecialTile;
|
||||
}
|
||||
|
||||
internal AnimationEditor(Animation animation, string name, Color blendColor)
|
||||
: this(animation, name)
|
||||
internal AnimationEditor(Animation animation, string displayName, Color blendColor)
|
||||
: this(animation, displayName)
|
||||
{
|
||||
animationPictureBox.UseBlendColor = true;
|
||||
animationPictureBox.BlendColor = blendColor;
|
||||
@@ -79,15 +71,12 @@ namespace PckStudio.Forms.Editor
|
||||
bulkAnimationSpeedToolStripMenuItem.Enabled =
|
||||
importToolStripMenuItem.Enabled =
|
||||
exportAsToolStripMenuItem.Enabled =
|
||||
changeTileToolStripMenuItem.Enabled =
|
||||
InterpolationCheckbox.Visible = !IsSpecialTile(_tileName);
|
||||
InterpolationCheckbox.Visible = !_isSpecialTile;
|
||||
}
|
||||
|
||||
private void AnimationEditor_Load(object sender, EventArgs e)
|
||||
{
|
||||
ValidateToolStrip();
|
||||
|
||||
SetTileLabel();
|
||||
LoadAnimationTreeView();
|
||||
}
|
||||
|
||||
@@ -170,7 +159,7 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!IsSpecialTile(_tileName) && _animation is not null && _animation.FrameCount > 0)
|
||||
if (!_isSpecialTile && _animation is not null && _animation.FrameCount > 0)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
return;
|
||||
@@ -279,7 +268,7 @@ namespace PckStudio.Forms.Editor
|
||||
diag.SaveBtn.Text = "Add";
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
_animation.AddFrame(diag.FrameTextureIndex, IsSpecialTile(_tileName) ? Animation.MinimumFrameTime : diag.FrameTime);
|
||||
_animation.AddFrame(diag.FrameTextureIndex, _isSpecialTile ? Animation.MinimumFrameTime : diag.FrameTime);
|
||||
UpdateTreeView();
|
||||
}
|
||||
}
|
||||
@@ -336,8 +325,8 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
var img = Image.FromFile(textureFile);
|
||||
JObject mcmeta = JObject.Parse(File.ReadAllText(fileDialog.FileName));
|
||||
Animation javaAnimation = AnimationHelper.GetAnimationFromJavaAnimation(mcmeta, img);
|
||||
javaAnimation.Category = _animation.Category;
|
||||
Animation javaAnimation = AnimationDeserializer.DefaultDeserializer.DeserializeJavaAnimation(mcmeta, img);
|
||||
//javaAnimation.Category = _animation.Category;
|
||||
_animation = javaAnimation;
|
||||
LoadAnimationTreeView();
|
||||
}
|
||||
@@ -348,36 +337,7 @@ namespace PckStudio.Forms.Editor
|
||||
}
|
||||
}
|
||||
|
||||
private void changeTileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopAnimation();
|
||||
using (ChangeTile diag = new ChangeTile())
|
||||
{
|
||||
if (diag.ShowDialog(this) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"{diag.SelectedTile}");
|
||||
_animation.Category = diag.Category;
|
||||
_tileName = diag.SelectedTile;
|
||||
|
||||
ValidateToolStrip();
|
||||
|
||||
SetTileLabel();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTileLabel()
|
||||
{
|
||||
var textureInfos = _animation.Category switch
|
||||
{
|
||||
AnimationCategory.Blocks => Tiles.BlockTileInfos,
|
||||
AnimationCategory.Items => Tiles.ItemTileInfos,
|
||||
_ => throw new ArgumentOutOfRangeException(_animation.Category.ToString())
|
||||
};
|
||||
tileLabel.Text = textureInfos.FirstOrDefault(p => p.InternalName == _tileName)?.DisplayName ?? _tileName;
|
||||
}
|
||||
|
||||
private void exportJavaAnimationToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
private void exportJavaAnimationToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog fileDialog = new SaveFileDialog();
|
||||
fileDialog.Title = "Please choose where you want to save your new animation";
|
||||
@@ -466,11 +426,8 @@ namespace PckStudio.Forms.Editor
|
||||
textures.Add(new Bitmap(gif, oldResolution, oldResolution));
|
||||
}
|
||||
|
||||
var animCat = _animation.Category;
|
||||
|
||||
_animation = new Animation(textures, string.Empty);
|
||||
_animation = new Animation(textures);
|
||||
_animation.Interpolate = InterpolationCheckbox.Checked;
|
||||
_animation.Category = animCat;
|
||||
LoadAnimationTreeView();
|
||||
}
|
||||
|
||||
@@ -493,7 +450,7 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
var fileDialog = new SaveFileDialog()
|
||||
{
|
||||
FileName = _tileName,
|
||||
FileName = tileLabel.Text,
|
||||
Filter = "GIF file|*.gif"
|
||||
};
|
||||
if (fileDialog.ShowDialog(this) != DialogResult.OK)
|
||||
|
||||
@@ -35,71 +35,19 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
public partial class GameRuleFileEditor : MetroFramework.Forms.MetroForm
|
||||
{
|
||||
private PckFileData _pckfile;
|
||||
private GameRuleFile _file;
|
||||
private GameRuleFile.CompressionType compressionType;
|
||||
private GameRuleFile.CompressionLevel compressionLevel;
|
||||
|
||||
private const string use_zlib = "Wii U, PS Vita";
|
||||
private const string use_deflate = "PS3";
|
||||
private const string use_xmem = "Xbox 360";
|
||||
public GameRuleFile Result => _file;
|
||||
|
||||
public GameRuleFileEditor()
|
||||
private GameRuleFileEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
PromptForCompressionType();
|
||||
saveToolStripMenuItem.Visible = !Settings.Default.AutoSaveChanges;
|
||||
}
|
||||
|
||||
private void PromptForCompressionType()
|
||||
public GameRuleFileEditor(GameRuleFile gameRuleFile) : this()
|
||||
{
|
||||
ItemSelectionPopUp dialog = new ItemSelectionPopUp(use_zlib, use_deflate, use_xmem);
|
||||
dialog.LabelText = "Type";
|
||||
dialog.ButtonText = "Ok";
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
switch(dialog.SelectedItem)
|
||||
{
|
||||
case use_zlib:
|
||||
wiiUPSVitaToolStripMenuItem.Checked = true;
|
||||
break;
|
||||
case use_deflate:
|
||||
pS3ToolStripMenuItem.Checked = true;
|
||||
break;
|
||||
case use_xmem:
|
||||
xbox360ToolStripMenuItem.Checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GameRuleFileEditor(PckFileData file) : this()
|
||||
{
|
||||
_pckfile = file;
|
||||
using (var stream = new MemoryStream(file.Data))
|
||||
{
|
||||
_file = OpenGameRuleFile(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public GameRuleFileEditor(Stream stream) : this()
|
||||
{
|
||||
_file = OpenGameRuleFile(stream);
|
||||
}
|
||||
|
||||
private GameRuleFile OpenGameRuleFile(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
var reader = new GameRuleFileReader(compressionType);
|
||||
return reader.FromStream(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
MessageBox.Show("Faild to open .grf/.grh file");
|
||||
}
|
||||
return default!;
|
||||
_file = gameRuleFile;
|
||||
}
|
||||
|
||||
private void OnLoad(object sender, EventArgs e)
|
||||
@@ -267,77 +215,55 @@ namespace PckStudio.Forms.Editor
|
||||
MessageBox.Show("World grf saving is currently unsupported");
|
||||
return;
|
||||
}
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
try
|
||||
{
|
||||
_pckfile?.SetData(new GameRuleFileWriter(_file));
|
||||
DialogResult = DialogResult.OK;
|
||||
MessageBox.Show("Saved!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
MessageBox.Show($"Failed to save grf file\n{ex.Message}", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
DialogResult = DialogResult.OK;
|
||||
MessageBox.Show("Saved!");
|
||||
}
|
||||
|
||||
private void openToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog dialog = new OpenFileDialog();
|
||||
dialog.Filter = "Game Rule File|*.grf";
|
||||
PromptForCompressionType();
|
||||
if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
using (var fs = File.OpenRead(dialog.FileName))
|
||||
{
|
||||
_file = OpenGameRuleFile(fs);
|
||||
ReloadGameRuleTree();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void noneToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionLevel = GameRuleFile.CompressionLevel.None;
|
||||
_file.Header.CompressionLevel = GameRuleFile.CompressionLevel.None;
|
||||
}
|
||||
|
||||
private void compressedToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionLevel = GameRuleFile.CompressionLevel.Compressed;
|
||||
_file.Header.CompressionLevel = GameRuleFile.CompressionLevel.Compressed;
|
||||
}
|
||||
|
||||
private void compressedRLEToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionLevel = GameRuleFile.CompressionLevel.CompressedRle;
|
||||
_file.Header.CompressionLevel = GameRuleFile.CompressionLevel.CompressedRle;
|
||||
}
|
||||
|
||||
private void compressedRLECRCToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionLevel = GameRuleFile.CompressionLevel.CompressedRleCrc;
|
||||
_file.Header.CompressionLevel = GameRuleFile.CompressionLevel.CompressedRleCrc;
|
||||
}
|
||||
|
||||
private void wiiUPSVitaToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionType = GameRuleFile.CompressionType.Zlib;
|
||||
_file.Header.CompressionType = GameRuleFile.CompressionType.Zlib;
|
||||
}
|
||||
|
||||
private void pS3ToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionType = GameRuleFile.CompressionType.Deflate;
|
||||
_file.Header.CompressionType = GameRuleFile.CompressionType.Deflate;
|
||||
}
|
||||
|
||||
private void xbox360ToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is ToolStripRadioButtonMenuItem radioButton && radioButton.Checked)
|
||||
compressionType = GameRuleFile.CompressionType.XMem;
|
||||
_file.Header.CompressionType = GameRuleFile.CompressionType.XMem;
|
||||
}
|
||||
|
||||
private void GameRuleFileEditor_FormClosing(object sender, FormClosingEventArgs e)
|
||||
|
||||
@@ -31,6 +31,7 @@ using OMI.Workers.Color;
|
||||
|
||||
using PckStudio.Extensions;
|
||||
using PckStudio.Helper;
|
||||
using PckStudio.Internal;
|
||||
using PckStudio.Internal.Json;
|
||||
|
||||
namespace PckStudio.Forms.Editor
|
||||
@@ -248,7 +249,7 @@ namespace PckStudio.Forms.Editor
|
||||
hasAnimation &&
|
||||
animationFile.Size > 0)
|
||||
{
|
||||
var animation = AnimationHelper.GetAnimationFromFile(animationFile);
|
||||
var animation = animationFile.Get(AnimationDeserializer.DefaultDeserializer);
|
||||
selectTilePictureBox.Start(animation);
|
||||
}
|
||||
}
|
||||
@@ -532,7 +533,7 @@ namespace PckStudio.Forms.Editor
|
||||
PckFileType.TextureFile
|
||||
);
|
||||
|
||||
var animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
var animation = file.Get(AnimationDeserializer.DefaultDeserializer);
|
||||
|
||||
var animationEditor = new AnimationEditor(animation, _selectedTile.Tile.InternalName, GetBlendColor());
|
||||
if (animationEditor.ShowDialog() != DialogResult.OK)
|
||||
@@ -540,7 +541,7 @@ namespace PckStudio.Forms.Editor
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationHelper.SaveAnimationToFile(file, animation);
|
||||
file.SetData(animationEditor.Result, AnimationSerializer.DefaultSerializer);
|
||||
// so animations can automatically update upon saving
|
||||
SelectedIndex = _selectedTile.Index;
|
||||
}
|
||||
|
||||
14
PCK-Studio/Interfaces/IPckDeserializer.cs
Normal file
14
PCK-Studio/Interfaces/IPckDeserializer.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OMI.Formats.Pck;
|
||||
|
||||
namespace PckStudio.Interfaces
|
||||
{
|
||||
internal interface IPckDeserializer<T>
|
||||
{
|
||||
public T Deserialize(PckFileData file);
|
||||
}
|
||||
}
|
||||
14
PCK-Studio/Interfaces/IPckFileSerializer.cs
Normal file
14
PCK-Studio/Interfaces/IPckFileSerializer.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OMI.Formats.Pck;
|
||||
|
||||
namespace PckStudio.Interfaces
|
||||
{
|
||||
internal interface IPckFileSerializer<T>
|
||||
{
|
||||
public void Serialize(T obj, ref PckFileData file);
|
||||
}
|
||||
}
|
||||
@@ -25,44 +25,24 @@ using System.Linq;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal sealed class Animation
|
||||
public sealed class Animation
|
||||
{
|
||||
public const int MinimumFrameTime = 1;
|
||||
|
||||
public const int GameTickInMilliseconds = 50;
|
||||
|
||||
public static Animation Empty(AnimationCategory category)
|
||||
{
|
||||
var animation = new Animation(Array.Empty<Image>(), string.Empty);
|
||||
animation.Category = category;
|
||||
return animation;
|
||||
}
|
||||
|
||||
public int FrameCount => frames.Count;
|
||||
|
||||
public int TextureCount => textures.Count;
|
||||
|
||||
public bool Interpolate { get; set; } = false;
|
||||
|
||||
|
||||
public AnimationCategory Category { get; set; }
|
||||
|
||||
public string CategoryString => GetCategoryName(Category);
|
||||
|
||||
public static string GetCategoryName(AnimationCategory category)
|
||||
{
|
||||
return category switch
|
||||
{
|
||||
AnimationCategory.Items => "items",
|
||||
AnimationCategory.Blocks => "blocks",
|
||||
_ => throw new ArgumentOutOfRangeException(category.ToString())
|
||||
};
|
||||
}
|
||||
|
||||
private readonly List<Image> textures;
|
||||
|
||||
private readonly IList<Frame> frames = new List<Frame>();
|
||||
|
||||
private object _syncLock = new object();
|
||||
|
||||
public Animation(IEnumerable<Image> textures)
|
||||
{
|
||||
this.textures = new List<Image>(textures);
|
||||
@@ -215,7 +195,7 @@ namespace PckStudio.Internal
|
||||
|
||||
public void SetFrame(int frameIndex, Frame frame)
|
||||
{
|
||||
lock(frames)
|
||||
lock(_syncLock)
|
||||
{
|
||||
frames[frameIndex] = frame;
|
||||
}
|
||||
@@ -245,7 +225,7 @@ namespace PckStudio.Internal
|
||||
|
||||
internal void SetFrameTicks(int ticks)
|
||||
{
|
||||
lock(frames)
|
||||
lock(_syncLock)
|
||||
{
|
||||
foreach (var frame in frames)
|
||||
{
|
||||
@@ -256,10 +236,15 @@ namespace PckStudio.Internal
|
||||
|
||||
internal void SwapFrames(int sourceIndex, int destinationIndex)
|
||||
{
|
||||
lock(frames)
|
||||
lock(_syncLock)
|
||||
{
|
||||
frames.Swap(sourceIndex, destinationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Animation CreateEmpty()
|
||||
{
|
||||
return new Animation(Array.Empty<Image>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,28 +2,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OMI.Formats.Pck;
|
||||
using PckStudio.Extensions;
|
||||
using PckStudio.Internal;
|
||||
using PckStudio.Interfaces;
|
||||
|
||||
namespace PckStudio.Helper
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal static class AnimationHelper
|
||||
internal sealed class AnimationDeserializer : IPckDeserializer<Animation>
|
||||
{
|
||||
internal static void SaveAnimationToFile(PckFileData file, Animation animation)
|
||||
{
|
||||
string anim = animation.BuildAnim();
|
||||
file.SetProperty("ANIM", anim);
|
||||
var texture = animation.BuildTexture();
|
||||
file.SetData(texture, ImageFormat.Png);
|
||||
}
|
||||
|
||||
internal static Animation GetAnimationFromFile(PckFileData file)
|
||||
public static readonly AnimationDeserializer DefaultDeserializer = new AnimationDeserializer();
|
||||
|
||||
public Animation Deserialize(PckFileData file)
|
||||
{
|
||||
_ = file ?? throw new ArgumentNullException(nameof(file));
|
||||
if (file.Size > 0)
|
||||
@@ -31,25 +24,20 @@ namespace PckStudio.Helper
|
||||
var texture = file.GetTexture();
|
||||
var frameTextures = texture.Split(ImageLayoutDirection.Vertical);
|
||||
var _animation = new Animation(frameTextures, file.GetProperty("ANIM"));
|
||||
_animation.Category = file.Filename.Split('/').Contains("items")
|
||||
? AnimationCategory.Items
|
||||
: AnimationCategory.Blocks;
|
||||
return _animation;
|
||||
}
|
||||
return Animation.Empty(file.Filename.Split('/').Contains("items")
|
||||
? AnimationCategory.Items
|
||||
: AnimationCategory.Blocks);
|
||||
return Animation.CreateEmpty();
|
||||
}
|
||||
|
||||
internal static Animation GetAnimationFromJavaAnimation(JObject jsonObject, Image texture)
|
||||
public Animation DeserializeJavaAnimation(JObject jsonObject, Image texture)
|
||||
{
|
||||
var textures = texture.Split(ImageLayoutDirection.Vertical);
|
||||
Animation result = new Animation(textures);
|
||||
if (jsonObject["animation"] is not JToken animation)
|
||||
return result;
|
||||
|
||||
|
||||
int frameTime = Animation.MinimumFrameTime;
|
||||
|
||||
|
||||
if (animation["frametime"] is JToken frametime_token && frametime_token.Type == JTokenType.Integer)
|
||||
frameTime = (int)frametime_token;
|
||||
|
||||
@@ -60,12 +48,12 @@ namespace PckStudio.Helper
|
||||
{
|
||||
foreach (JToken frame in frames_token.Children())
|
||||
{
|
||||
if (frame.Type == JTokenType.Object &&
|
||||
if (frame.Type == JTokenType.Object &&
|
||||
frame["index"] is JToken frame_index &&
|
||||
frame_index.Type == JTokenType.Integer &&
|
||||
frame["time"] is JToken frame_time &&
|
||||
frame_time.Type == JTokenType.Integer)
|
||||
{
|
||||
{
|
||||
Debug.WriteLine("Index: {0}, Time: {1}", frame_index, frame_time);
|
||||
result.AddFrame((int)frame_index, (int)frame_time);
|
||||
}
|
||||
28
PCK-Studio/Internal/AnimationSerializer.cs
Normal file
28
PCK-Studio/Internal/AnimationSerializer.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OMI.Formats.Pck;
|
||||
using PckStudio.Extensions;
|
||||
using PckStudio.Interfaces;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal sealed class AnimationSerializer : IPckFileSerializer<Animation>
|
||||
{
|
||||
public static readonly AnimationSerializer DefaultSerializer = new AnimationSerializer();
|
||||
|
||||
public void Serialize(Animation animation, ref PckFileData file)
|
||||
{
|
||||
string anim = animation.BuildAnim();
|
||||
file.SetProperty("ANIM", anim);
|
||||
var texture = animation.BuildTexture();
|
||||
file.SetData(texture, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal enum AnimationCategory
|
||||
internal enum ResourceCategory
|
||||
{
|
||||
Items,
|
||||
Blocks
|
||||
Unknown = -1,
|
||||
ItemAnimation,
|
||||
BlockAnimation
|
||||
}
|
||||
}
|
||||
35
PCK-Studio/Internal/ResourceLocation.cs
Normal file
35
PCK-Studio/Internal/ResourceLocation.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal class ResourceLocation
|
||||
{
|
||||
public static string GetPathFromCategory(ResourceCategory category)
|
||||
{
|
||||
return category switch
|
||||
{
|
||||
ResourceCategory.ItemAnimation => "res/textures/items",
|
||||
ResourceCategory.BlockAnimation => "res/textures/blocks",
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
|
||||
public static ResourceCategory GetCategoryFromPath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || !path.StartsWith("res/"))
|
||||
return ResourceCategory.Unknown;
|
||||
|
||||
if (path.StartsWith("res/textures/items"))
|
||||
return ResourceCategory.ItemAnimation;
|
||||
|
||||
if (path.StartsWith("res/textures/blocks"))
|
||||
return ResourceCategory.BlockAnimation;
|
||||
|
||||
return ResourceCategory.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ using PckStudio.Popups;
|
||||
using PckStudio.Classes.Utils;
|
||||
using PckStudio.Helper;
|
||||
using System.Text.RegularExpressions;
|
||||
using PckStudio.Internal.Json;
|
||||
|
||||
namespace PckStudio
|
||||
{
|
||||
@@ -511,16 +512,29 @@ namespace PckStudio
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.Filename.StartsWith("res/textures/blocks/") && !file.Filename.StartsWith("res/textures/items/"))
|
||||
if (!file.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation)) &&
|
||||
!file.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.BlockAnimation)))
|
||||
return;
|
||||
Animation animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
using (AnimationEditor animationEditor = new AnimationEditor(animation, Path.GetFileNameWithoutExtension(file.Filename)))
|
||||
|
||||
Animation animation = file.Get(AnimationDeserializer.DefaultDeserializer);
|
||||
string filename = Path.GetFileNameWithoutExtension(file.Filename);
|
||||
|
||||
var textureInfos = ResourceLocation.GetCategoryFromPath(file.Filename) switch
|
||||
{
|
||||
ResourceCategory.BlockAnimation => Tiles.BlockTileInfos,
|
||||
ResourceCategory.ItemAnimation => Tiles.ItemTileInfos,
|
||||
_ => Array.Empty<JsonTileInfo>().ToList()
|
||||
};
|
||||
string displayname = textureInfos.FirstOrDefault(p => p.InternalName == filename)?.DisplayName ?? filename;
|
||||
|
||||
string[] specialTileNames = { "clock", "compass" };
|
||||
|
||||
using (AnimationEditor animationEditor = new AnimationEditor(animation, displayname, filename.ToLower().EqualsAny(specialTileNames)))
|
||||
{
|
||||
if (animationEditor.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
wasModified = true;
|
||||
file.Filename = animationEditor.FinalPath;
|
||||
AnimationHelper.SaveAnimationToFile(file, animation);
|
||||
file.SetData(animationEditor.Result, AnimationSerializer.DefaultSerializer);
|
||||
BuildMainTreeView();
|
||||
}
|
||||
}
|
||||
@@ -528,9 +542,33 @@ namespace PckStudio
|
||||
|
||||
private void HandleGameRuleFile(PckFileData file)
|
||||
{
|
||||
using GameRuleFileEditor grfEditor = new GameRuleFileEditor(file);
|
||||
wasModified = grfEditor.ShowDialog(this) == DialogResult.OK;
|
||||
UpdateRichPresence();
|
||||
const string use_deflate = "PS3";
|
||||
const string use_xmem = "Xbox 360";
|
||||
const string use_zlib = "Wii U, PS Vita";
|
||||
|
||||
ItemSelectionPopUp dialog = new ItemSelectionPopUp(use_zlib, use_deflate, use_xmem);
|
||||
dialog.LabelText = "Type";
|
||||
dialog.ButtonText = "Ok";
|
||||
if (dialog.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var compressiontype = dialog.SelectedItem switch
|
||||
{
|
||||
use_deflate => GameRuleFile.CompressionType.Deflate,
|
||||
use_xmem => GameRuleFile.CompressionType.XMem,
|
||||
use_zlib => GameRuleFile.CompressionType.Zlib,
|
||||
_ => GameRuleFile.CompressionType.Unknown
|
||||
};
|
||||
|
||||
GameRuleFile grf = file.Get(new GameRuleFileReader(compressiontype));
|
||||
|
||||
using GameRuleFileEditor grfEditor = new GameRuleFileEditor(grf);
|
||||
if (grfEditor.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
file.SetData(new GameRuleFileWriter(grfEditor.Result));
|
||||
wasModified = true;
|
||||
UpdateRichPresence();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAudioFile(PckFileData file)
|
||||
@@ -636,7 +674,8 @@ namespace PckStudio
|
||||
Debug.WriteLine(string.Format("An error occured of type: {0} with message: {1}", ex.GetType(), ex.Message), "Exception");
|
||||
}
|
||||
|
||||
if ((file.Filename.StartsWith("res/textures/blocks/") || file.Filename.StartsWith("res/textures/items/")) &&
|
||||
if ((file.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation)) ||
|
||||
file.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.BlockAnimation))) &&
|
||||
file.Filetype == PckFileType.TextureFile
|
||||
&& !file.IsMipmappedFile())
|
||||
{
|
||||
@@ -832,11 +871,11 @@ namespace PckStudio
|
||||
/// <returns>True if the remove should be canceled, otherwise False</returns>
|
||||
private bool BeforeFileRemove(PckFileData file)
|
||||
{
|
||||
string itemPath = "res/textures/items/";
|
||||
string itemPath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation);
|
||||
|
||||
// warn the user about deleting compass.png and clock.png
|
||||
if (file.Filetype == PckFileType.TextureFile &&
|
||||
(file.Filename == itemPath + "compass.png" || file.Filename == itemPath + "clock.png"))
|
||||
(file.Filename == itemPath + "/compass.png" || file.Filename == itemPath + "/clock.png"))
|
||||
{
|
||||
if (MessageBox.Show("Are you sure want to delete this file? If \"compass.png\" or \"clock.png\" are missing, your game will crash upon loading this pack.", "Warning",
|
||||
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
|
||||
@@ -1013,24 +1052,20 @@ namespace PckStudio
|
||||
if (diag.ShowDialog(this) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
if (currentPCK.Contains($"res/textures/{Animation.GetCategoryName(diag.Category)}/{diag.SelectedTile}.png", PckFileType.TextureFile))
|
||||
string animationFilepath = $"{ResourceLocation.GetPathFromCategory(diag.Category)}/{diag.SelectedTile}.png";
|
||||
|
||||
if (currentPCK.Contains(animationFilepath, PckFileType.TextureFile))
|
||||
{
|
||||
MessageBox.Show($"{diag.SelectedTile} is already present.", "File already present");
|
||||
return;
|
||||
}
|
||||
|
||||
var file = new PckFileData(
|
||||
$"res/textures/{Animation.GetCategoryName(diag.Category)}/{diag.SelectedTile}.png",
|
||||
PckFileType.TextureFile);
|
||||
|
||||
Animation animation = AnimationHelper.GetAnimationFromFile(file);
|
||||
|
||||
using AnimationEditor animationEditor = new AnimationEditor(animation, diag.SelectedTile);
|
||||
using AnimationEditor animationEditor = new AnimationEditor(Animation.CreateEmpty(), diag.SelectedTile.DisplayName, diag.SelectedTile.InternalName.EqualsAny("clock", "compass"));
|
||||
if (animationEditor.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
wasModified = true;
|
||||
AnimationHelper.SaveAnimationToFile(file, animation);
|
||||
currentPCK.AddFile(file);
|
||||
PckFileData file = currentPCK.CreateNewFile(animationFilepath, PckFileType.TextureFile);
|
||||
file.SetData(animationEditor.Result, AnimationSerializer.DefaultSerializer);
|
||||
BuildMainTreeView();
|
||||
ReloadMetaTreeView();
|
||||
}
|
||||
|
||||
@@ -138,9 +138,13 @@
|
||||
<Compile Include="Extensions\LocFileExtensions.cs" />
|
||||
<Compile Include="Extensions\PckFileDataExtensions.cs" />
|
||||
<Compile Include="Extensions\TreeNodeExtensions.cs" />
|
||||
<Compile Include="Helper\AnimationHelper.cs" />
|
||||
<Compile Include="Internal\AnimationCategory.cs" />
|
||||
<Compile Include="Internal\AnimationSerializer.cs" />
|
||||
<Compile Include="Internal\AnimationDeserializer.cs" />
|
||||
<Compile Include="Interfaces\IPckDeserializer.cs" />
|
||||
<Compile Include="Interfaces\IPckFileSerializer.cs" />
|
||||
<Compile Include="Internal\ResourceCategory.cs" />
|
||||
<Compile Include="Internal\CommitInfo.cs" />
|
||||
<Compile Include="Internal\ResourceLocation.cs" />
|
||||
<Compile Include="Internal\SkinAnimFlag.cs" />
|
||||
<Compile Include="Internal\SkinAnimMask.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
|
||||
Reference in New Issue
Block a user