mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-09-22 02:23:13 +00:00
Fixed several skin paper doll related issues
-Fixed cancelled MessageBox erroneously stating "Node not extracted" while using the Export Skin Icon tool. -Skin icons can no longer be exported for skins with abnormal resolutions. -Skin paper dolls can no longer be created for skins with abnormal resolutions. A default skin icon will be returned instead. -Fix crash for skin textures smaller than the base resolution skin size -Fix crash for boxes placed outside of the base resolution skin canvas
This commit is contained in:
@@ -839,6 +839,12 @@ namespace PckStudio.Controls
|
|||||||
|
|
||||||
Bitmap customIcon = new Bitmap(skinIconWidth, skinIconHeight);
|
Bitmap customIcon = new Bitmap(skinIconWidth, skinIconHeight);
|
||||||
|
|
||||||
|
// get the bust crop for the image
|
||||||
|
// this is handled externally to use the skin data to ensure skins are positioned in context of the default player head
|
||||||
|
Image croppedPaperDoll = skin.DrawPaperDoll(xmlVersion: EditorValue.File.xmlVersion, bustCrop: true);
|
||||||
|
if (croppedPaperDoll is null)
|
||||||
|
return GetDefaultSkinNodeIconKey(skin.Anim);
|
||||||
|
|
||||||
using (Graphics gfx = Graphics.FromImage(customIcon))
|
using (Graphics gfx = Graphics.FromImage(customIcon))
|
||||||
{
|
{
|
||||||
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
|
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
@@ -847,10 +853,6 @@ namespace PckStudio.Controls
|
|||||||
|
|
||||||
gfx.Fill(new Rectangle(0, 0, skinIconWidth, skinIconHeight), Color.FromArgb(0xFF, 0x5D, 0x9C, 0xEC));
|
gfx.Fill(new Rectangle(0, 0, skinIconWidth, skinIconHeight), Color.FromArgb(0xFF, 0x5D, 0x9C, 0xEC));
|
||||||
|
|
||||||
// get the bust crop for the image
|
|
||||||
// this is handled externally to use the skin data to ensure skins are positioned in context of the default player head
|
|
||||||
Image croppedPaperDoll = skin.DrawPaperDoll(xmlVersion: EditorValue.File.xmlVersion, bustCrop: true);
|
|
||||||
|
|
||||||
gfx.DrawImage(croppedPaperDoll, 0, 0); // the crop bust is already the same dimensions as the custom icon
|
gfx.DrawImage(croppedPaperDoll, 0, 0); // the crop bust is already the same dimensions as the custom icon
|
||||||
|
|
||||||
gfx.DrawImage(Resources.CUSTOM_SKIN_ICON, 0, 0); // draw border on top
|
gfx.DrawImage(Resources.CUSTOM_SKIN_ICON, 0, 0); // draw border on top
|
||||||
@@ -2523,7 +2525,7 @@ namespace PckStudio.Controls
|
|||||||
// Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
|
// Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
|
||||||
string.IsNullOrWhiteSpace(Path.GetDirectoryName(saveFileDialog.FileName)))
|
string.IsNullOrWhiteSpace(Path.GetDirectoryName(saveFileDialog.FileName)))
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, "The chosen directory is invalid. Please choose a different one and try again.", "Node not extracted");
|
MessageBox.Show(this, "The chosen directory is invalid. Please choose a different one and try again.", "Icon not exported");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2541,7 +2543,16 @@ namespace PckStudio.Controls
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
skin.DrawPaperDoll(bustCrop: cropped).Save(saveFileDialog.FileName);
|
Image finalDoll = skin.DrawPaperDoll(bustCrop: cropped);
|
||||||
|
|
||||||
|
if (finalDoll is null)
|
||||||
|
{
|
||||||
|
MessageBox.Show(this, "Cannot create an icon from an invalid Minecraft skin.", "Icon not exported");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
finalDoll.Save(saveFileDialog.FileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,14 +74,43 @@ namespace PckStudio.Core.Extensions
|
|||||||
{
|
{
|
||||||
//pixel scale set to 10 so inflated parts can be seen as properly as possible
|
//pixel scale set to 10 so inflated parts can be seen as properly as possible
|
||||||
|
|
||||||
|
Image skinTexture = skin.Texture;
|
||||||
|
if (skinTexture.Width != skinTexture.Height && skinTexture.Width / skinTexture.Height != 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
bool isWideSkin = skin.Anim.GetFlag(SkinAnimFlag.MODERN_WIDE_MODEL);
|
bool isWideSkin = skin.Anim.GetFlag(SkinAnimFlag.MODERN_WIDE_MODEL);
|
||||||
bool isSlimSkin = skin.Anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
|
bool isSlimSkin = skin.Anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
|
||||||
bool isModernSkin = isWideSkin || isSlimSkin;
|
bool isModernSkin = isWideSkin || isSlimSkin;
|
||||||
bool isDinnerbone = skin.Anim.GetFlag(SkinAnimFlag.DINNERBONE);
|
bool isDinnerbone = skin.Anim.GetFlag(SkinAnimFlag.DINNERBONE);
|
||||||
bool isStatueOfLiberty = skin.Anim.GetFlag(SkinAnimFlag.STATUE_OF_LIBERTY);
|
bool isStatueOfLiberty = skin.Anim.GetFlag(SkinAnimFlag.STATUE_OF_LIBERTY);
|
||||||
|
|
||||||
float textureScaleX = skin.Texture.Width / 64f; // minecraft skins always have a width of 64
|
int skinHeight = isModernSkin ? 64 : 32;
|
||||||
float textureScaleY = skin.Texture.Height / (isModernSkin ? 64f : 32f);
|
|
||||||
|
// fix for abnormal skin textures that are smaller than 64
|
||||||
|
if (skinTexture.Width != 64 || skinTexture.Height != skinHeight)
|
||||||
|
{
|
||||||
|
Bitmap resized = new Bitmap(64, skinHeight);
|
||||||
|
|
||||||
|
using (Graphics gfx = Graphics.FromImage(resized))
|
||||||
|
{
|
||||||
|
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
|
gfx.PixelOffsetMode = PixelOffsetMode.Half;
|
||||||
|
gfx.SmoothingMode = SmoothingMode.None;
|
||||||
|
gfx.CompositingMode = CompositingMode.SourceCopy;
|
||||||
|
|
||||||
|
gfx.DrawImage(
|
||||||
|
skinTexture,
|
||||||
|
new Rectangle(0, 0, 64, skinHeight)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
skinTexture = resized;
|
||||||
|
}
|
||||||
|
|
||||||
|
float textureScaleX = skinTexture.Width / 64f; // minecraft skins always have a width of 64
|
||||||
|
float textureScaleY = skinTexture.Height / (isModernSkin ? 64f : 32f);
|
||||||
|
|
||||||
// start with a large canvas and crop down later
|
// start with a large canvas and crop down later
|
||||||
Image paperDoll = new Bitmap(512, 512);
|
Image paperDoll = new Bitmap(512, 512);
|
||||||
@@ -220,6 +249,8 @@ namespace PckStudio.Core.Extensions
|
|||||||
|
|
||||||
bool isStatueOfLibertyArm = isStatueOfLiberty && (box.Type == "ARM0" || box.Type == "SLEEVE0" || box.Type == "ARMARMOR0");
|
bool isStatueOfLibertyArm = isStatueOfLiberty && (box.Type == "ARM0" || box.Type == "SLEEVE0" || box.Type == "ARMARMOR0");
|
||||||
|
|
||||||
|
box.UV = new (box.UV.X % 64, box.UV.Y % (isModernSkin ? 64f : 32f));
|
||||||
|
|
||||||
// this math is basically to ensure the face is stretched if the texture is improper
|
// this math is basically to ensure the face is stretched if the texture is improper
|
||||||
Rectangle faceRect = new Rectangle(
|
Rectangle faceRect = new Rectangle(
|
||||||
isStatueOfLibertyArm // get back of ARM 0 box if Statue of Liberty
|
isStatueOfLibertyArm // get back of ARM 0 box if Statue of Liberty
|
||||||
@@ -230,6 +261,11 @@ namespace PckStudio.Core.Extensions
|
|||||||
(int)(boxHeight * textureScaleY)
|
(int)(boxHeight * textureScaleY)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(faceRect.Size.Height == 0)
|
||||||
|
{
|
||||||
|
faceRect.Size = new Size(faceRect.X, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// get back of the face to display behind just incase transparent parts exist on the front layer
|
// get back of the face to display behind just incase transparent parts exist on the front layer
|
||||||
Rectangle backFaceRect = new Rectangle(
|
Rectangle backFaceRect = new Rectangle(
|
||||||
!isStatueOfLibertyArm // get front of ARM 0 box if Statue of Liberty
|
!isStatueOfLibertyArm // get front of ARM 0 box if Statue of Liberty
|
||||||
@@ -240,8 +276,13 @@ namespace PckStudio.Core.Extensions
|
|||||||
(int)(boxHeight * textureScaleY)
|
(int)(boxHeight * textureScaleY)
|
||||||
);
|
);
|
||||||
|
|
||||||
Image boxFace = skin.Texture.GetArea(faceRect);
|
if (backFaceRect.Size.Height == 0)
|
||||||
Image backBoxFace = skin.Texture.GetArea(backFaceRect);
|
{
|
||||||
|
backFaceRect.Size = new Size(backFaceRect.X, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image boxFace = skinTexture.GetArea(faceRect);
|
||||||
|
Image backBoxFace = skinTexture.GetArea(backFaceRect);
|
||||||
|
|
||||||
if (box.Mirror)
|
if (box.Mirror)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace PckStudio.Core.Skin
|
|||||||
public string Type { get; }
|
public string Type { get; }
|
||||||
public Vector3 Pos { get; }
|
public Vector3 Pos { get; }
|
||||||
public Vector3 Size { get; }
|
public Vector3 Size { get; }
|
||||||
public Vector2 UV { get; }
|
public Vector2 UV { get; set; } // changing this to simulate texture wrapping for paper doll drawing. this might be a temporary change -May
|
||||||
public SkinArmorFlags ArmorMaskFlags { get; }
|
public SkinArmorFlags ArmorMaskFlags { get; }
|
||||||
public bool Mirror { get; }
|
public bool Mirror { get; }
|
||||||
public float Scale { get; }
|
public float Scale { get; }
|
||||||
|
|||||||
Reference in New Issue
Block a user