mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-09-23 09:42:26 +00:00
Improved skin paper doll draw function
This commit is contained in:
@@ -7,11 +7,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PckStudio.Core.Extensions
|
namespace PckStudio.Core.Extensions
|
||||||
{
|
{
|
||||||
@@ -95,6 +91,7 @@ namespace PckStudio.Core.Extensions
|
|||||||
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
|
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
gfx.SmoothingMode = SmoothingMode.None;
|
gfx.SmoothingMode = SmoothingMode.None;
|
||||||
|
gfx.CompositingMode = CompositingMode.SourceOver;
|
||||||
|
|
||||||
SkinBOX baseHeadBox = new SkinBOX("HEAD", new(-4, -8, -4), new(8), new(0, 0));
|
SkinBOX baseHeadBox = new SkinBOX("HEAD", new(-4, -8, -4), new(8), new(0, 0));
|
||||||
SkinBOX baseTorsoBox = new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16));
|
SkinBOX baseTorsoBox = new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16));
|
||||||
@@ -165,17 +162,29 @@ namespace PckStudio.Core.Extensions
|
|||||||
baseBoxes.Add(new SkinBOX("PANTS1", new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: 0.25f));
|
baseBoxes.Add(new SkinBOX("PANTS1", new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: 0.25f));
|
||||||
}
|
}
|
||||||
|
|
||||||
skinBoxes.AddRange(baseBoxes);
|
HashSet<SkinBOX> baseBoxSet = new(baseBoxes);
|
||||||
|
|
||||||
|
baseBoxes.Clear();
|
||||||
|
|
||||||
|
skinBoxes.AddRange(baseBoxSet);
|
||||||
skinBoxes.AddRange(skin.Model.AdditionalBoxes);
|
skinBoxes.AddRange(skin.Model.AdditionalBoxes);
|
||||||
|
|
||||||
skinBoxes = skinBoxes
|
skinBoxes.Sort((first, second) =>
|
||||||
.OrderByDescending(box =>
|
{
|
||||||
isStatueOfLiberty && box.Type == "ARM0"
|
float aZPos = isStatueOfLiberty && first.Type == "ARM0"
|
||||||
? -box.Pos.Z
|
? -first.Pos.Z
|
||||||
: box.Pos.Z
|
: first.Pos.Z;
|
||||||
)
|
|
||||||
.ThenBy(box => box.Scale)
|
float bZPos = isStatueOfLiberty && second.Type == "ARM0"
|
||||||
.ToList();
|
? -second.Pos.Z
|
||||||
|
: second.Pos.Z;
|
||||||
|
|
||||||
|
int result = bZPos.CompareTo(aZPos);
|
||||||
|
|
||||||
|
return result != 0
|
||||||
|
? result
|
||||||
|
: first.Scale.CompareTo(second.Scale);
|
||||||
|
});
|
||||||
|
|
||||||
float canvasWidth = 0;
|
float canvasWidth = 0;
|
||||||
float canvasHeight = 0;
|
float canvasHeight = 0;
|
||||||
@@ -190,178 +199,264 @@ namespace PckStudio.Core.Extensions
|
|||||||
float defaultDrawOffsetX = paperDoll.Width / 2f; // draw at center of the canvas
|
float defaultDrawOffsetX = paperDoll.Width / 2f; // draw at center of the canvas
|
||||||
float defaultDrawOffsetY = paperDoll.Height / 2f - torsoCenterY * pixelScale; // draw from center of the torso box
|
float defaultDrawOffsetY = paperDoll.Height / 2f - torsoCenterY * pixelScale; // draw from center of the torso box
|
||||||
|
|
||||||
|
var drawFunctions = new List<(
|
||||||
|
Image BackFace,
|
||||||
|
Image FrontFace,
|
||||||
|
RectangleF DrawRect,
|
||||||
|
bool StatueOfLibertyArm
|
||||||
|
)>();
|
||||||
|
|
||||||
|
var partOffsets = skin.Model.PartOffsets
|
||||||
|
.ToDictionary(x => x.Type, x => x.Value);
|
||||||
|
|
||||||
foreach (SkinBOX box in skinBoxes)
|
foreach (SkinBOX box in skinBoxes)
|
||||||
{
|
{
|
||||||
try
|
float boxWidth = box.Size.X;
|
||||||
|
float boxHeight = box.Size.Y;
|
||||||
|
float boxDepth = box.Size.Z;
|
||||||
|
|
||||||
|
if (boxWidth <= 0 || boxHeight <= 0) // if either of these are 0, skip because drawing is impossible
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool isStatueOfLibertyArm = isStatueOfLiberty && (box.Type == "ARM0" || box.Type == "SLEEVE0" || box.Type == "ARMARMOR0");
|
||||||
|
|
||||||
|
// this math is basically to ensure the face is stretched if the texture is improper
|
||||||
|
Rectangle faceRect = new Rectangle(
|
||||||
|
isStatueOfLibertyArm // get back of ARM 0 box if Statue of Liberty
|
||||||
|
? (int)((box.UV.X + boxWidth + 2 * boxDepth) * textureScaleX) // depth + width + depth = offset for back of box
|
||||||
|
: (int)((box.UV.X + boxDepth) * textureScaleX),
|
||||||
|
(int)((box.UV.Y + boxDepth) * textureScaleY),
|
||||||
|
(int)(boxWidth * textureScaleX),
|
||||||
|
(int)(boxHeight * textureScaleY)
|
||||||
|
);
|
||||||
|
|
||||||
|
// get back of the face to display behind just incase transparent parts exist on the front layer
|
||||||
|
Rectangle backFaceRect = new Rectangle(
|
||||||
|
!isStatueOfLibertyArm // get front of ARM 0 box if Statue of Liberty
|
||||||
|
? (int)((box.UV.X + boxWidth + 2 * boxDepth) * textureScaleX) // depth + width + depth = offset for back of box
|
||||||
|
: (int)((box.UV.X + boxDepth) * textureScaleX),
|
||||||
|
(int)((box.UV.Y + boxDepth) * textureScaleY),
|
||||||
|
(int)(boxWidth * textureScaleX),
|
||||||
|
(int)(boxHeight * textureScaleY)
|
||||||
|
);
|
||||||
|
|
||||||
|
Image boxFace = skin.Texture.GetArea(faceRect);
|
||||||
|
Image backBoxFace = skin.Texture.GetArea(backFaceRect);
|
||||||
|
|
||||||
|
if (box.Mirror)
|
||||||
{
|
{
|
||||||
float boxWidth = box.Size.X;
|
boxFace.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
||||||
float boxHeight = box.Size.Y;
|
}
|
||||||
float boxDepth = box.Size.Z;
|
else
|
||||||
|
{
|
||||||
|
backBoxFace.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
||||||
|
}
|
||||||
|
|
||||||
if (boxWidth <= 0 || boxHeight <= 0) // if either of these are 0, skip because drawing is impossible
|
if (isStatueOfLibertyArm)
|
||||||
continue;
|
{
|
||||||
|
boxFace.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
backBoxFace.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
}
|
||||||
|
|
||||||
bool isStatueOfLibertyArm = isStatueOfLiberty && (box.Type == "ARM0" || box.Type == "SLEEVE0" || box.Type == "ARMARMOR0");
|
// these values are added to later
|
||||||
|
float drawOffsetX = defaultDrawOffsetX; // draw at center of the canvas
|
||||||
|
float drawOffsetY = defaultDrawOffsetY;
|
||||||
|
|
||||||
// this math is basically to ensure the face is stretched if the texture is improper
|
// offset by 4 pixels so feet align with where the head should be for the bust crop. This might not be perfect, but it gets the job done for the 2 "vanilla" upside-down skins
|
||||||
Rectangle faceRect = new Rectangle(
|
if (isDinnerbone)
|
||||||
isStatueOfLibertyArm // get back of ARM 0 box if Statue of Liberty
|
drawOffsetY -= 4 * pixelScale;
|
||||||
? (int)((box.UV.X + boxWidth + 2 * boxDepth) * textureScaleX) // depth + width + depth = offset for back of box
|
|
||||||
: (int)((box.UV.X + boxDepth) * textureScaleX),
|
|
||||||
(int)((box.UV.Y + boxDepth) * textureScaleY),
|
|
||||||
(int)(boxWidth * textureScaleX),
|
|
||||||
(int)(boxHeight * textureScaleY)
|
|
||||||
);
|
|
||||||
|
|
||||||
Image boxFace = skin.Texture.GetArea(faceRect);
|
float armXOffset = GameConstants.SkinLeftArmTranslation.X * pixelScale;
|
||||||
if (box.Mirror) boxFace.RotateFlip(RotateFlipType.RotateNoneFlipX);
|
float armYOffset = GameConstants.SkinLeftArmTranslation.Y * pixelScale;
|
||||||
if (isStatueOfLibertyArm)
|
float legXOffset = GameConstants.SkinLeftLegTranslation.X * pixelScale;
|
||||||
|
float legYOffset = GameConstants.SkinLeftLegTranslation.Y * pixelScale;
|
||||||
|
|
||||||
|
float offset = 0;
|
||||||
|
|
||||||
|
switch (box.Type)
|
||||||
|
{
|
||||||
|
case "HEAD":
|
||||||
|
case "HEADWEAR":
|
||||||
|
partOffsets.TryGetValue("HEAD", out offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "BODY":
|
||||||
|
case "WAIST":
|
||||||
|
case "JACKET":
|
||||||
|
case "BELT":
|
||||||
|
case "BODYARMOR":
|
||||||
|
partOffsets.TryGetValue("BODY", out offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ARM0":
|
||||||
|
case "SLEEVE0":
|
||||||
|
case "ARMARMOR0":
|
||||||
|
partOffsets.TryGetValue("ARM0", out offset);
|
||||||
|
drawOffsetX -= armXOffset;
|
||||||
|
drawOffsetY += armYOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ARM1":
|
||||||
|
case "SLEEVE1":
|
||||||
|
case "ARMARMOR1":
|
||||||
|
partOffsets.TryGetValue("ARM1", out offset);
|
||||||
|
drawOffsetX += armXOffset;
|
||||||
|
drawOffsetY += armYOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "LEG0":
|
||||||
|
case "PANTS0":
|
||||||
|
case "LEGGING0":
|
||||||
|
case "SOCK0":
|
||||||
|
case "BOOT0":
|
||||||
|
partOffsets.TryGetValue("BOOT0", out offset);
|
||||||
|
drawOffsetX -= legXOffset;
|
||||||
|
drawOffsetY += legYOffset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "LEG1":
|
||||||
|
case "PANTS1":
|
||||||
|
case "LEGGING1":
|
||||||
|
case "SOCK1":
|
||||||
|
case "BOOT1":
|
||||||
|
partOffsets.TryGetValue("BOOT1", out offset);
|
||||||
|
drawOffsetX += legXOffset;
|
||||||
|
drawOffsetY += legYOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawOffsetY += offset * pixelScale;
|
||||||
|
|
||||||
|
float boxPosY = box.Pos.Y;
|
||||||
|
|
||||||
|
if (isStatueOfLibertyArm)
|
||||||
|
{
|
||||||
|
boxPosY = -(box.Pos.Y + box.Size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float drawX = box.Pos.X * pixelScale;
|
||||||
|
float drawY = boxPosY * pixelScale;
|
||||||
|
|
||||||
|
float drawWidth = boxWidth * pixelScale;
|
||||||
|
float drawHeight = boxHeight * pixelScale;
|
||||||
|
|
||||||
|
// handle Box scale
|
||||||
|
float boxInflate =
|
||||||
|
// if XMLVersion 3 or a base box; then return box scale
|
||||||
|
(xmlVersion == 3 || baseBoxSet.Contains(box)) ? box.Scale
|
||||||
|
// if not; then check that it is an overlay box
|
||||||
|
: (xmlVersion > 0 && xmlVersion < 3 && SkinBOX.OverlayTypes.Contains(box.Type))
|
||||||
|
// if so, return hardcoded box inflate value
|
||||||
|
? (box.Type == "HEADWEAR" ? 0.5f : 0.25f)
|
||||||
|
: 0f; // finally, if not caught anywhere else, return no scale
|
||||||
|
|
||||||
|
float drawInflate = boxInflate * pixelScale * 1.5f; // no idea why 1.5 seems to fix this :,)
|
||||||
|
float halfInflation = drawInflate * 0.5f;
|
||||||
|
|
||||||
|
float finalDrawX = drawOffsetX + drawX - halfInflation;
|
||||||
|
float finalDrawY = drawOffsetY + drawY - halfInflation;
|
||||||
|
|
||||||
|
float finalDrawWidth = drawWidth + drawInflate;
|
||||||
|
float finalDrawHeight = drawHeight + drawInflate;
|
||||||
|
|
||||||
|
RectangleF boxRect = new RectangleF(finalDrawX, finalDrawY, finalDrawWidth, finalDrawHeight);
|
||||||
|
|
||||||
|
if (isStatueOfLiberty && box.Type == "ARM0")
|
||||||
|
{
|
||||||
|
float pivotX = defaultDrawOffsetX + GameConstants.SkinRightArmPivot.X * pixelScale;
|
||||||
|
float pivotY = defaultDrawOffsetY + GameConstants.SkinRightArmPivot.Y * pixelScale;
|
||||||
|
|
||||||
|
const float Angle = -8f * (float)Math.PI / 180f;
|
||||||
|
|
||||||
|
float cos = (float)Math.Cos(Angle);
|
||||||
|
float sin = (float)Math.Sin(Angle);
|
||||||
|
|
||||||
|
// used to calculate if the bounds of the arm go beyond the current bounds of the image so that the entire skin is shown
|
||||||
|
PointF[] armBounds =
|
||||||
{
|
{
|
||||||
boxFace.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
|
||||||
}
|
|
||||||
|
|
||||||
float drawOffsetX = defaultDrawOffsetX; // draw at center of the canvas
|
|
||||||
float drawOffsetY = defaultDrawOffsetY;
|
|
||||||
|
|
||||||
// offset by 4 pixels so feet align with where the head should be for the bust crop. This might not be perfect, but it gets the job done for the 2 "vanilla" upside-down skins
|
|
||||||
if (isDinnerbone)
|
|
||||||
drawOffsetY -= 4 * pixelScale;
|
|
||||||
|
|
||||||
float armXOffset = GameConstants.SkinLeftArmTranslation.X * pixelScale;
|
|
||||||
float armYOffset = GameConstants.SkinLeftArmTranslation.Y * pixelScale;
|
|
||||||
float legXOffset = GameConstants.SkinLeftLegTranslation.X * pixelScale;
|
|
||||||
float legYOffset = GameConstants.SkinLeftLegTranslation.Y * pixelScale;
|
|
||||||
|
|
||||||
switch (box.Type)
|
|
||||||
{
|
|
||||||
case "HEAD":
|
|
||||||
case "HEADWEAR":
|
|
||||||
drawOffsetY += skin.Model.PartOffsets.Find(x => x.Type == "HEAD").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
case "BODY":
|
|
||||||
case "WAIST":
|
|
||||||
case "JACKET":
|
|
||||||
case "BELT":
|
|
||||||
case "BODYARMOR":
|
|
||||||
drawOffsetY += skin.Model.PartOffsets.Find(x => x.Type == "BODY").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
case "ARM0":
|
|
||||||
case "SLEEVE0":
|
|
||||||
case "ARMARMOR0":
|
|
||||||
drawOffsetX -= armXOffset;
|
|
||||||
drawOffsetY += armYOffset + skin.Model.PartOffsets.Find(x => x.Type == "ARM0").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
case "ARM1":
|
|
||||||
case "SLEEVE1":
|
|
||||||
case "ARMARMOR1":
|
|
||||||
drawOffsetX += armXOffset;
|
|
||||||
drawOffsetY += armYOffset + skin.Model.PartOffsets.Find(x => x.Type == "ARM1").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
case "LEG0":
|
|
||||||
case "PANTS0":
|
|
||||||
case "LEGGING0":
|
|
||||||
case "SOCK0":
|
|
||||||
case "BOOT0":
|
|
||||||
drawOffsetX -= legXOffset;
|
|
||||||
drawOffsetY += legYOffset + skin.Model.PartOffsets.Find(x => x.Type == "LEG0").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
case "LEG1":
|
|
||||||
case "PANTS1":
|
|
||||||
case "LEGGING1":
|
|
||||||
case "SOCK1":
|
|
||||||
case "BOOT1":
|
|
||||||
drawOffsetX += legXOffset;
|
|
||||||
drawOffsetY += legYOffset + skin.Model.PartOffsets.Find(x => x.Type == "LEG1").Value * pixelScale;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
float boxPosY = box.Pos.Y;
|
|
||||||
|
|
||||||
if (isStatueOfLibertyArm)
|
|
||||||
{
|
|
||||||
boxPosY = -(box.Pos.Y + box.Size.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float drawX = box.Pos.X * pixelScale;
|
|
||||||
float drawY = boxPosY * pixelScale;
|
|
||||||
|
|
||||||
float drawWidth = boxWidth * pixelScale;
|
|
||||||
float drawHeight = boxHeight * pixelScale;
|
|
||||||
|
|
||||||
// handle Box scale
|
|
||||||
float boxInflate =
|
|
||||||
// if XMLVersion 3 or a base box; then return box scale
|
|
||||||
(xmlVersion == 3 || baseBoxes.Contains(box)) ? box.Scale
|
|
||||||
// if not; then check that it is an overlay box
|
|
||||||
: (xmlVersion > 0 && xmlVersion < 3 && SkinBOX.OverlayTypes.Contains(box.Type))
|
|
||||||
// if so, return hardcoded box inflate value
|
|
||||||
? (box.Type == "HEADWEAR" ? 0.5f : 0.25f)
|
|
||||||
: 0f; // finally, if not caught anywhere else, return no scale
|
|
||||||
|
|
||||||
float drawInflate = boxInflate * pixelScale * 1.5f; // no idea why 1.5 seems to fix this :,)
|
|
||||||
float halfInflation = drawInflate * 0.5f;
|
|
||||||
|
|
||||||
float finalDrawX = drawOffsetX + drawX - halfInflation;
|
|
||||||
float finalDrawY = drawOffsetY + drawY - halfInflation;
|
|
||||||
|
|
||||||
float finalDrawWidth = drawWidth + drawInflate;
|
|
||||||
float finalDrawHeight = drawHeight + drawInflate;
|
|
||||||
|
|
||||||
RectangleF boxRect = new RectangleF(finalDrawX, finalDrawY, finalDrawWidth, finalDrawHeight);
|
|
||||||
|
|
||||||
if (isStatueOfLiberty && box.Type == "ARM0")
|
|
||||||
{
|
|
||||||
float pivotX = defaultDrawOffsetX + GameConstants.SkinRightArmPivot.X * pixelScale;
|
|
||||||
float pivotY = defaultDrawOffsetY + GameConstants.SkinRightArmPivot.Y * pixelScale;
|
|
||||||
|
|
||||||
float angle = -8f * (float)Math.PI / 180f;
|
|
||||||
|
|
||||||
// used to calculate if the bounds of the arm go beyond the current bounds of the image so that the entire skin is shown
|
|
||||||
PointF[] armBounds =
|
|
||||||
{
|
|
||||||
new PointF(finalDrawX, finalDrawY),
|
new PointF(finalDrawX, finalDrawY),
|
||||||
new PointF(finalDrawX + finalDrawWidth, finalDrawY),
|
new PointF(finalDrawX + finalDrawWidth, finalDrawY),
|
||||||
new PointF(finalDrawX, finalDrawY + finalDrawHeight),
|
new PointF(finalDrawX, finalDrawY + finalDrawHeight),
|
||||||
new PointF(finalDrawX + finalDrawWidth, finalDrawY + finalDrawHeight)
|
new PointF(finalDrawX + finalDrawWidth, finalDrawY + finalDrawHeight)
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var bound in armBounds)
|
foreach (var bound in armBounds)
|
||||||
{
|
|
||||||
float finalX = bound.X - pivotX;
|
|
||||||
float finalY = bound.Y - pivotY;
|
|
||||||
|
|
||||||
float rotateX = pivotX + (finalX * (float)Math.Cos(angle) - finalY * (float)Math.Sin(angle));
|
|
||||||
float rotateY = pivotY + (finalX * (float)Math.Sin(angle) + finalY * (float)Math.Cos(angle));
|
|
||||||
|
|
||||||
canvasMinX = Math.Min(canvasMinX, rotateX);
|
|
||||||
canvasMinY = Math.Min(canvasMinY, rotateY);
|
|
||||||
canvasMaxX = Math.Max(canvasMaxX, rotateX);
|
|
||||||
canvasMaxY = Math.Max(canvasMaxY, rotateY);
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = gfx.Save();
|
|
||||||
|
|
||||||
gfx.TranslateTransform(pivotX, pivotY);
|
|
||||||
gfx.RotateTransform(-8f);
|
|
||||||
gfx.TranslateTransform(-pivotX, -pivotY);
|
|
||||||
|
|
||||||
gfx.DrawImage(boxFace, boxRect);
|
|
||||||
|
|
||||||
gfx.Restore(state);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
canvasMinX = Math.Min(canvasMinX, finalDrawX);
|
float finalX = bound.X - pivotX;
|
||||||
canvasMinY = Math.Min(canvasMinY, finalDrawY);
|
float finalY = bound.Y - pivotY;
|
||||||
canvasMaxX = Math.Max(canvasMaxX, finalDrawX + finalDrawWidth);
|
|
||||||
canvasMaxY = Math.Max(canvasMaxY, finalDrawY + finalDrawHeight);
|
|
||||||
|
|
||||||
gfx.DrawImage(boxFace, boxRect);
|
float rotateX = pivotX + (finalX * cos - finalY * sin);
|
||||||
|
float rotateY = pivotY + (finalX * sin + finalY * cos);
|
||||||
|
|
||||||
|
canvasMinX = Math.Min(canvasMinX, rotateX);
|
||||||
|
canvasMinY = Math.Min(canvasMinY, rotateY);
|
||||||
|
canvasMaxX = Math.Max(canvasMaxX, rotateX);
|
||||||
|
canvasMaxY = Math.Max(canvasMaxY, rotateY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.Message);
|
canvasMinX = Math.Min(canvasMinX, finalDrawX);
|
||||||
|
canvasMinY = Math.Min(canvasMinY, finalDrawY);
|
||||||
|
canvasMaxX = Math.Max(canvasMaxX, finalDrawX + finalDrawWidth);
|
||||||
|
canvasMaxY = Math.Max(canvasMaxY, finalDrawY + finalDrawHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawFunctions.Add((
|
||||||
|
backBoxFace,
|
||||||
|
boxFace,
|
||||||
|
boxRect,
|
||||||
|
isStatueOfLiberty && box.Type == "ARM0"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw back faces first
|
||||||
|
for (int i = drawFunctions.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var function = drawFunctions[i];
|
||||||
|
|
||||||
|
if (function.StatueOfLibertyArm)
|
||||||
|
{
|
||||||
|
float pivotX = defaultDrawOffsetX + GameConstants.SkinRightArmPivot.X * pixelScale;
|
||||||
|
float pivotY = defaultDrawOffsetY + GameConstants.SkinRightArmPivot.Y * pixelScale;
|
||||||
|
|
||||||
|
var state = gfx.Save();
|
||||||
|
|
||||||
|
gfx.TranslateTransform(pivotX, pivotY);
|
||||||
|
gfx.RotateTransform(-8f);
|
||||||
|
gfx.TranslateTransform(-pivotX, -pivotY);
|
||||||
|
|
||||||
|
gfx.DrawImage(function.BackFace, function.DrawRect);
|
||||||
|
|
||||||
|
gfx.Restore(state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gfx.DrawImage(function.BackFace, function.DrawRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then draw all fronts overtop
|
||||||
|
foreach (var function in drawFunctions)
|
||||||
|
{
|
||||||
|
if (function.StatueOfLibertyArm)
|
||||||
|
{
|
||||||
|
float pivotX = defaultDrawOffsetX + GameConstants.SkinRightArmPivot.X * pixelScale;
|
||||||
|
float pivotY = defaultDrawOffsetY + GameConstants.SkinRightArmPivot.Y * pixelScale;
|
||||||
|
|
||||||
|
var state = gfx.Save();
|
||||||
|
|
||||||
|
gfx.TranslateTransform(pivotX, pivotY);
|
||||||
|
gfx.RotateTransform(-8f);
|
||||||
|
gfx.TranslateTransform(-pivotX, -pivotY);
|
||||||
|
|
||||||
|
gfx.DrawImage(function.FrontFace, function.DrawRect);
|
||||||
|
|
||||||
|
gfx.Restore(state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gfx.DrawImage(function.FrontFace, function.DrawRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user