From 2d9440b40138d5bbfdad886ef31cbcc2fd59a055 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Sun, 21 Jan 2024 19:59:00 +0100 Subject: [PATCH] SkinRenderer - Add support for part offset --- PCK-Studio/Extensions/SkinBOXExtensions.cs | 54 ++ .../CustomModelEditor.Designer.cs | 186 ++--- .../Skins-And-Textures/CustomModelEditor.cs | 176 ++--- .../Skins-And-Textures/CustomModelEditor.resx | 644 +++++------------- PCK-Studio/Internal/ModelOffset.cs | 81 +++ PCK-Studio/PckStudio.csproj | 2 + PCK-Studio/Rendering/CubeRenderGroup.cs | 10 +- PCK-Studio/Rendering/SkinRenderer.Designer.cs | 3 +- PCK-Studio/Rendering/SkinRenderer.cs | 154 +++-- .../ToolboxItems/InterpolationPictureBox.cs | 9 + 10 files changed, 525 insertions(+), 794 deletions(-) create mode 100644 PCK-Studio/Extensions/SkinBOXExtensions.cs create mode 100644 PCK-Studio/Internal/ModelOffset.cs diff --git a/PCK-Studio/Extensions/SkinBOXExtensions.cs b/PCK-Studio/Extensions/SkinBOXExtensions.cs new file mode 100644 index 00000000..7e7ce2ae --- /dev/null +++ b/PCK-Studio/Extensions/SkinBOXExtensions.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; +using PckStudio.Internal; + +namespace PckStudio.Extensions +{ + internal static class SkinBOXExtensions + { + public static GraphicsPath GetUVGraphicsPath(this SkinBOX skinBOX, Vector2 scalingFactor) + { + var types = new byte[9]; + var points = new PointF[9]; + + types[0] = (byte)PathPointType.Start; + types[1] = (byte)PathPointType.Line; + types[2] = (byte)PathPointType.Line; + types[3] = (byte)PathPointType.Line; + types[4] = (byte)PathPointType.Line; + types[5] = (byte)PathPointType.Line; + types[6] = (byte)PathPointType.Line; + types[7] = (byte)PathPointType.Line; + types[8] = (byte)PathPointType.Line; + + points[0] = new PointF(skinBOX.UV.X, skinBOX.UV.Y + skinBOX.Size.Z); + points[1] = new PointF(skinBOX.UV.X + skinBOX.Size.Z, skinBOX.UV.Y + skinBOX.Size.Z); + points[2] = new PointF(skinBOX.UV.X + skinBOX.Size.Z, skinBOX.UV.Y); + points[3] = new PointF(skinBOX.UV.X + skinBOX.Size.Z + skinBOX.Size.X * 2, skinBOX.UV.Y); + points[4] = new PointF(skinBOX.UV.X + skinBOX.Size.Z + skinBOX.Size.X * 2, skinBOX.UV.Y + skinBOX.Size.Z); + points[5] = new PointF(skinBOX.UV.X + skinBOX.Size.Z * 2 + skinBOX.Size.X * 2, skinBOX.UV.Y + skinBOX.Size.Z); + points[6] = new PointF(skinBOX.UV.X + skinBOX.Size.Z * 2 + skinBOX.Size.X * 2, skinBOX.UV.Y + skinBOX.Size.Z + skinBOX.Size.Y); + points[7] = new PointF(skinBOX.UV.X, skinBOX.UV.Y + skinBOX.Size.Z + skinBOX.Size.Y); + points[8] = points[0]; + + for (int i = 0; i < points.Length; i++) + { + points[i] = new PointF(points[i].X * scalingFactor.X, points[i].Y * scalingFactor.Y); + } + + return new GraphicsPath(points, types); + + } + + public static GraphicsPath GetUVGraphicsPath(this SkinBOX skinBOX) + { + return skinBOX.GetUVGraphicsPath(Vector2.One); + } + } +} diff --git a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.Designer.cs b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.Designer.cs index 6f7d7ee0..8ea61e9c 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.Designer.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.Designer.cs @@ -41,19 +41,6 @@ this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.changeColorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.buttonDone = new MetroFramework.Controls.MetroButton(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.tabBody = new System.Windows.Forms.TabControl(); - this.tabArmor = new System.Windows.Forms.TabPage(); - this.tabPage1 = new System.Windows.Forms.TabPage(); - this.myTablePanel2 = new System.Windows.Forms.TableLayoutPanel(); - this.offsetArms = new System.Windows.Forms.TextBox(); - this.label14 = new System.Windows.Forms.Label(); - this.offsetBody = new System.Windows.Forms.TextBox(); - this.offsetLegs = new System.Windows.Forms.TextBox(); - this.label10 = new System.Windows.Forms.Label(); - this.label13 = new System.Windows.Forms.Label(); - this.offsetHead = new System.Windows.Forms.TextBox(); - this.label12 = new System.Windows.Forms.Label(); this.buttonEXPORT = new MetroFramework.Controls.MetroButton(); this.buttonIMPORT = new MetroFramework.Controls.MetroButton(); this.buttonImportModel = new MetroFramework.Controls.MetroButton(); @@ -70,18 +57,17 @@ this.PosZUpDown = new System.Windows.Forms.NumericUpDown(); this.PosYUpDown = new System.Windows.Forms.NumericUpDown(); this.PosXUpDown = new System.Windows.Forms.NumericUpDown(); + this.modelPartListBox = new System.Windows.Forms.ListBox(); + this.clampToViewCheckbox = new MetroFramework.Controls.MetroCheckBox(); + this.captureScreenshotButton = new MetroFramework.Controls.MetroButton(); + this.showToolsCheckBox = new MetroFramework.Controls.MetroCheckBox(); this.renderer3D1 = new PckStudio.Rendering.SkinRenderer(); this.uvPictureBox = new PckStudio.ToolboxItems.InterpolationPictureBox(); - this.listBox1 = new System.Windows.Forms.ListBox(); label5 = new System.Windows.Forms.Label(); label3 = new System.Windows.Forms.Label(); label7 = new System.Windows.Forms.Label(); labelTextureMappingPreview = new System.Windows.Forms.Label(); this.contextMenuStrip1.SuspendLayout(); - this.groupBox1.SuspendLayout(); - this.tabBody.SuspendLayout(); - this.tabPage1.SuspendLayout(); - this.myTablePanel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.SizeXUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.SizeYUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.SizeZUpDown)).BeginInit(); @@ -161,92 +147,6 @@ this.buttonDone.UseSelectable = true; this.buttonDone.Click += new System.EventHandler(this.buttonDone_Click); // - // groupBox1 - // - resources.ApplyResources(this.groupBox1, "groupBox1"); - this.groupBox1.Controls.Add(this.tabBody); - this.groupBox1.ForeColor = System.Drawing.Color.White; - this.groupBox1.Name = "groupBox1"; - this.groupBox1.TabStop = false; - // - // tabBody - // - this.tabBody.Controls.Add(this.tabArmor); - this.tabBody.Controls.Add(this.tabPage1); - resources.ApplyResources(this.tabBody, "tabBody"); - this.tabBody.Name = "tabBody"; - this.tabBody.SelectedIndex = 0; - // - // tabArmor - // - this.tabArmor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(17)))), ((int)(((byte)(17)))), ((int)(((byte)(17))))); - resources.ApplyResources(this.tabArmor, "tabArmor"); - this.tabArmor.Name = "tabArmor"; - // - // tabPage1 - // - this.tabPage1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(17)))), ((int)(((byte)(17)))), ((int)(((byte)(17))))); - this.tabPage1.Controls.Add(this.myTablePanel2); - resources.ApplyResources(this.tabPage1, "tabPage1"); - this.tabPage1.Name = "tabPage1"; - // - // myTablePanel2 - // - resources.ApplyResources(this.myTablePanel2, "myTablePanel2"); - this.myTablePanel2.Controls.Add(this.offsetArms, 1, 3); - this.myTablePanel2.Controls.Add(this.label14, 0, 3); - this.myTablePanel2.Controls.Add(this.offsetBody, 1, 1); - this.myTablePanel2.Controls.Add(this.offsetLegs, 1, 2); - this.myTablePanel2.Controls.Add(this.label10, 0, 0); - this.myTablePanel2.Controls.Add(this.label13, 0, 2); - this.myTablePanel2.Controls.Add(this.offsetHead, 1, 0); - this.myTablePanel2.Controls.Add(this.label12, 0, 1); - this.myTablePanel2.Name = "myTablePanel2"; - // - // offsetArms - // - resources.ApplyResources(this.offsetArms, "offsetArms"); - this.offsetArms.Name = "offsetArms"; - // - // label14 - // - resources.ApplyResources(this.label14, "label14"); - this.label14.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192))))); - this.label14.Name = "label14"; - // - // offsetBody - // - resources.ApplyResources(this.offsetBody, "offsetBody"); - this.offsetBody.Name = "offsetBody"; - // - // offsetLegs - // - resources.ApplyResources(this.offsetLegs, "offsetLegs"); - this.offsetLegs.Name = "offsetLegs"; - // - // label10 - // - resources.ApplyResources(this.label10, "label10"); - this.label10.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(0))))); - this.label10.Name = "label10"; - // - // label13 - // - resources.ApplyResources(this.label13, "label13"); - this.label13.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(0)))), ((int)(((byte)(64))))); - this.label13.Name = "label13"; - // - // offsetHead - // - resources.ApplyResources(this.offsetHead, "offsetHead"); - this.offsetHead.Name = "offsetHead"; - // - // label12 - // - resources.ApplyResources(this.label12, "label12"); - this.label12.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(64)))), ((int)(((byte)(0))))); - this.label12.Name = "label12"; - // // buttonEXPORT // resources.ApplyResources(this.buttonEXPORT, "buttonEXPORT"); @@ -400,12 +300,46 @@ -2147483648}); this.PosXUpDown.Name = "PosXUpDown"; // + // modelPartListBox + // + this.modelPartListBox.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.modelPartListBox.ContextMenuStrip = this.contextMenuStrip1; + this.modelPartListBox.FormattingEnabled = true; + resources.ApplyResources(this.modelPartListBox, "modelPartListBox"); + this.modelPartListBox.Name = "modelPartListBox"; + this.modelPartListBox.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + this.modelPartListBox.DoubleClick += new System.EventHandler(this.listBox1_DoubleClick); + // + // clampToViewCheckbox + // + resources.ApplyResources(this.clampToViewCheckbox, "clampToViewCheckbox"); + this.clampToViewCheckbox.Name = "clampToViewCheckbox"; + this.clampToViewCheckbox.Theme = MetroFramework.MetroThemeStyle.Dark; + this.clampToViewCheckbox.UseSelectable = true; + this.clampToViewCheckbox.CheckedChanged += new System.EventHandler(this.clampToViewCheckbox_CheckedChanged); + // + // captureScreenshotButton + // + resources.ApplyResources(this.captureScreenshotButton, "captureScreenshotButton"); + this.captureScreenshotButton.ForeColor = System.Drawing.Color.White; + this.captureScreenshotButton.Name = "captureScreenshotButton"; + this.captureScreenshotButton.Theme = MetroFramework.MetroThemeStyle.Dark; + this.captureScreenshotButton.UseSelectable = true; + this.captureScreenshotButton.Click += new System.EventHandler(this.captureScreenshotButton_Click); + // + // showToolsCheckBox + // + resources.ApplyResources(this.showToolsCheckBox, "showToolsCheckBox"); + this.showToolsCheckBox.Name = "showToolsCheckBox"; + this.showToolsCheckBox.Theme = MetroFramework.MetroThemeStyle.Dark; + this.showToolsCheckBox.UseSelectable = true; + // // renderer3D1 // resources.ApplyResources(this.renderer3D1, "renderer3D1"); this.renderer3D1.ANIM = skinANIM1; this.renderer3D1.BackColor = System.Drawing.Color.DimGray; - this.renderer3D1.CameraTarget = ((OpenTK.Vector2)(resources.GetObject("renderer3D1.CameraTarget"))); + this.renderer3D1.ClampModel = false; this.renderer3D1.Name = "renderer3D1"; this.renderer3D1.Texture = null; this.renderer3D1.VSync = true; @@ -414,25 +348,19 @@ // uvPictureBox // resources.ApplyResources(this.uvPictureBox, "uvPictureBox"); - this.uvPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.uvPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; this.uvPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; this.uvPictureBox.Name = "uvPictureBox"; this.uvPictureBox.TabStop = false; // - // listBox1 - // - this.listBox1.ContextMenuStrip = this.contextMenuStrip1; - this.listBox1.FormattingEnabled = true; - resources.ApplyResources(this.listBox1, "listBox1"); - this.listBox1.Name = "listBox1"; - this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); - this.listBox1.DoubleClick += new System.EventHandler(this.listBox1_DoubleClick); - // // CustomModelEditor // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.listBox1); + this.Controls.Add(this.showToolsCheckBox); + this.Controls.Add(this.captureScreenshotButton); + this.Controls.Add(this.clampToViewCheckbox); + this.Controls.Add(this.modelPartListBox); this.Controls.Add(this.renderer3D1); this.Controls.Add(this.PosZUpDown); this.Controls.Add(this.PosYUpDown); @@ -450,24 +378,18 @@ this.Controls.Add(this.buttonImportModel); this.Controls.Add(this.buttonEXPORT); this.Controls.Add(labelTextureMappingPreview); - this.Controls.Add(this.uvPictureBox); this.Controls.Add(this.buttonIMPORT); - this.Controls.Add(this.groupBox1); this.Controls.Add(label7); this.Controls.Add(this.buttonDone); this.Controls.Add(label3); this.Controls.Add(label5); + this.Controls.Add(this.uvPictureBox); this.MaximizeBox = false; this.Name = "CustomModelEditor"; this.Style = MetroFramework.MetroColorStyle.Silver; this.Theme = MetroFramework.MetroThemeStyle.Dark; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.generateModel_FormClosing); this.contextMenuStrip1.ResumeLayout(false); - this.groupBox1.ResumeLayout(false); - this.tabBody.ResumeLayout(false); - this.tabPage1.ResumeLayout(false); - this.myTablePanel2.ResumeLayout(false); - this.myTablePanel2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.SizeXUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.SizeYUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.SizeZUpDown)).EndInit(); @@ -495,19 +417,6 @@ private PckStudio.ToolboxItems.InterpolationPictureBox uvPictureBox; private MetroFramework.Controls.MetroButton buttonIMPORT; private MetroFramework.Controls.MetroButton buttonEXPORT; - private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.TabControl tabBody; - private System.Windows.Forms.TabPage tabPage1; - private System.Windows.Forms.TableLayoutPanel myTablePanel2; - private System.Windows.Forms.TextBox offsetArms; - private System.Windows.Forms.Label label14; - private System.Windows.Forms.TextBox offsetBody; - private System.Windows.Forms.TextBox offsetLegs; - private System.Windows.Forms.Label label10; - private System.Windows.Forms.Label label13; - private System.Windows.Forms.TextBox offsetHead; - private System.Windows.Forms.Label label12; - private System.Windows.Forms.TabPage tabArmor; private MetroFramework.Controls.MetroCheckBox generateTextureCheckBox; private MetroFramework.Controls.MetroCheckBox checkGuide; private MetroFramework.Controls.MetroCheckBox checkBoxArmor; @@ -520,6 +429,9 @@ private System.Windows.Forms.NumericUpDown PosYUpDown; private System.Windows.Forms.NumericUpDown PosXUpDown; private Rendering.SkinRenderer renderer3D1; - private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.ListBox modelPartListBox; + private MetroFramework.Controls.MetroCheckBox clampToViewCheckbox; + private MetroFramework.Controls.MetroButton captureScreenshotButton; + private MetroFramework.Controls.MetroCheckBox showToolsCheckBox; } } \ No newline at end of file diff --git a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.cs b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.cs index 6414cb6d..eb04b3e0 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; @@ -11,11 +12,11 @@ using System.Text.RegularExpressions; using Newtonsoft.Json; using MetroFramework.Forms; + using OMI.Formats.Pck; + using PckStudio.Internal; using PckStudio.Extensions; -using System.Diagnostics; -using System.Text; using PckStudio.Forms.Editor; namespace PckStudio.Forms @@ -33,82 +34,8 @@ namespace PckStudio.Forms PixelOffsetMode = PixelOffsetMode.HighQuality, }; - private static readonly string[] ValidModelBoxTypes = new string[] - { - // Base 64x32 Parts - "HEAD", - "BODY", - "ARM0", - "ARM1", - "LEG0", - "LEG1", - - // 64x64 Overlay Parts - "HEADWEAR", - "JACKET", - "SLEEVE0", - "SLEEVE1", - "WAIST", - "PANTS0", - "PANTS1", - - // Armor Parts - "BODYARMOR", - "ARMARMOR0", - "ARMARMOR1", - "BELT", - "LEGGING0", - "LEGGING1", - "SOCK0", - "SOCK1", - "BOOT0", - "BOOT1" - }; - - private static readonly string[] ValidModelOffsetTypes = new string[] - { - // Body Offsets - "HEAD", - "BODY", - "ARM0", - "ARM1", - "LEG0", - "LEG1", - - // Armor Offsets - "HELMET", - "CHEST", "BODYARMOR", - "SHOULDER0", "ARMARMOR0", - "SHOULDER1", "ARMARMOR0", - "BELT", - "LEGGING0", - "LEGGING1", - "SOCK0", "BOOT0", - "SOCK1", "BOOT1", - - "TOOL0", - "TOOL1", - }; - List modelOffsets = new List(); - private readonly struct ModelOffset - { - public readonly string Name; - public readonly float YOffset; - - public ModelOffset(string name, float yOffset) - { - Name = name; - YOffset = yOffset; - } - public (string, string) ToProperty() - { - string value = $"{Name} Y {YOffset}"; - return ("OFFSET", value.Replace(',','.')); - } - } - public CustomModelEditor(PckFileData file) { InitializeComponent(); @@ -116,42 +43,22 @@ namespace PckStudio.Forms _file = file; if (_file.Size > 0) { - uvPictureBox.Image = renderer3D1.Texture = _file.GetTexture(); + uvPictureBox.BackgroundImage = renderer3D1.Texture = _file.GetTexture(); } //comboParent.Items.AddRange(ValidModelBoxTypes); LoadModelData(file.Properties); } - private static readonly Regex sWhitespace = new Regex(@"\s+"); - public static string ReplaceWhitespace(string input, string replacement) - { - return sWhitespace.Replace(input, replacement); - } - private void LoadModelData(PckFileProperties properties) { renderer3D1.ANIM = properties.GetPropertyValue("ANIM", SkinANIM.FromString); var boxProperties = properties.GetProperties("BOX"); Array.ForEach(boxProperties, kv => renderer3D1.ModelData.Add(SkinBOX.FromString(kv.Value))); - listBox1.DataSource = renderer3D1.ModelData; - listBox1.DisplayMember = "Type"; + modelPartListBox.DataSource = renderer3D1.ModelData; + modelPartListBox.DisplayMember = "Type"; - properties.GetProperties("OFFSET").All(kv => { - string[] offset = ReplaceWhitespace(kv.Value, ",").TrimEnd('\n', '\r', ' ').Split(','); - if (offset.Length < 3) - return false; - string name = offset[0]; - if (offset[1] != "Y") - return false; - float value = float.Parse(offset[2]); - if (ValidModelOffsetTypes.Contains(name)) - { - modelOffsets.Add(new ModelOffset(name, value)); - return true; - } - return false; - }); + Array.ForEach(properties.GetProperties("OFFSET"), kv => renderer3D1.SetPartOffset(ModelOffset.FromString(kv.Value))); } private void GenerateUVTextureMap() @@ -191,7 +98,7 @@ namespace PckStudio.Forms //Export Current Skin Texture private void buttonEXPORT_Click(object sender, EventArgs e) { - Bitmap bitmap = new Bitmap(uvPictureBox.Image, 64, 64); + Bitmap bitmap = new Bitmap(uvPictureBox.BackgroundImage, 64, 64); using SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "PNG Image Files | *.png"; if (saveFileDialog.ShowDialog() == DialogResult.OK) @@ -214,7 +121,7 @@ namespace PckStudio.Forms if ((img.Width == img.Height || img.Height == img.Width / 2)) { generateTextureCheckBox.Checked = false; - using (Graphics graphics = Graphics.FromImage(uvPictureBox.Image)) + using (Graphics graphics = Graphics.FromImage(uvPictureBox.BackgroundImage)) { graphics.ApplyConfig(_graphicsConfig); graphics.DrawImage(img, 0, 0, img.Width, img.Height); @@ -231,6 +138,7 @@ namespace PckStudio.Forms 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); @@ -240,7 +148,6 @@ namespace PckStudio.Forms DialogResult = DialogResult.OK; } - // Exports model as csm file private void buttonExportModel_Click(object sender, EventArgs e) { //SaveFileDialog saveFileDialog = new SaveFileDialog(); @@ -292,31 +199,15 @@ namespace PckStudio.Forms private void cloneToolStripMenuItem_Click(object sender, EventArgs e) { - //try - //{ - // ListViewItem listViewItem = new ListViewItem(); - // var selected = listViewBoxes.SelectedItems[0]; - // listViewItem.Text = selected.Text; - // listViewItem.Tag = selected.Tag; - // int num = 0; - // foreach (ListViewItem.ListViewSubItem subItem in selected.SubItems) - // { - // if (num > 0) - // listViewItem.SubItems.Add(subItem.Text); - // ++num; - // } - // listViewBoxes.Items.Add(listViewItem); - //} - //catch (Exception ex) - //{ - // Console.WriteLine(ex.Message); - // MessageBox.Show("Please Select a Part"); - //} + if (modelPartListBox.SelectedItem is SkinBOX box) + { + renderer3D1.ModelData.Add((SkinBOX)box.Clone()); + } } private void deleteToolStripMenuItem_Click(object sender, EventArgs e) { - if (listBox1.SelectedItem is SkinBOX box) + if (modelPartListBox.SelectedItem is SkinBOX box) { renderer3D1.ModelData.Remove(box); } @@ -340,7 +231,6 @@ namespace PckStudio.Forms //{ // if (modelBoxes.Remove(part)) // listViewBoxes.SelectedItems[0].Remove(); - //} } @@ -431,25 +321,51 @@ namespace PckStudio.Forms private void renderer3D1_TextureChanging(object sender, Rendering.TextureChangingEventArgs e) { // TODO: add validation for 64x64 and 64x32 - uvPictureBox.Image = e.NewTexture; + uvPictureBox.BackgroundImage = e.NewTexture; } private void listBox1_DoubleClick(object sender, EventArgs e) { - if (listBox1.SelectedItem is SkinBOX box) + if (modelPartListBox.SelectedItem is SkinBOX box) { var boxEditor = new BoxEditor(box, false); if (boxEditor.ShowDialog() == DialogResult.OK) { - renderer3D1.ModelData[listBox1.SelectedIndex] = boxEditor.Result; - listBox1.Update(); + renderer3D1.ModelData[modelPartListBox.SelectedIndex] = boxEditor.Result; + modelPartListBox.Update(); } } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { - //renderer3D1.SelectedIndex = listBox1.SelectedIndex; + if (modelPartListBox.SelectedItem is SkinBOX box) + { + int scale = 3; + uvPictureBox.Image = new Bitmap(uvPictureBox.BackgroundImage.Width * scale, uvPictureBox.BackgroundImage.Height * scale); + using (Graphics g = Graphics.FromImage(uvPictureBox.Image)) + { + g.DrawPath(new Pen(Color.HotPink, 1f), box.GetUVGraphicsPath(new System.Numerics.Vector2(uvPictureBox.Image.Width / uvPictureBox.BackgroundImage.Width, uvPictureBox.Image.Height / uvPictureBox.BackgroundImage.Height))); + } + uvPictureBox.Invalidate(); + } + } + + private void clampToViewCheckbox_CheckedChanged(object sender, EventArgs e) + { + renderer3D1.ClampModel = clampToViewCheckbox.Checked; + } + + private void captureScreenshotButton_Click(object sender, EventArgs e) + { + using SaveFileDialog saveFileDialog = new SaveFileDialog() + { + Filter = "PNG|*.png" + }; + if (saveFileDialog.ShowDialog() == DialogResult.OK) + { + renderer3D1.GetThumbnail().Save(saveFileDialog.FileName, ImageFormat.Png); + } } } diff --git a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.resx b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.resx index 78ab88b5..b9fb72b5 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.resx +++ b/PCK-Studio/Forms/Skins-And-Textures/CustomModelEditor.resx @@ -133,7 +133,7 @@ - 691, 357 + 629, 404 44, 13 @@ -154,7 +154,7 @@ $this - 25 + 26 False @@ -169,7 +169,7 @@ NoControl - 691, 259 + 632, 374 27, 13 @@ -190,11 +190,14 @@ $this - 24 + 25 False + + Top, Right + True @@ -202,7 +205,7 @@ NoControl - 654, 236 + 684, 345 22, 13 @@ -223,7 +226,7 @@ $this - 22 + 23 False @@ -238,7 +241,7 @@ NoControl - 655, 56 + 695, 41 128, 13 @@ -259,7 +262,7 @@ $this - 18 + 21 17, 17 @@ -349,10 +352,10 @@ Bottom, Right - 653, 663 + 632, 547 - 130, 22 + 250, 22 111 @@ -370,391 +373,13 @@ $this - 23 - - - Top, Right - - - 4, 22 - - - 3, 3, 3, 3 - - - 116, 132 - - - 1 - - - Armor - - - tabArmor - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBody - - - 0 - - - 2 - - - Left - - - 58, 99 - - - 43, 20 - - - 85 - - - 0 - - - offsetArms - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 0 - - - Left - - - True - - - NoControl - - - 3, 103 - - - 38, 13 - - - 90 - - - ARMS - - - label14 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 1 - - - Left - - - 58, 36 - - - 43, 20 - - - 83 - - - 0 - - - offsetBody - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 2 - - - Left - - - 58, 67 - - - 43, 20 - - - 84 - - - 0 - - - offsetLegs - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 3 - - - Left - - - True - - - NoControl - - - 3, 9 - - - 37, 13 - - - 87 - - - HEAD - - - label10 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 4 - - - Left - - - True - - - NoControl - - - 3, 71 - - - 35, 13 - - - 89 - - - LEGS - - - label13 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 5 - - - Left - - - 58, 5 - - - 43, 20 - - - 86 - - - 0 - - - offsetHead - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 6 - - - Left - - - True - - - NoControl - - - 3, 40 - - - 37, 13 - - - 88 - - - BODY - - - label12 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - myTablePanel2 - - - 7 - - - Fill - - - 3, 3 - - - 4 - - - 110, 126 - - - 146 - - - myTablePanel2 - - - System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabPage1 - - - 0 - - - <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="offsetArms" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label14" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="offsetBody" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="offsetLegs" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label10" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label13" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="offsetHead" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label12" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,50,Percent,50" /><Rows Styles="Percent,25,Percent,25,Percent,25,Percent,25" /></TableLayoutSettings> - - - 4, 22 - - - 3, 3, 3, 3 - - - 116, 132 - - - 0 - - - Body - - - tabPage1 - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBody - - - 1 - - - Fill - - - 3, 16 - - - 124, 158 - - - 144 - - - tabBody - - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 0 - - - 654, 459 - - - 130, 177 - - - 139 - - - OFFSETS - - - groupBox1 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 21 + 24 Top, Right - 722, 206 + 752, 315 61, 21 @@ -775,13 +400,13 @@ $this - 17 + 20 Top, Right - 655, 206 + 685, 315 61, 21 @@ -802,7 +427,7 @@ $this - 20 + 22 Bottom, Left @@ -811,7 +436,7 @@ False - 306, 663 + 306, 547 106, 21 @@ -832,7 +457,7 @@ $this - 16 + 19 Bottom, Left @@ -841,7 +466,7 @@ False - 418, 663 + 418, 548 89, 21 @@ -862,7 +487,7 @@ $this - 15 + 18 Bottom, Left @@ -871,7 +496,7 @@ False - 194, 663 + 194, 547 106, 21 @@ -892,13 +517,16 @@ $this - 14 + 17 + + + Top, Right True - 23, 547 + 632, 440 140, 15 @@ -919,13 +547,16 @@ $this - 13 + 16 + + + Top, Right True - 23, 568 + 632, 461 84, 15 @@ -946,13 +577,16 @@ $this - 12 + 15 + + + Top, Right True - 23, 589 + 632, 503 129, 15 @@ -973,16 +607,16 @@ $this - 11 + 14 Top, Right - 658, 275 + 685, 372 - 119, 20 + 53, 20 150 @@ -1000,16 +634,16 @@ $this - 10 + 13 Top, Right - 658, 301 + 744, 372 - 119, 20 + 53, 20 151 @@ -1027,16 +661,16 @@ $this - 9 + 12 Top, Right - 658, 327 + 803, 372 - 119, 20 + 58, 20 152 @@ -1054,13 +688,13 @@ $this - 8 + 11 Top, Right - 682, 233 + 712, 342 43, 20 @@ -1078,13 +712,13 @@ $this - 7 + 10 Top, Right - 731, 234 + 761, 342 43, 20 @@ -1102,16 +736,16 @@ $this - 6 + 9 Top, Right - 657, 425 + 803, 404 - 120, 20 + 58, 20 160 @@ -1129,16 +763,16 @@ $this - 3 + 6 Top, Right - 658, 399 + 744, 404 - 119, 20 + 53, 20 159 @@ -1156,16 +790,16 @@ $this - 4 + 7 Top, Right - 658, 373 + 685, 404 - 119, 20 + 53, 20 158 @@ -1183,23 +817,124 @@ $this - 5 + 8 + + + 23, 59 + + + 165, 481 + + + 161 + + + modelPartListBox + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + Top, Right + + + True + + + 632, 482 + + + 137, 15 + + + 162 + + + Clamp Model to View + + + clampToViewCheckbox + + + MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + + $this + + + 3 + + + Bottom, Left + + + 513, 548 + + + 113, 21 + + + 163 + + + Capture Screenshot + + + captureScreenshotButton + + + MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + + $this + + + 2 + + + Top, Right + + + True + + + 632, 524 + + + 82, 15 + + + 164 + + + Show Tools + + + showToolsCheckBox + + + MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + + $this + + + 1 Top, Bottom, Left, Right - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA - AVgBWQAACwsCAAAAAAAAAAAAoEAL - - 194, 59 - 449, 577 + 432, 482 0 @@ -1214,19 +949,22 @@ $this - 2 + 5 Top, Right + + Zoom + NoControl - 655, 72 + 632, 59 - 128, 128 + 250, 250 Zoom @@ -1244,28 +982,7 @@ $this - 19 - - - 23, 56 - - - 165, 485 - - - 161 - - - listBox1 - - - System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 + 27 True @@ -1277,7 +994,7 @@ 6, 13 - 806, 707 + 905, 590 @@ -3785,11 +3502,8 @@ AP//AAA= - - 1114, 1000 - - 753, 707 + 905, 590 CenterParent diff --git a/PCK-Studio/Internal/ModelOffset.cs b/PCK-Studio/Internal/ModelOffset.cs new file mode 100644 index 00000000..26a70bae --- /dev/null +++ b/PCK-Studio/Internal/ModelOffset.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.IO; +using PckStudio.Extensions; +using System.Diagnostics; +using System.Text.RegularExpressions; + +namespace PckStudio.Internal +{ + internal readonly struct ModelOffset + { + private static readonly Regex sWhitespace = new Regex(@"\s+"); + internal static string ReplaceWhitespace(string input, string replacement) + { + return sWhitespace.Replace(input, replacement); + } + + private static readonly string[] ValidModelOffsetTypes = new string[] + { + // Body Offsets + "HEAD", + "BODY", + "ARM0", + "ARM1", + "LEG0", + "LEG1", + + // Armor Offsets + "HELMET", + "CHEST", "BODYARMOR", + "SHOULDER0", "ARMARMOR0", + "SHOULDER1", "ARMARMOR1", + "BELT", + "LEGGING0", + "LEGGING1", + "SOCK0", "BOOT0", + "SOCK1", "BOOT1", + + "TOOL0", + "TOOL1", + }; + + public readonly string Name; + public readonly float Value; + + public ModelOffset(string name, float value) + { + Name = name; + Value = value; + } + + public static ModelOffset FromString(string offsetFormatString) + { + string[] offset = ReplaceWhitespace(offsetFormatString.TrimEnd('\n', '\r', ' '), ",").Split(','); + if (offset.Length < 3) + throw new InvalidDataException("Format string does not contain enough data."); + + string name = offset[0]; + + if (!ValidModelOffsetTypes.Contains(name)) + { + Debug.WriteLine($"'{name}' is an invalid offset type."); + } + + // Ignore => Y assumed + //if (offset[1] != "Y") + + if (!float.TryParse(offset[2], out float value)) + { + Debug.WriteLine($"Failed to parse y offset for: '{name}'"); + } + return new ModelOffset(name, value); + } + + public (string, string) ToProperty() + { + string value = $"{Name} Y {Value}"; + return ("OFFSET", value.Replace(',', '.')); + } + } +} \ No newline at end of file diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 8f9c9719..66b4c602 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -137,8 +137,10 @@ + + diff --git a/PCK-Studio/Rendering/CubeRenderGroup.cs b/PCK-Studio/Rendering/CubeRenderGroup.cs index f0ae4af3..7b705ec3 100644 --- a/PCK-Studio/Rendering/CubeRenderGroup.cs +++ b/PCK-Studio/Rendering/CubeRenderGroup.cs @@ -31,14 +31,22 @@ namespace PckStudio.Rendering { private List cubes; + internal float Scale { get; set; } = 1f; + internal CubeRenderGroup(string name) : base(name, PrimitiveType.Quads) { cubes = new List(5); } + internal CubeRenderGroup(string name, float scale) + : this(name) + { + Scale = scale; + } + internal void AddSkinBox(SkinBOX skinBox) { - AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + 1f, skinBox.Mirror, skinBox.Type == "HEAD"); + AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + Scale, skinBox.Mirror, skinBox.Type == "HEAD"); } internal void Clear() diff --git a/PCK-Studio/Rendering/SkinRenderer.Designer.cs b/PCK-Studio/Rendering/SkinRenderer.Designer.cs index 90b82221..05bc02c7 100644 --- a/PCK-Studio/Rendering/SkinRenderer.Designer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.Designer.cs @@ -45,11 +45,12 @@ namespace PckStudio.Rendering // moveTimer // this.moveTimer.Enabled = true; - this.moveTimer.Interval = 10; + this.moveTimer.Interval = 1; this.moveTimer.Tick += new System.EventHandler(this.moveTimer_Tick); // // animationTimer // + this.animationTimer.Enabled = true; this.animationTimer.Interval = 50; this.animationTimer.Tick += new System.EventHandler(this.animationTimer_Tick); // diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index e4b8ca36..08f67572 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -67,10 +67,6 @@ namespace PckStudio.Rendering remove => Events.RemoveHandler(nameof(TextureChanging), value); } - - [Description("Anim flags for special effects applied to the skin")] - [Category("Appearance")] - [Browsable(true)] public SkinANIM ANIM { get => _anim; @@ -81,13 +77,9 @@ namespace PckStudio.Rendering } } - [Description("Additional model data")] - [Category("Appearance")] public ObservableCollection ModelData { get; } - [Description("The offset from the origin point")] - [Category("Appearance")] - public Vector2 CameraTarget + private Vector2 CameraTarget { get => camera.Position; set @@ -153,30 +145,32 @@ namespace PckStudio.Rendering private Image _texture; private Dictionary additionalModelRenderGroups; - + private Dictionary partOffset; private CubeRenderGroup head; - private CubeRenderGroup headOverlay; private CubeRenderGroup body; - private CubeRenderGroup bodyOverlay; private CubeRenderGroup rightArm; - private CubeRenderGroup rightArmOverlay; private CubeRenderGroup leftArm; - private CubeRenderGroup leftArmOverlay; private CubeRenderGroup rightLeg; - private CubeRenderGroup rightLegOverlay; private CubeRenderGroup leftLeg; + + private CubeRenderGroup headOverlay; + private CubeRenderGroup bodyOverlay; + private CubeRenderGroup rightArmOverlay; + private CubeRenderGroup leftArmOverlay; + private CubeRenderGroup rightLegOverlay; private CubeRenderGroup leftLegOverlay; - private float animationRot; - private float animationRotStep = 0.05f; + private float animationCurrentRotationAngle; + private float animationRotationStep = 0.5f; + private float animationMaxAngleInDegrees = 5f; #if DEBUG private bool showWireFrame = false; internal Matrix4 HeadMatrix { get; set; } = Matrix4.Identity; internal Matrix4 BodyMatrix { get; set; } = Matrix4.Identity; - internal Matrix4 RightArmMatrix { get; set; } = Matrix4.Identity; - internal Matrix4 LeftArmMatrix { get; set; } = Matrix4.Identity; + internal Matrix4 RightArmMatrix { get; set; } = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, 25f); + internal Matrix4 LeftArmMatrix { get; set; } = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, -25f); internal Matrix4 RightLegMatrix { get; set; } = Matrix4.Identity; internal Matrix4 LeftLegMatrix { get; set; } = Matrix4.Identity; #endif @@ -190,14 +184,12 @@ namespace PckStudio.Rendering ModelData.CollectionChanged += ModelData_CollectionChanged; additionalModelRenderGroups = new Dictionary(6) { - { "HEAD", head }, - { "BODY", body }, - { "BODYARMOR",new CubeRenderGroup("BODYARMOR") }, - { "ARM0", rightArm }, - { "ARM1", leftArm }, - { "BELT", new CubeRenderGroup("BELT") }, - { "LEG0", rightLeg }, - { "LEG1", leftLeg }, + { "HEAD", head }, + { "BODY", body }, + { "ARM0", rightArm }, + { "ARM1", leftArm }, + { "LEG0", rightLeg }, + { "LEG1", leftLeg }, { "HEADWEAR", headOverlay }, { "JACKET" , bodyOverlay }, @@ -205,7 +197,50 @@ namespace PckStudio.Rendering { "SLEEVE1" , leftArmOverlay }, { "PANTS0" , rightLegOverlay }, { "PANTS1" , leftLegOverlay }, + + { "BODYARMOR", new CubeRenderGroup("BODYARMOR") }, + { "BELT", new CubeRenderGroup("BELT") }, }; + + partOffset = new Dictionary() + { + { "HEAD", 0f }, + { "BODY", 0f }, + { "ARM0", 0f }, + { "ARM1", 0f }, + { "LEG0", 0f }, + { "LEG1", 0f }, + + { "HEADWEAR" , 0f }, + { "JACKET" , 0f }, + { "SLEEVE0" , 0f }, + { "SLEEVE1" , 0f }, + { "PANTS0" , 0f }, + { "PANTS1" , 0f }, + + { "BODYARMOR", 0f }, + { "BELT" , 0f }, + }; + } + + public void SetPartOffset(ModelOffset offset) + { + SetPartOffset(offset.Name, offset.Value); + } + + public void SetPartOffset(string name, float value) + { + if (!partOffset.ContainsKey(name)) + { + Debug.WriteLine($"'{name}' is not inside {nameof(partOffset)}"); + return; + } + partOffset[name] = value; + } + + private float GetOffset(string name) + { + return partOffset.ContainsKey(name) ? partOffset[name] : 0f; } private void ModelData_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) @@ -234,7 +269,7 @@ namespace PckStudio.Rendering head.AddCube(new(-4, -8, -4), new(8, 8, 8), new(0, 0), flipZMapping: true); head.Submit(); - headOverlay ??= new CubeRenderGroup("Head Overlay"); + headOverlay ??= new CubeRenderGroup("Head Overlay", OverlayScale); headOverlay.AddCube(new(-4, -8, -4), new(8, 8, 8), new(32, 0), flipZMapping: true, scale: OverlayScale); headOverlay.Submit(); @@ -242,7 +277,7 @@ namespace PckStudio.Rendering body.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 16)); body.Submit(); - bodyOverlay ??= new CubeRenderGroup("Body Overlay"); + bodyOverlay ??= new CubeRenderGroup("Body Overlay", OverlayScale); bodyOverlay.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale); bodyOverlay.Submit(); @@ -250,7 +285,7 @@ namespace PckStudio.Rendering rightArm.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 16)); rightArm.Submit(); - rightArmOverlay ??= new CubeRenderGroup("Right Arm Overlay"); + rightArmOverlay ??= new CubeRenderGroup("Right Arm Overlay", OverlayScale); rightArmOverlay.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); rightArmOverlay.Submit(); @@ -258,7 +293,7 @@ namespace PckStudio.Rendering leftArm.AddCube(new(-1, -2, -2), new(4, 12, 4), new(32, 48)); leftArm.Submit(); - leftArmOverlay ??= new CubeRenderGroup("Left Arm Overlay"); + leftArmOverlay ??= new CubeRenderGroup("Left Arm Overlay", OverlayScale); leftArmOverlay.AddCube(new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale); leftArmOverlay.Submit(); @@ -266,7 +301,7 @@ namespace PckStudio.Rendering rightLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 16)); rightLeg.Submit(); - rightLegOverlay ??= new CubeRenderGroup("Right Leg Overlay"); + rightLegOverlay ??= new CubeRenderGroup("Right Leg Overlay", OverlayScale); rightLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 32), scale: OverlayScale); rightLegOverlay.Submit(); @@ -274,7 +309,7 @@ namespace PckStudio.Rendering leftLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(16, 48)); leftLeg.Submit(); - leftLegOverlay ??= new CubeRenderGroup("Left Leg Overlay"); + leftLegOverlay ??= new CubeRenderGroup("Left Leg Overlay", OverlayScale); leftLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: OverlayScale); leftLegOverlay.Submit(); } @@ -435,7 +470,7 @@ namespace PckStudio.Rendering MakeCurrent(); - camera.Update(Size.Width / (float)Size.Height); + camera.Update(ClientSize.Width / (float)ClientSize.Height); var viewProjection = camera.GetViewProjection(); _skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection); @@ -444,12 +479,13 @@ namespace PckStudio.Rendering GL.Viewport(Size); GL.ClearColor(BackColor); - GL.Clear(ClearBufferMask.ColorBufferBit); - GL.Clear(ClearBufferMask.DepthBufferBit); + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Enable(EnableCap.Texture2D); // Enable textures + GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings GL.DepthFunc(DepthFunction.Lequal); // Enable correct Z Drawings + GL.DepthMask(true); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); @@ -463,44 +499,41 @@ namespace PckStudio.Rendering bool slimModel = ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL); - const float rotationAngle = 2.5f; - var extraLegRightRotation = Matrix4.Identity; - var extraLegLeftRotation = Matrix4.Identity; - var extraArmRightRotation = Matrix4.Identity; - var extraArmLeftRotation = Matrix4.Identity; + var legRightMatrix = Matrix4.Identity; + var legLeftMatrix = Matrix4.Identity; + var armRightMatrix = Matrix4.Identity; + var armLeftMatrix = Matrix4.Identity; if (!ANIM.GetFlag(SkinAnimFlag.STATIC_ARMS)) { - extraArmRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(-rotationAngle)) * - Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(-animationRot)); - extraArmLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(rotationAngle)) * - Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(animationRot)); + armRightMatrix = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(animationCurrentRotationAngle)); + armLeftMatrix = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-animationCurrentRotationAngle)); } if (!ANIM.GetFlag(SkinAnimFlag.STATIC_LEGS)) { - extraLegRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-rotationAngle)); - extraLegLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(rotationAngle)); + legRightMatrix = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-animationCurrentRotationAngle)); + legLeftMatrix = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(animationCurrentRotationAngle)); } if (ANIM.GetFlag(SkinAnimFlag.ZOMBIE_ARMS)) { var rotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); - extraArmRightRotation *= rotation; - extraArmLeftRotation *= rotation; + armRightMatrix = rotation; + armLeftMatrix = rotation; } if (ANIM.GetFlag(SkinAnimFlag.STATUE_OF_LIBERTY)) { - extraArmRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-180f)); + armRightMatrix = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-180f)); } RenderBodyPart(new Vector3(0f, 0f, 0f), Vector3.Zero, HeadMatrix, modelMatrix, "HEAD", "HEADWEAR"); RenderBodyPart(new Vector3(0f, 0f, 0f), Vector3.Zero, BodyMatrix, modelMatrix, "BODY", "JACKET"); - RenderBodyPart(new Vector3(0f, 2f, 0f), new Vector3(slimModel ? -4f : -5f, -2f, 0f), RightArmMatrix * extraArmRightRotation, modelMatrix, "ARM0", "SLEEVE0"); - RenderBodyPart(new Vector3(0f, 2f, 0f), new Vector3( 5f, -2f, 0f), LeftArmMatrix * extraArmLeftRotation, modelMatrix, "ARM1", "SLEEVE1"); - RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3(-2f, -12f, 0f), RightLegMatrix * extraLegRightRotation, modelMatrix, "LEG0", "PANTS0"); - RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3( 2f, -12f, 0f), LeftLegMatrix * extraLegLeftRotation, modelMatrix, "LEG1", "PANTS1"); + RenderBodyPart(new Vector3( 4f, 2f, 0f), new Vector3(slimModel ? -4f : -5f, -2f, 0f), RightArmMatrix * armRightMatrix, modelMatrix, "ARM0", "SLEEVE0"); + RenderBodyPart(new Vector3(-4f, 2f, 0f), new Vector3( 5f, -2f, 0f), LeftArmMatrix * armLeftMatrix , modelMatrix, "ARM1", "SLEEVE1"); + RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3(-2f, -12f, 0f), RightLegMatrix * legRightMatrix, modelMatrix, "LEG0", "PANTS0"); + RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3( 2f, -12f, 0f), LeftLegMatrix * legLeftMatrix , modelMatrix, "LEG1", "PANTS1"); SwapBuffers(); } @@ -516,6 +549,9 @@ namespace PckStudio.Rendering private void RenderPart(string name, Vector3 pivot, Vector3 translation, Matrix4 rotation, Matrix4 globalMatrix) { CubeRenderGroup renderGroup = additionalModelRenderGroups[name]; + float yOffset = GetOffset(name); + translation.Y -= yOffset; + pivot.Y += yOffset; renderGroup.Submit(); RenderBuffer buffer = renderGroup.GetRenderBuffer(); var model = Matrix4.CreateTranslation(translation); @@ -570,11 +606,9 @@ namespace PckStudio.Rendering if (!Focused) return; - const float angle = 2f; - - animationRot += animationRotStep; - if (animationRot > angle || animationRot < -angle) - animationRotStep = -animationRotStep; + animationCurrentRotationAngle += animationRotationStep; + if (animationCurrentRotationAngle >= animationMaxAngleInDegrees || animationCurrentRotationAngle <= -animationMaxAngleInDegrees) + animationRotationStep = -animationRotationStep; Refresh(); } @@ -632,7 +666,7 @@ namespace PckStudio.Rendering /// /// Captures the currently displayed frame /// - /// Thumbnail of the cameras current view space + /// Image of the cameras current view public Image GetThumbnail() { Bitmap bmp = new Bitmap(Width, Height); diff --git a/PCK-Studio/ToolboxItems/InterpolationPictureBox.cs b/PCK-Studio/ToolboxItems/InterpolationPictureBox.cs index 3da28235..ad80b8d3 100644 --- a/PCK-Studio/ToolboxItems/InterpolationPictureBox.cs +++ b/PCK-Studio/ToolboxItems/InterpolationPictureBox.cs @@ -9,6 +9,15 @@ namespace PckStudio.ToolboxItems public class InterpolationPictureBox : PictureBox { public InterpolationMode InterpolationMode { get; set; } + + public InterpolationMode BackgroundInterpolationMode { get; set; } + + protected override void OnPaintBackground(PaintEventArgs paintEventArgs) + { + paintEventArgs.Graphics.InterpolationMode = BackgroundInterpolationMode; + paintEventArgs.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + base.OnPaintBackground(paintEventArgs); + } protected override void OnPaint(PaintEventArgs paintEventArgs) {