diff --git a/PCK-Studio/Extensions/PckFileDataExtensions.cs b/PCK-Studio/Extensions/PckFileDataExtensions.cs
index 9488fdcb..5adaa1b0 100644
--- a/PCK-Studio/Extensions/PckFileDataExtensions.cs
+++ b/PCK-Studio/Extensions/PckFileDataExtensions.cs
@@ -7,8 +7,10 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using OMI.Formats.Languages;
using OMI.Formats.Pck;
using OMI.Workers;
+using PckStudio.Internal;
namespace PckStudio.Extensions
{
@@ -26,18 +28,107 @@ namespace PckStudio.Extensions
{
throw new Exception("File is not suitable to contain image data.");
}
- using (var stream = new MemoryStream(file.Data))
+ using var stream = new MemoryStream(file.Data);
+
+ try
{
- try
- {
- return Image.FromStream(stream);
- }
- catch(Exception ex)
- {
- Trace.WriteLine($"Failed to read image from pck file data({file.Filename}).", category: nameof(PckFileDataExtensions) + "." + nameof(GetTexture));
- Debug.WriteLine(ex.Message);
- return EmptyImage;
- }
+ return Image.FromStream(stream);
+ }
+ catch (Exception ex)
+ {
+ Trace.TraceError($"Failed to read image from pck file data({file.Filename}).");
+ Debug.WriteLine(ex.Message);
+ return EmptyImage;
+ }
+ }
+
+ ///
+ /// Tries to get the skin id of the skin
+ ///
+ ///
+ /// Non-zero base number on success, otherwise 0
+ ///
+ internal static int GetSkinId(this PckFileData file)
+ {
+ if (file.Filetype != PckFileType.SkinFile)
+ throw new InvalidOperationException("File is not a skin file");
+
+ string filename = Path.GetFileNameWithoutExtension(file.Filename);
+ if (!filename.StartsWith("dlcskin"))
+ {
+ Trace.TraceWarning($"[{nameof(GetSkin)}] File does not start with 'dlcskin'");
+ return 0;
+ }
+
+ int skinId = 0;
+ if (!int.TryParse(filename.Substring("dlcskin".Length), out skinId))
+ {
+ Trace.TraceWarning($"[{nameof(GetSkin)}] Failed to parse Skin Id");
+ }
+ return skinId;
+ }
+
+ internal static Skin GetSkin(this PckFileData file)
+ {
+ if (file.Filetype != PckFileType.SkinFile)
+ throw new InvalidOperationException("File is not a skin file");
+
+ if (file.Properties.Contains("CAPEPATH"))
+ Debug.WriteLine($"[{nameof(GetSkin)}] TODO: add cape texture/path.");
+
+ int skinId = file.GetSkinId();
+
+ string name = file.Properties.GetPropertyValue("DISPLAYNAME");
+ Image texture = file.GetTexture();
+ SkinANIM anim = file.Properties.GetPropertyValue("ANIM", SkinANIM.FromString);
+ IEnumerable boxes = file.Properties.GetProperties("BOX").Select(kv => SkinBOX.FromString(kv.Value));
+ IEnumerable offsets = file.Properties.GetProperties("OFFSET").Select(kv => SkinPartOffset.FromString(kv.Value));
+ return new Skin(name, skinId, texture, anim, boxes, offsets);
+ }
+
+ internal static void SetSkin(this PckFileData file, Skin skin, LOCFile localizationFile)
+ {
+ if (file.Filetype != PckFileType.SkinFile)
+ throw new InvalidOperationException("File is not a skin file");
+
+ file.SetData(skin.Texture, ImageFormat.Png);
+
+ string skinId = skin.Id.ToString("d08");
+
+ // TODO: keep filepath
+ file.Filename = $"dlcskin{skinId}.png";
+
+ string skinLocKey = $"IDS_dlcskin{skinId}_DISPLAYNAME";
+ file.Properties.SetProperty("DISPLAYNAME", skin.Name);
+ file.Properties.SetProperty("DISPLAYNAMEID", skinLocKey);
+ localizationFile.AddLocKey(skinLocKey, skin.Name);
+
+ if (!string.IsNullOrEmpty(skin.Theme))
+ {
+ file.Properties.SetProperty("THEMENAME", skin.Theme);
+ file.Properties.SetProperty("THEMENAMEID", $"IDS_dlcskin{skinId}_THEMENAME");
+ localizationFile.AddLocKey($"IDS_dlcskin{skinId}_THEMENAME", skin.Theme);
+ }
+
+ if (skin.HasCape)
+ {
+ file.Properties.SetProperty("CAPEPATH", $"dlccape{skinId}.png");
+ }
+
+ file.Properties.SetProperty("ANIM", skin.ANIM.ToString());
+ file.Properties.SetProperty("GAME_FLAGS", "0x18");
+ file.Properties.SetProperty("FREE", "1");
+
+ file.Properties.RemoveAll(kv => kv.Key == "BOX");
+ file.Properties.RemoveAll(kv => kv.Key == "OFFSET");
+
+ foreach (SkinBOX box in skin.AdditionalBoxes)
+ {
+ file.Properties.Add(box.ToProperty());
+ }
+ foreach (SkinPartOffset offset in skin.PartOffsets)
+ {
+ file.Properties.Add(offset.ToProperty());
}
}
diff --git a/PCK-Studio/Extensions/SkinExtensions.cs b/PCK-Studio/Extensions/SkinExtensions.cs
new file mode 100644
index 00000000..e26dedba
--- /dev/null
+++ b/PCK-Studio/Extensions/SkinExtensions.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OMI.Formats.Languages;
+using OMI.Formats.Pck;
+using PckStudio.Internal;
+
+namespace PckStudio.Extensions
+{
+ internal static class SkinExtensions
+ {
+ public static PckFileData CreateFile(this Skin skin, LOCFile localizationFile)
+ {
+ string skinId = skin.Id.ToString("d08");
+ PckFileData skinFile = new PckFileData($"dlcskin{skinId}.png", PckFileType.SkinFile);
+
+ string skinLocKey = $"IDS_dlcskin{skinId}_DISPLAYNAME";
+ skinFile.Properties.Add("DISPLAYNAME", skin.Name);
+ skinFile.Properties.Add("DISPLAYNAMEID", skinLocKey);
+ localizationFile.AddLocKey(skinLocKey, skin.Name);
+
+ if (!string.IsNullOrEmpty(skin.Theme))
+ {
+ skinFile.Properties.Add("THEMENAME", skin.Theme);
+ skinFile.Properties.Add("THEMENAMEID", $"IDS_dlcskin{skinId}_THEMENAME");
+ localizationFile.AddLocKey($"IDS_dlcskin{skinId}_THEMENAME", skin.Theme);
+ }
+
+ if (skin.HasCape)
+ {
+ skinFile.Properties.Add("CAPEPATH", $"dlccape{skinId}.png");
+ }
+
+ skinFile.Properties.Add("ANIM", skin.ANIM);
+ skinFile.Properties.Add("GAME_FLAGS", "0x18");
+ skinFile.Properties.Add("FREE", "1");
+
+ foreach (SkinBOX box in skin.AdditionalBoxes)
+ {
+ skinFile.Properties.Add(box.ToProperty());
+ }
+ foreach (SkinPartOffset offset in skin.PartOffsets)
+ {
+ skinFile.Properties.Add(offset.ToProperty());
+ }
+
+ skinFile.SetData(skin.Texture, ImageFormat.Png);
+
+ return skinFile;
+ }
+
+ public static PckFileData CreateCapeFile(this Skin skin)
+ {
+ if (!skin.HasCape)
+ throw new InvalidOperationException("Skin does not contain a cape.");
+ string skinId = skin.Id.ToString("d08");
+ PckFileData capeFile = new PckFileData($"dlccape{skinId}.png", PckFileType.CapeFile);
+ capeFile.SetData(skin.CapeTexture, ImageFormat.Png);
+ return capeFile;
+ }
+ }
+}
diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs
index 55f32a05..686829b3 100644
--- a/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs
+++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs
@@ -437,7 +437,7 @@
this.Name = "CustomSkinEditor";
this.Style = MetroFramework.MetroColorStyle.Silver;
this.Theme = MetroFramework.MetroThemeStyle.Dark;
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.generateModel_FormClosing);
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CustomSkinEditor_FormClosing);
this.contextMenuStrip1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.SizeXUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.SizeYUpDown)).EndInit();
diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs
index ee67a740..32ef3e4c 100644
--- a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs
+++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs
@@ -21,10 +21,12 @@ namespace PckStudio.Forms.Editor
{
public partial class CustomSkinEditor : MetroForm
{
- private Image _previewImage;
public Image PreviewImage => _previewImage;
- private PckFileData _file;
+ public Skin ResultSkin => _skin;
+
+ private Image _previewImage;
+ private Skin _skin;
private Random rng;
private BindingSource skinPartListBindingSource;
@@ -36,35 +38,45 @@ namespace PckStudio.Forms.Editor
PixelOffsetMode = PixelOffsetMode.HighQuality,
};
- public CustomSkinEditor(PckFileData file)
+ private CustomSkinEditor()
{
InitializeComponent();
- _file = file;
rng = new Random();
}
+ public CustomSkinEditor(Skin skin) : this()
+ {
+ _skin = skin;
+ }
+
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
renderer3D1.InitializeGL();
- renderer3D1.OutlineColor = Color.DarkSlateBlue;
- if (_file.Size > 0)
+ if (_skin.Texture is not null)
{
- renderer3D1.Texture = _file.GetTexture();
+ renderer3D1.Texture = _skin.Texture;
}
- LoadModelData(_file.Properties);
+ renderer3D1.ANIM = _skin.ANIM;
+ renderer3D1.OutlineColor = Color.DarkSlateBlue;
+ LoadModelData();
}
- private void LoadModelData(PckFileProperties properties)
+ private void LoadModelData()
{
- renderer3D1.ANIM = properties.GetPropertyValue("ANIM", SkinANIM.FromString);
- var boxProperties = properties.GetProperties("BOX");
- var offsetProperties = properties.GetProperties("OFFSET");
+ var boxProperties = _skin.AdditionalBoxes;
+ var offsetProperties = _skin.PartOffsets;
- skinNameLabel.Text = properties.HasProperty("DISPLAYNAME") ? properties.GetPropertyValue("DISPLAYNAME") : "";
+ skinNameLabel.Text = _skin.Name;
- Array.ForEach(boxProperties, kv => renderer3D1.ModelData.Add(SkinBOX.FromString(kv.Value)));
- Array.ForEach(offsetProperties, kv => renderer3D1.SetPartOffset(SkinPartOffset.FromString(kv.Value)));
+ foreach (SkinBOX box in boxProperties)
+ {
+ renderer3D1.ModelData.Add(box);
+ }
+ foreach (SkinPartOffset offset in offsetProperties)
+ {
+ renderer3D1.SetPartOffset(offset);
+ }
skinPartListBindingSource = new BindingSource(renderer3D1.ModelData, null);
skinPartListBox.DataSource = skinPartListBindingSource;
@@ -128,22 +140,28 @@ namespace PckStudio.Forms.Editor
private void buttonDone_Click(object sender, EventArgs e)
{
- _file.Properties.RemoveAll(kv => kv.Key == "BOX");
- foreach (var part in renderer3D1.ModelData)
- {
- _file.Properties.Add("BOX", part);
- }
- _previewImage = renderer3D1.GetThumbnail();
+ //Debug.Fail("TODO: Implement");
+ _skin.AdditionalBoxes.Clear();
+ _skin.AdditionalBoxes.AddRange(renderer3D1.ModelData);
+
+ // TODO: Get part offset list/IEnumerable from renderer
+ //_skin.PartOffsets.Clear();
+ //_skin.PartOffsets.AddRange();
+
+ //_previewImage = renderer3D1.GetThumbnail();
DialogResult = DialogResult.OK;
}
+ // TODO
private void buttonExportModel_Click(object sender, EventArgs e)
{
- //SaveFileDialog saveFileDialog = new SaveFileDialog();
- //saveFileDialog.Filter = "Custom Skin Model File | *.CSM";
- //if (saveFileDialog.ShowDialog() != DialogResult.OK)
- // return;
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Title = "Save Model File";
+ saveFileDialog.Filter = "Custom Skin Model File (*.csm,*.CSM)|*.csm;*.CSM|" +
+ "Custom Skin Model Binary File (*.csmb)|*.csmb|";
+ if (saveFileDialog.ShowDialog() != DialogResult.OK)
+ return;
//string contents = "";
//foreach (ListViewItem listViewItem in listViewBoxes.Items)
//{
@@ -159,12 +177,13 @@ namespace PckStudio.Forms.Editor
//File.WriteAllText(saveFileDialog.FileName, contents);
}
- [Obsolete("Kept for backwards compatibility, remove later.")]
+ [Obsolete("Kept for backwards compatibility.")]
private void importCustomSkinButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
- openFileDialog.Filter = "Custom Skin Model File (*.csm,*.CSM)|*.csm;*.CSM|Custom Skin Model Binary File (*.csmb)|*.csmb|JSON Model File(*.json)|*.JSON;*.json";
openFileDialog.Title = "Select Model File";
+ openFileDialog.Filter = "Custom Skin Model File (*.csm,*.CSM)|*.csm;*.CSM|" +
+ "Custom Skin Model Binary File (*.csmb)|*.csmb|";
if (MessageBox.Show("Import custom model project file? Your current work will be lost!", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes && openFileDialog.ShowDialog() == DialogResult.OK)
{
string fileExtension = Path.GetExtension(openFileDialog.FileName);
@@ -210,9 +229,8 @@ namespace PckStudio.Forms.Editor
}
}
- private void generateModel_FormClosing(object sender, FormClosingEventArgs e)
- {
-
+ private void CustomSkinEditor_FormClosing(object sender, FormClosingEventArgs e)
+ {
}
private void outlineColorButton_Click(object sender, EventArgs e)
@@ -264,7 +282,7 @@ namespace PckStudio.Forms.Editor
return;
}
generateTextureCheckBox.Checked = false;
- uvPictureBox.BackgroundImage = img;
+ uvPictureBox.BackgroundImage = _skin.Texture = img;
}
private void skinPartListBox_DoubleClick(object sender, EventArgs e)
diff --git a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.Designer.cs b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.Designer.cs
index 871ee322..fdfdce3f 100644
--- a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.Designer.cs
+++ b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.Designer.cs
@@ -33,7 +33,6 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddNewSkin));
System.Windows.Forms.Label label2;
System.Windows.Forms.Label label1;
- this.textTheme = new System.Windows.Forms.TextBox();
this.contextMenuSkin = new System.Windows.Forms.ContextMenuStrip(this.components);
this.replaceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuCape = new System.Windows.Forms.ContextMenuStrip(this.components);
@@ -81,11 +80,6 @@
label1.ForeColor = System.Drawing.Color.White;
label1.Name = "label1";
//
- // textTheme
- //
- resources.ApplyResources(this.textTheme, "textTheme");
- this.textTheme.Name = "textTheme";
- //
// contextMenuSkin
//
this.contextMenuSkin.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -289,6 +283,7 @@
// capePictureBox
//
resources.ApplyResources(this.capePictureBox, "capePictureBox");
+ this.capePictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.capePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.capePictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.capePictureBox.Name = "capePictureBox";
@@ -298,6 +293,7 @@
// skinPictureBox
//
resources.ApplyResources(this.skinPictureBox, "skinPictureBox");
+ this.skinPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.skinPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.skinPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.skinPictureBox.Name = "skinPictureBox";
@@ -343,7 +339,6 @@
}
#endregion
- private System.Windows.Forms.TextBox textTheme;
private System.Windows.Forms.ContextMenuStrip contextMenuSkin;
private System.Windows.Forms.ToolStripMenuItem replaceToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip contextMenuCape;
diff --git a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.cs b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.cs
index 36ab7f02..eb6e0e1c 100644
--- a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.cs
+++ b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.cs
@@ -12,123 +12,93 @@ using PckStudio.IO._3DST;
using PckStudio.Properties;
using PckStudio.Forms;
using PckStudio.Extensions;
+using System.Linq;
+using System.Diagnostics;
namespace PckStudio.Popups
{
public partial class AddNewSkin : MetroFramework.Forms.MetroForm
{
- public PckFileData SkinFile => skin;
- public PckFileData CapeFile => cape;
- public bool HasCape => cape is not null;
+ public Skin NewSkin => newSkin;
+
+ //public PckFileData SkinFile => _skinFile;
+ //public PckFileData CapeFile => cape;
+ //public bool HasCape => cape is not null;
private LOCFile currentLoc;
- private PckFileData skin = new PckFileData("dlcskinXYXYXYXY", PckFileType.SkinFile);
- private PckFileData cape;
- private SkinANIM anim = new SkinANIM();
+ //private PckFileData _skinFile = new PckFileData("dlcskinXYXYXYXY", PckFileType.SkinFile);
+ //private PckFileData cape;
+ private Skin newSkin;
private Random rng = new Random();
- private eSkinType skinType;
-
- private enum eSkinType
- {
- Invalid = -1,
- _64x64,
- _64x32,
- _64x64HD,
- _64x32HD,
- Custom,
- }
-
public AddNewSkin(LOCFile loc)
{
InitializeComponent();
currentLoc = loc;
+ newSkin = new Skin("", 0, Resources.classic_template, new SkinANIM(), Enumerable.Empty(), Enumerable.Empty());
}
- private void CheckImage(Image img)
+ private void SetNewTexture(Image img)
{
- switch (img.Height)
+ if (img is null)
{
- case 64:
- anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64, true);
- MessageBox.Show("64x64 Skin Detected");
- skinType = eSkinType._64x64;
- break;
- case 32:
- anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64 | SkinAnimFlag.SLIM_MODEL, false);
- MessageBox.Show("64x32 Skin Detected");
- skinType = eSkinType._64x32;
- break;
- default:
- if (img.Width == img.Height)
- {
- anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64, true);
- MessageBox.Show("64x64 HD Skin Detected");
- skinType = eSkinType._64x64HD;
- break;
- }
-
- if (img.Height == img.Width / 2)
- {
- anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64 | SkinAnimFlag.SLIM_MODEL, false);
- MessageBox.Show("64x32 HD Skin Detected");
- skinType = eSkinType._64x32HD;
- break;
- }
-
- MessageBox.Show("Not a Valid Skin File");
- skinType = eSkinType.Invalid;
- return;
+ Debug.Assert(false, "Image is null.");
}
+ if (img.Width != img.Height && img.Height != img.Width / 2)
+ {
+ MessageBox.Show("The selected image does not suit a skin texture.", "Invalid image dimensions.", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ newSkin.ANIM.SetFlag(SkinAnimFlag.RESOLUTION_64x64, img.Width == img.Height);
- skinPictureBox.Image = img;
- capePictureBox.Visible = true;
- buttonCape.Visible = true;
- capeLabel.Visible = true;
- buttonDone.Enabled = true;
- buttonAnimGen.Enabled = true;
+ skinPictureBox.Image = newSkin.Texture = img;
labelSelectTexture.Visible = false;
+ //capePictureBox.Visible = true;
+ //buttonCape.Visible = true;
+ //capeLabel.Visible = true;
+ //buttonDone.Enabled = true;
+ //buttonAnimGen.Enabled = true;
}
private void DrawModel()
{
- bool isSlim = anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
+ bool isSlim = newSkin.ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL);
Pen outlineColor = Pens.LightGray;
Brush fillColor = Brushes.Gray;
Image previewTexture = new Bitmap(displayBox.Width, displayBox.Height);
using (Graphics g = Graphics.FromImage(previewTexture))
{
- if(!anim.GetFlag(SkinAnimFlag.HEAD_DISABLED))
+ if(!newSkin.ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED))
{
//Head
g.DrawRectangle(outlineColor, 70, 15, 40, 40);
g.FillRectangle(fillColor, 71, 16, 39, 39);
}
- if (!anim.GetFlag(SkinAnimFlag.BODY_DISABLED))
+ if (!newSkin.ANIM.GetFlag(SkinAnimFlag.BODY_DISABLED))
{
//Body
g.DrawRectangle(outlineColor, 70, 55, 40, 60);
g.FillRectangle(fillColor, 71, 56, 39, 59);
}
- if (!anim.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED))
+ if (!newSkin.ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED))
{
//Arm0
g.DrawRectangle(outlineColor, isSlim ? 55 : 50, 55, isSlim ? 15 : 20, 60);
g.FillRectangle(fillColor , isSlim ? 56 : 51, 56, isSlim ? 14 : 19, 59);
}
- if (!anim.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED))
+ if (!newSkin.ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED))
{
//Arm1
g.DrawRectangle(outlineColor, 110, 55, isSlim ? 15 : 20, 60);
g.FillRectangle(fillColor, 111, 56, isSlim ? 14 : 19, 59);
}
- if (!anim.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED))
+ if (!newSkin.ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED))
{
//Leg0
g.DrawRectangle(outlineColor, 70, 115, 20, 60);
g.FillRectangle(fillColor, 71, 116, 19, 59);
}
- if (!anim.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED))
+ if (!newSkin.ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED))
{
//Leg1
g.DrawRectangle(outlineColor, 90, 115, 20, 60);
@@ -158,7 +128,7 @@ namespace PckStudio.Popups
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
- CheckImage(Image.FromFile(ofd.FileName));
+ SetNewTexture(Image.FromFile(ofd.FileName));
}
}
@@ -187,12 +157,12 @@ namespace PckStudio.Popups
using (var fs = File.OpenRead(ofd.FileName))
{
var reader = new _3DSTextureReader();
- CheckImage(reader.FromStream(fs));
+ SetNewTexture(reader.FromStream(fs));
}
textSkinName.Text = Path.GetFileNameWithoutExtension(ofd.FileName);
return;
}
- CheckImage(Image.FromFile(ofd.FileName));
+ SetNewTexture(Image.FromFile(ofd.FileName));
}
}
}
@@ -223,9 +193,7 @@ namespace PckStudio.Popups
MessageBox.Show("Not a Valid Cape File");
return;
}
- capePictureBox.Image = Image.FromFile(ofd.FileName);
- cape ??= new PckFileData("dlccapeXYXYXYXY", PckFileType.CapeFile);
- cape.SetData(File.ReadAllBytes(ofd.FileName));
+ newSkin.CapeTexture = capePictureBox.Image = Image.FromFile(ofd.FileName);
contextMenuCape.Items[0].Text = "Replace";
capeLabel.Visible = false;
contextMenuCape.Visible = true;
@@ -235,35 +203,18 @@ namespace PckStudio.Popups
private void CreateButton_Click(object sender, EventArgs e)
{
- if (!int.TryParse(textSkinID.Text, out int _skinId))
+ if (radioButtonManual.Checked)
{
- MessageBox.Show("The Skin ID Must be a Unique 8 Digit Number Thats Not Already in Use", "Invalid Skin ID", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
+ if (!int.TryParse(textSkinID.Text, out int _skinId))
+ {
+ MessageBox.Show("The Skin Id must be a unique 8 digit number that is not already in use", "Invalid Skin Id", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ newSkin.Id = _skinId;
}
- string skinId = _skinId.ToString("d08");
- skin.Filename = $"dlcskin{skinId}.png";
- string skinDisplayNameLocKey = $"IDS_dlcskin{skinId}_DISPLAYNAME";
- currentLoc.AddLocKey(skinDisplayNameLocKey, textSkinName.Text);
- skin.Properties.Add("DISPLAYNAME", textSkinName.Text);
- skin.Properties.Add("DISPLAYNAMEID", skinDisplayNameLocKey);
- if (!string.IsNullOrEmpty(textThemeName.Text))
- {
- skin.Properties.Add("THEMENAME", textThemeName.Text);
- skin.Properties.Add("THEMENAMEID", $"IDS_dlcskin{skinId}_THEMENAME");
- currentLoc.AddLocKey($"IDS_dlcskin{skinId}_THEMENAME", textThemeName.Text);
- }
- skin.Properties.Add("ANIM", anim);
- skin.Properties.Add("GAME_FLAGS", "0x18");
- skin.Properties.Add("FREE", "1");
-
- if (HasCape)
- {
- cape.Filename = $"dlccape{skinId}.png";
- skin.Properties.Add("CAPEPATH", cape.Filename);
- }
- skin.SetData(skinPictureBox.Image, ImageFormat.Png);
+ newSkin.Name = textSkinName.Text;
+ newSkin.Theme = textThemeName.Text;
DialogResult = DialogResult.OK;
- Close();
}
private void textSkinID_TextChanged(object sender, EventArgs e)
@@ -274,24 +225,18 @@ namespace PckStudio.Popups
private void CreateCustomModel_Click(object sender, EventArgs e)
{
- //Prompt for skin model generator
if (MessageBox.Show("Create your own custom skin model?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) != DialogResult.Yes)
return;
- skin.SetData(Resources.classic_template, ImageFormat.Png);
+ using CustomSkinEditor customSkinEditor = new CustomSkinEditor(newSkin);
- using CustomSkinEditor generate = new CustomSkinEditor(skin);
-
- if (generate.ShowDialog() == DialogResult.OK)
+ if (customSkinEditor.ShowDialog() == DialogResult.OK)
{
- displayBox.Image = generate.PreviewImage;
+ skinPictureBox.Image = customSkinEditor.ResultSkin.Texture;
+ newSkin = customSkinEditor.ResultSkin;
buttonDone.Enabled = true;
labelSelectTexture.Visible = false;
- if (skinType != eSkinType._64x64 && skinType != eSkinType._64x64HD)
- {
- buttonSkin.Location = new Point(buttonSkin.Location.X - skinPictureBox.Width, buttonSkin.Location.Y);
- skinType = eSkinType._64x64;
- }
+ DrawModel();
}
}
@@ -299,8 +244,8 @@ namespace PckStudio.Popups
{
if (radioButtonAuto.Checked)
{
- int num = rng.Next(100000, 99999999);
- textSkinID.Text = num.ToString();
+ newSkin.Id = rng.Next(100000, 99999999);
+ textSkinID.Text = newSkin.Id.ToString();
textSkinID.Enabled = false;
}
}
@@ -312,10 +257,10 @@ namespace PckStudio.Popups
private void buttonAnimGen_Click(object sender, EventArgs e)
{
- using ANIMEditor diag = new ANIMEditor(anim.ToString());
+ using ANIMEditor diag = new ANIMEditor(newSkin.ANIM);
if (diag.ShowDialog(this) == DialogResult.OK)
{
- anim = diag.ResultAnim;
+ newSkin.ANIM = diag.ResultAnim;
DrawModel();
}
}
diff --git a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.resx b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.resx
index 2f724c3d..2310be6d 100644
--- a/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.resx
+++ b/PCK-Studio/Forms/Skins-And-Textures/AddNewSkin.resx
@@ -219,21 +219,6 @@
19
-
- 102, 78
-
-
- 239, 20
-
-
- 32
-
-
- textTheme
-
-
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
17, 17
diff --git a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs
index c13fed89..68108ddd 100644
--- a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs
+++ b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs
@@ -18,11 +18,11 @@ namespace PckStudio.Forms
private Image texture;
private IEnumerable data;
- public SkinPreview(Image image, IEnumerable modelData)
+ public SkinPreview(Skin skin)
{
InitializeComponent();
- texture = image;
- data = modelData;
+ texture = skin.Texture;
+ data = skin.AdditionalBoxes;
}
protected override void OnLoad(EventArgs e)
diff --git a/PCK-Studio/Internal/Skin.cs b/PCK-Studio/Internal/Skin.cs
new file mode 100644
index 00000000..12dc0ca1
--- /dev/null
+++ b/PCK-Studio/Internal/Skin.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using OMI.Formats.Pck;
+
+namespace PckStudio.Internal
+{
+ public sealed class Skin
+ {
+ public string Name { get; set; }
+ public string Theme { get; set; }
+ public int Id { get; set; }
+ public Image Texture { get; set; }
+ public Image CapeTexture { get; set; }
+ public bool HasCape => CapeTexture is not null;
+ public SkinANIM ANIM { get; set; }
+ public List AdditionalBoxes { get; }
+ public List PartOffsets { get; }
+
+ public Skin(string name, int id, Image texture, SkinANIM anim, IEnumerable additionalBoxes, IEnumerable partOffsets)
+ {
+ Name = name;
+ Id = id;
+ Texture = texture;
+ ANIM = anim;
+ AdditionalBoxes = new List(additionalBoxes);
+ PartOffsets = new List(partOffsets);
+ }
+ }
+}
diff --git a/PCK-Studio/Internal/SkinANIM.cs b/PCK-Studio/Internal/SkinANIM.cs
index c152efa8..90c7c6b8 100644
--- a/PCK-Studio/Internal/SkinANIM.cs
+++ b/PCK-Studio/Internal/SkinANIM.cs
@@ -57,6 +57,10 @@ namespace PckStudio.Internal
=> IsValidANIM(value)
? new SkinANIM(Convert.ToInt32(value.TrimEnd(' ', '\n', '\r'), 16))
: new SkinANIM();
+
+ public static SkinANIM FromValue(int value) => new SkinANIM(value);
+
+ public int ToValue() => _flags.Data;
public static SkinANIM operator |(SkinANIM _this, SkinANIM other) => new SkinANIM(_this._flags.Data | other._flags.Data);
diff --git a/PCK-Studio/Internal/SkinPartOffset.cs b/PCK-Studio/Internal/SkinPartOffset.cs
index f651f4ff..c6c34536 100644
--- a/PCK-Studio/Internal/SkinPartOffset.cs
+++ b/PCK-Studio/Internal/SkinPartOffset.cs
@@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
namespace PckStudio.Internal
{
- internal readonly struct SkinPartOffset
+ public readonly struct SkinPartOffset
{
private static readonly Regex sWhitespace = new Regex(@"\s+");
internal static string ReplaceWhitespace(string input, string replacement)
diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs
index 70cb7c8f..301817ba 100644
--- a/PCK-Studio/MainForm.cs
+++ b/PCK-Studio/MainForm.cs
@@ -432,21 +432,17 @@ namespace PckStudio
public void HandleSkinFile(PckFileData file)
{
- if (file.Properties.HasProperty("BOX"))
+ using CustomSkinEditor skinEditor = new CustomSkinEditor(file.GetSkin());
+ if (skinEditor.ShowDialog() == DialogResult.OK)
{
- using CustomSkinEditor generate = new CustomSkinEditor(file);
- if (generate.ShowDialog() == DialogResult.OK)
- {
- entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty;
- wasModified = true;
- ReloadMetaTreeView();
- }
- return;
- }
+ if (!TryGetLocFile(out var locFile))
+ Debug.Fail("Failed to aquire loc file.");
+ file.SetSkin(skinEditor.ResultSkin, locFile);
- var skinPreview = new SkinPreview(file.GetTexture(), file.Properties.GetProperties("BOX").Select(kv => SkinBOX.FromString(kv.Value)));
- skinPreview.ANIM = file.Properties.GetPropertyValue("ANIM", SkinANIM.FromString);
- skinPreview.ShowDialog();
+ entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty;
+ wasModified = true;
+ ReloadMetaTreeView();
+ }
}
public void HandleModelsFile(PckFileData file)
@@ -783,43 +779,50 @@ namespace PckStudio
MessageBox.Show("No .loc file found", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
- using (AddNewSkin add = new AddNewSkin(locFile))
- if (add.ShowDialog() == DialogResult.OK)
+ using (AddNewSkin addNewSkinDialog = new AddNewSkin(locFile))
+ if (addNewSkinDialog.ShowDialog() == DialogResult.OK)
{
-
- if (currentPCK.HasFile("Skins.pck", PckFileType.SkinDataFile)) // Prioritize Skins.pck
+ var skinFile = addNewSkinDialog.NewSkin.CreateFile(locFile);
+ currentPCK.AddFile(skinFile);
+ if (currentPCK.HasFile("Skins.pck", PckFileType.SkinDataFile)) // Prioritize Skins.pck
{
TreeNode subPCK = treeViewMain.Nodes.Find("Skins.pck", false).FirstOrDefault();
- if (subPCK.Nodes.ContainsKey("Skins")) add.SkinFile.Filename = add.SkinFile.Filename.Insert(0, "Skins/");
- add.SkinFile.Filename = add.SkinFile.Filename.Insert(0, "Skins.pck/");
- TreeNode newNode = new TreeNode(Path.GetFileName(add.SkinFile.Filename));
- newNode.Tag = add.SkinFile;
+ if (subPCK.Nodes.ContainsKey("Skins"))
+ skinFile.Filename = skinFile.Filename.Insert(0, "Skins/");
+ skinFile.Filename = skinFile.Filename.Insert(0, "Skins.pck/");
+ TreeNode newNode = new TreeNode(Path.GetFileName(skinFile.Filename));
+ newNode.Tag = skinFile;
SetNodeIcon(newNode, PckFileType.SkinFile);
subPCK.Nodes.Add(newNode);
RebuildSubPCK(newNode.FullPath);
}
else
{
- if (treeViewMain.Nodes.ContainsKey("Skins")) add.SkinFile.Filename = add.SkinFile.Filename.Insert(0, "Skins/"); // Then Skins folder
- currentPCK.AddFile(add.SkinFile);
+ if (treeViewMain.Nodes.ContainsKey("Skins"))
+ skinFile.Filename = skinFile.Filename.Insert(0, "Skins/"); // Then Skins folder
+ currentPCK.AddFile(skinFile);
}
- if (add.HasCape)
+
+ if (addNewSkinDialog.NewSkin.HasCape)
{
- if (currentPCK.HasFile("Skins.pck", PckFileType.SkinDataFile)) // Prioritize Skins.pck
+ var capeFile = addNewSkinDialog.NewSkin.CreateCapeFile();
+ if (currentPCK.HasFile("Skins.pck", PckFileType.SkinDataFile)) // Prioritize Skins.pck
{
TreeNode subPCK = treeViewMain.Nodes.Find("Skins.pck", false).FirstOrDefault();
- if (subPCK.Nodes.ContainsKey("Skins")) add.CapeFile.Filename = add.CapeFile.Filename.Insert(0, "Skins/");
- add.CapeFile.Filename = add.CapeFile.Filename.Insert(0, "Skins.pck/");
- TreeNode newNode = new TreeNode(Path.GetFileName(add.CapeFile.Filename));
- newNode.Tag = add.CapeFile;
+ if (subPCK.Nodes.ContainsKey("Skins"))
+ capeFile.Filename = capeFile.Filename.Insert(0, "Skins/");
+ capeFile.Filename = capeFile.Filename.Insert(0, "Skins.pck/");
+ TreeNode newNode = new TreeNode(Path.GetFileName(capeFile.Filename));
+ newNode.Tag = capeFile;
SetNodeIcon(newNode, PckFileType.SkinFile);
subPCK.Nodes.Add(newNode);
RebuildSubPCK(newNode.FullPath);
}
else
{
- if (treeViewMain.Nodes.ContainsKey("Skins")) add.CapeFile.Filename = add.CapeFile.Filename.Insert(0, "Skins/"); // Then Skins folder
- currentPCK.AddFile(add.CapeFile);
+ if (treeViewMain.Nodes.ContainsKey("Skins"))
+ capeFile.Filename = capeFile.Filename.Insert(0, "Skins/"); // Then Skins folder
+ currentPCK.AddFile(capeFile);
}
}
diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj
index 04546dcb..25cb5cda 100644
--- a/PCK-Studio/PckStudio.csproj
+++ b/PCK-Studio/PckStudio.csproj
@@ -137,8 +137,10 @@
+
+