From 6376d709c082e8abf289545d5e2aac32e993209a Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Sun, 29 Oct 2023 12:15:10 +0100 Subject: [PATCH] Improved SkinRenderer.cs - Fixed mouse getting stuck when lossing focus of the window --- PCK-Studio/Extensions/CursorExtensions.cs | 51 ++ PCK-Studio/PckStudio.csproj | 1 + PCK-Studio/Rendering/SkinRenderer.Designer.cs | 10 +- PCK-Studio/Rendering/SkinRenderer.cs | 445 ++++++++++++------ 4 files changed, 350 insertions(+), 157 deletions(-) create mode 100644 PCK-Studio/Extensions/CursorExtensions.cs diff --git a/PCK-Studio/Extensions/CursorExtensions.cs b/PCK-Studio/Extensions/CursorExtensions.cs new file mode 100644 index 00000000..2739674c --- /dev/null +++ b/PCK-Studio/Extensions/CursorExtensions.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PckStudio.Extensions +{ + internal static class CursorExtensions + { + + [StructLayout(LayoutKind.Sequential)] + struct PointStruct + { + public Int32 x; + public Int32 y; + } + + [StructLayout(LayoutKind.Sequential)] + struct CursorInfoStruct + { + /// The structure size in bytes that must be set via calling Marshal.SizeOf(typeof(CursorInfoStruct)). + public Int32 cbSize; + /// The cursor state: 0 == hidden, 1 == showing, 2 == suppressed (is supposed to be when finger touch is used, but in practice finger touch results in 0, not 2) + public Int32 flags; + /// A handle to the cursor. + public IntPtr hCursor; + /// The cursor screen coordinates. + public PointStruct pt; + } + + /// Must initialize cbSize + [DllImport("user32.dll")] + static extern bool GetCursorInfo(ref CursorInfoStruct pci); + + public static bool IsVisible(this Cursor _) + { + CursorInfoStruct pci = new CursorInfoStruct(); + pci.cbSize = Marshal.SizeOf(typeof(CursorInfoStruct)); + GetCursorInfo(ref pci); + // const Int32 hidden = 0x00; + const Int32 showing = 0x01; + // const Int32 suppressed = 0x02; + bool isVisible = ((pci.flags & showing) != 0); + return isVisible; + } + + } +} diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 20d3ecc4..f181fb8a 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -135,6 +135,7 @@ + diff --git a/PCK-Studio/Rendering/SkinRenderer.Designer.cs b/PCK-Studio/Rendering/SkinRenderer.Designer.cs index a930ab2f..07aaebae 100644 --- a/PCK-Studio/Rendering/SkinRenderer.Designer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.Designer.cs @@ -36,17 +36,25 @@ namespace PckStudio.Rendering { components = new System.ComponentModel.Container(); moveTimer = new System.Windows.Forms.Timer(components); - moveTimer.Tick += new EventHandler(Move_Tick); + animationTimer = new System.Windows.Forms.Timer(components); + moveTimer.Tick += new EventHandler(moveTimer_Tick); + animationTimer.Tick += new EventHandler(animationTimer_Tick); SuspendLayout(); // // moveTimer // moveTimer.Enabled = true; moveTimer.Interval = 10; + // + // animationTimer + // + animationTimer.Enabled = false; + animationTimer.Interval = 50; Name = "Renderer3D"; ResumeLayout(false); } private System.Windows.Forms.Timer moveTimer; + private System.Windows.Forms.Timer animationTimer; } } diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index 00990b1b..0931a486 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -6,8 +6,6 @@ using System.Text; using System.Threading.Tasks; using OpenTK; using PckStudio.Internal; -using static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab; -using System.Windows.Media.Media3D; using PckStudio.Extensions; using OpenTK.Graphics.OpenGL; using System.Windows.Forms; @@ -15,6 +13,7 @@ using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using PckStudio.Properties; +using PckStudio.Forms.Editor; namespace PckStudio.Rendering { @@ -31,32 +30,44 @@ namespace PckStudio.Rendering get => _texture; set { - if (skinShader is not null) + if (value is null) + return; + + if (HasValidContext && skinShader is not null) { var texture = new Texture2D(value); texture.Bind(0); skinShader.SetUniform1("u_Texture", 0); Refresh(); } - TextureScaleValue = new Vector2(1f / value.Width, 1f / value.Height); _texture = value; } } - private Vector2 _lookAngle = Vector2.Zero; + [Description("Anim flags for special effects applied to the skin")] + [Category("Appearance")] + public SkinANIM ANIM + { + get => _anim; + set + { + _anim = value; + OnANIMUpdate(); + } + } + + [Description("Additional model data")] + [Category("Appearance")] + public List ModelData { get; } = new List(); + [Description("The offset from the orignal point (for zoom)")] [Category("Appearance")] public Vector2 LookAngle { - get => _lookAngle; - set - { - _lookAngle = value; - camera.LookAt(value); - } + get => camera.Position; + set => camera.LookAt(value); } - private Vector2 TextureScaleValue = new Vector2(1f / 64); private void GLDebugMessage(DebugSource source, DebugType type, int id, DebugSeverity severity, int length, IntPtr message, IntPtr userParam) { @@ -68,31 +79,108 @@ namespace PckStudio.Rendering Debug.WriteLine(msg); } - private Vector2 _modelRotation; - private Vector2 modelRotation + private Vector2 _globalModelRotation; + private Vector2 GlobalModelRotation { - get => _modelRotation; + get => _globalModelRotation; set { - _modelRotation.X = MathHelper.Clamp(value.X, -5f, 5f); - _modelRotation.Y = MathHelper.Clamp(value.Y, -180f, 180f); + _globalModelRotation.X = MathHelper.Clamp(value.X, -90f, 90f); + _globalModelRotation.Y = MathHelper.Clamp(value.Y, -180f, 180f); } } - private bool IsMouseDown; + private Bitmap _texture; + private Vector2 TextureScaleValue = new Vector2(1f / 64); + private const float OverlayScale = 0.1f; + + private bool IsLeftMouseDown; private bool IsRightMouseDown; - private bool IsMouseHidden; + private bool IsMouseHidden + { + get => !Cursor.IsVisible(); + set + { + if (value) + { + Cursor.Hide(); + return; + } + Cursor.Show(); + } + } private Point PreviousMouseLocation; private Point MouseLoc; + private Shader skinShader; + private SkinANIM _anim; - private Dictionary renderGroups; + private Dictionary defaultRenderGroups; + private Dictionary additionalModelRenderGroups; - private Bitmap _texture; + + private float animationRot; + private float animationRotStep = 1f; public SkinRenderer() { InitializeComponent(); + InitializeCamera(); + _anim = new SkinANIM(); // use backing field to not raise OnANIMUpdate + defaultRenderGroups = new Dictionary(6) + { + { "HEAD", new RenderGroup("HEAD") }, + { "BODY", new RenderGroup("BODY") }, + { "ARM0", new RenderGroup("ARM0") }, + { "ARM1", new RenderGroup("ARM1") }, + { "LEG0", new RenderGroup("LEG0") }, + { "LEG1", new RenderGroup("LEG1") }, + + { "HEADWEAR", new RenderGroup("HEADWEAR") }, + { "JACKET", new RenderGroup("JACKET")}, + { "SLEEVE0", new RenderGroup("SLEEVE0")}, + { "SLEEVE1", new RenderGroup("SLEEVE1")}, + { "LEGGING0", new RenderGroup("LEGGING0")}, + { "LEGGING1", new RenderGroup("LEGGING1")}, + + //{ "PANTS0", new RenderGroup("PANTS0")}, + //{ "PANTS1", new RenderGroup("PANTS1")}, + //{ "WAIST", new RenderGroup("WAIST")}, + //{ "SOCK0", new RenderGroup("SOCK0")}, + //{ "SOCK1", new RenderGroup("SOCK1")}, + //{ "BOOT0", new RenderGroup("BOOT0")}, + //{ "BOOT1", new RenderGroup("BOOT1")}, + //{ "ARMARMOR1", new RenderGroup("ARMARMOR1")}, + //{ "ARMARMOR0", new RenderGroup("ARMARMOR0")}, + //{ "BODYARMOR", new RenderGroup("BODYARMOR")}, + //{ "BELT", new RenderGroup("BELT")}, + }; + additionalModelRenderGroups = new Dictionary(6) + { + { "HEAD", new RenderGroup("HEAD") }, + { "BODY", new RenderGroup("BODY") }, + { "ARM0", new RenderGroup("ARM0") }, + { "ARM1", new RenderGroup("ARM1") }, + { "LEG0", new RenderGroup("LEG0") }, + { "LEG1", new RenderGroup("LEG1") }, + + { "HEADWEAR", new RenderGroup("HEADWEAR") }, + { "JACKET", new RenderGroup("JACKET")}, + { "SLEEVE0", new RenderGroup("SLEEVE0")}, + { "SLEEVE1", new RenderGroup("SLEEVE1")}, + { "LEGGING0", new RenderGroup("LEGGING0")}, + { "LEGGING1", new RenderGroup("LEGGING1")}, + }; + } + + private void InitializeCamera() + { + const float distance = 36f; + camera = new PerspectiveCamera(new Vector2(0f, 5f), distance, Vector2.Zero, 60f) + { + MinimumFov = 30f, + MaximumFov = 90f, + }; } protected override void OnLoad(EventArgs e) @@ -102,55 +190,70 @@ namespace PckStudio.Rendering return; MakeCurrent(); - camera = new Camera(new Vector2(0f, 1f), 36f, Vector2.Zero, 60f); - - camera.MinimumFov = 30f; - camera.MaximumFov = 90f; - - camera.LookAt(new Vector2(0f, 5f)); + Trace.TraceInformation(GL.GetString(StringName.Version)); GL.DebugMessageCallback(GLDebugMessage, IntPtr.Zero); - Trace.TraceInformation(GL.GetString(StringName.Version)); - skinShader = Shader.Create(Resources.skinVertexShader, Resources.skinFragment); skinShader.Bind(); - Texture = Resources.slim_template; - - renderGroups = new Dictionary(6) + if (_texture is null) { - { "HEAD", new RenderGroup("HEAD") }, - { "BODY", new RenderGroup("BODY") }, - { "ARM0", new RenderGroup("ARM0") }, - { "ARM1", new RenderGroup("ARM1") }, - { "LEG0", new RenderGroup("LEG0") }, - { "LEG1", new RenderGroup("LEG1") } - }; + Texture = Resources.classic_template; + if (Texture.Size == new Size(64, 64)) + { + ANIM.SetFlag(SkinAnimFlag.RESOLUTION_64x64, true); + } + } - var headbox = new SkinBOX("HEAD", new(-4, -8, -4), new(8, 8, 8), new( 0, 0)); - var bodybox = new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16)); - var arm0box = new SkinBOX("ARM0", new(-3, -2, -2), new(4, 12, 4), new(40, 16)); - var arm1box = new SkinBOX("ARM1", new(-1, -2, -2), new(4, 12, 4), new(32, 48)); - var leg0box = new SkinBOX("LEG0", new(-2, 0, -2), new(4, 12, 4), new( 0, 16)); - var leg1box = new SkinBOX("LEG1", new(-2, 0, -2), new(4, 12, 4), new(16, 48)); + var headbox = new SkinBOX("HEAD", new(-4, -8, -4), new(8, 8, 8), new( 0, 0)); + var headoverlaybox = new SkinBOX("HEADWEAR", new(-4, -8, -4), new(8, 8, 8), new(32, 0), scale: OverlayScale); + var bodybox = new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16)); + var bodyoverlaybox = new SkinBOX("JACKET", new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale); + var arm0box = new SkinBOX("ARM0", new(-3, -2, -2), new(4, 12, 4), new(40, 16)); + var arm1box = new SkinBOX("ARM1", new(-1, -2, -2), new(4, 12, 4), new(32, 48)); + var arm0overlaybox = new SkinBOX("SLEEVE0", new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); + var arm1overlaybox = new SkinBOX("SLEEVE1", new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale); + var leg0box = new SkinBOX("LEG0", new(-2, 0, -2), new(4, 12, 4), new( 0, 16)); + var leg0overlaybox = new SkinBOX("LEGGING0", new(-2, 0, -2), new(4, 12, 4), new( 0, 32), scale: OverlayScale); + var leg1box = new SkinBOX("LEG1", new(-2, 0, -2), new(4, 12, 4), new(16, 48)); + var leg1overlaybox = new SkinBOX("LEGGING1", new(-2, 0, -2), new(4, 12, 4), new( 0, 48), scale: OverlayScale); - AddGroup(headbox, TextureScaleValue); - AddGroup(bodybox, TextureScaleValue); - AddGroup(arm0box, TextureScaleValue); - AddGroup(arm1box, TextureScaleValue); - AddGroup(leg0box, TextureScaleValue); - AddGroup(leg1box, TextureScaleValue); + AddToGroup(headbox); + AddToGroup(headoverlaybox); + AddToGroup(bodybox); + AddToGroup(bodyoverlaybox); + AddToGroup(arm0box); + AddToGroup(arm0overlaybox); + AddToGroup(arm1box); + AddToGroup(arm1overlaybox); + AddToGroup(leg0box); + AddToGroup(leg0overlaybox); + AddToGroup(leg1box); + AddToGroup(leg1overlaybox); + + foreach (var item in ModelData) + { + AddCustomModelPart(item); + } GLErrorCheck(); } - private void AddGroup(SkinBOX skinBox, Vector2 textureScaleValue) + private void AddCustomModelPart(SkinBOX skinBox) { - if (!renderGroups.ContainsKey(skinBox.Type)) + if (!additionalModelRenderGroups.ContainsKey(skinBox.Type)) throw new KeyNotFoundException(skinBox.Type); - renderGroups[skinBox.Type].AddBox(skinBox, textureScaleValue); + additionalModelRenderGroups[skinBox.Type].AddBox(skinBox); + } + + private void AddToGroup(SkinBOX skinBox) + { + if (!defaultRenderGroups.ContainsKey(skinBox.Type)) + throw new KeyNotFoundException(skinBox.Type); + + defaultRenderGroups[skinBox.Type].AddBox(skinBox); } [Conditional("DEBUG")] @@ -160,69 +263,19 @@ namespace PckStudio.Rendering Debug.Assert(error == ErrorCode.NoError, error.ToString()); } - private RenderBuffer GetBox3D(SkinBOX skinBOX) - { - return GetBox3D(skinBOX.Pos.ToOpenTKVector(), skinBOX.Size.ToOpenTKVector(), skinBOX.UV.ToOpenTKVector()); - } - - private RenderBuffer GetBox3D(Vector3 position, Vector3 size, Vector2 uv) - { - var vertexData = new TextureVertex[] - { - new TextureVertex(new Vector3(position.X , size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z + size.Y) * TextureScaleValue), - new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y) * TextureScaleValue), - - new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z + size.Y) * TextureScaleValue), - new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z + size.Y) * TextureScaleValue), - - new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z + size.Y) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * TextureScaleValue), - new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z, uv.Y) * TextureScaleValue), - - new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y) * TextureScaleValue), - new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y + size.Z) * TextureScaleValue), - new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * TextureScaleValue), - }; - - var indexBuffer = new IndexBuffer( - 0, 1, 2, 3, // Face 1 (Front) - 4, 5, 6, 7, // Face 2 (Back) - 0, 8, 9, 3, // Face 3 (Left) - 1, 5, 6, 2, // Face 4 (Right) - 0, 1, 10, 11, // Face 5(Top) - 12, 13, 14, 15 // Face 6 (Bottom) - ); - - var buffer = new VertexBuffer(vertexData, vertexData.Length * TextureVertex.SizeInBytes); - var layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); - layout.Add(2); - - var vertexArray = new VertexArray(); - - vertexArray.AddBuffer(buffer, layout); - - return new RenderBuffer(vertexArray, indexBuffer, PrimitiveType.Quads); - } - - private Matrix4 GetModelFromSkinBOX(SkinBOX skinBox) - { - return Matrix4.CreateTranslation(skinBox.Pos.ToOpenTKVector()) * Matrix4.CreateScale(skinBox.Scale); - } - protected override bool ProcessDialogKey(Keys keyData) { switch (keyData) { + case Keys.Escape: + if (IsMouseHidden || IsLeftMouseDown || IsRightMouseDown) + { + IsMouseHidden = IsRightMouseDown = IsLeftMouseDown = false; + Cursor.Position = PreviousMouseLocation; + } + break; case Keys.R: - modelRotation = Vector2.Zero; + GlobalModelRotation = Vector2.Zero; LookAngle = Vector2.Zero; Refresh(); return true; @@ -236,10 +289,48 @@ namespace PckStudio.Rendering Texture = Image.FromFile(fileDialog.FileName) as Bitmap; } return true; + case Keys.F3: + + return true; + case Keys.A: + { + using var animeditor = new ANIMEditor(ANIM); + if (animeditor.ShowDialog() == DialogResult.OK) + { + ANIM = animeditor.ResultAnim; + Refresh(); + } + } + return true; } return base.ProcessDialogKey(keyData); } + private void OnANIMUpdate() + { + bool slim = ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL); + if (slim || ANIM.GetFlag(SkinAnimFlag.RESOLUTION_64x64)) + { + int slimValue = slim ? 3 : 4; + TextureScaleValue = new Vector2(1f / 64); + defaultRenderGroups["ARM0"].ReplaceBox(0, new(-3, -2, -2), new(slimValue, 12, 4), new(40, 16)); + defaultRenderGroups["ARM1"].ReplaceBox(0, new(-1, -2, -2), new(slimValue, 12, 4), new(32, 48)); + defaultRenderGroups["SLEEVE0"].ReplaceBox(0, new(-3, -2, -2), new(slimValue, 12, 4), new(40, 32), scale: OverlayScale); + defaultRenderGroups["SLEEVE1"].ReplaceBox(0, new(-1, -2, -2), new(slimValue, 12, 4), new(48, 48), scale: OverlayScale); + + defaultRenderGroups["LEG0"].ReplaceBox(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); + defaultRenderGroups["LEG1"].ReplaceBox(0, new(-2, 0, -2), new(4, 12, 4), new(16, 48)); + return; + } + TextureScaleValue = new Vector2(1f / 64, 1f / 32); + defaultRenderGroups["ARM0"].ReplaceBox(0, new(-3, -2, -2), new(4, 12, 4), new(40, 16)); + defaultRenderGroups["ARM1"].ReplaceBox(0, new(-1, -2, -2), new(4, 12, 4), new(40, 16)); + defaultRenderGroups["LEG0"].ReplaceBox(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); + defaultRenderGroups["LEG1"].ReplaceBox(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); + defaultRenderGroups["SLEEVE0"].ReplaceBox(0, new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); + defaultRenderGroups["SLEEVE1"].ReplaceBox(0, new(-1, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); + } + protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); @@ -248,12 +339,13 @@ namespace PckStudio.Rendering return; } - MakeCurrent(); + MakeCurrent(); camera.Update(Size.Width / (float)Size.Height); var viewProjection = camera.GetViewProjection(); skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection); + skinShader.SetUniform2("u_TexScale", TextureScaleValue); GL.Viewport(Size); @@ -272,48 +364,74 @@ namespace PckStudio.Rendering GL.Enable(EnableCap.AlphaTest); // Enable transparent GL.AlphaFunc(AlphaFunction.Greater, 0.4f); - Matrix4 transform = Matrix4.CreateTranslation(new Vector3(0f, 16f, 0f)); - Matrix4 rotation = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(modelRotation.X)) - * Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(modelRotation.Y)); + Matrix4 modelRotationMatrix = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(GlobalModelRotation.X)) + * Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(GlobalModelRotation.Y)); + + + RenderSkinPartIf("HEAD" , !ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED), new Vector3(0f, 16f, 0f), modelRotationMatrix); + RenderSkinPartIf("HEADWEAR", !ANIM.GetFlag(SkinAnimFlag.HEAD_OVERLAY_DISABLED), new Vector3(0f, 16f + OverlayScale, 0f), modelRotationMatrix); - var model = transform * rotation; + RenderSkinPartIf("BODY" , !ANIM.GetFlag(SkinAnimFlag.BODY_DISABLED), new Vector3(0f, -4f, 0f), modelRotationMatrix); + RenderSkinPartIf("JACKET", !ANIM.GetFlag(SkinAnimFlag.BODY_OVERLAY_DISABLED), new Vector3(0f, -4f + OverlayScale, 0f), modelRotationMatrix); - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["HEAD"].GetRenderBuffer()); + var extraRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(animationRot)); + var extraLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(-animationRot)); + var translationRight = new Vector3(ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL) ? -4f : -5f, -2f, 0f); + var translationLeft = new Vector3(5f, -2f, 0f); + if (ANIM.GetFlag(SkinAnimFlag.ZOMBIE_ARMS)) + { + extraRightRotation *= Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); + extraLeftRotation *= Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); + translationRight.Yz = translationLeft.Yz = new Vector2(-8f, 6f); + } - transform = Matrix4.CreateTranslation(new Vector3(0f, -4f, 0f)); - model = transform * rotation; + RenderSkinPartIf("ARM0" , !ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED) , translationRight, extraRightRotation * modelRotationMatrix); + RenderSkinPartIf("SLEEVE0", !ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_OVERLAY_DISABLED), translationRight, extraRightRotation * modelRotationMatrix); - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["BODY"].GetRenderBuffer()); + RenderSkinPartIf("ARM1" , !ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED) , translationLeft , extraLeftRotation * modelRotationMatrix); + RenderSkinPartIf("SLEEVE1", !ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_OVERLAY_DISABLED) , translationLeft , extraLeftRotation * modelRotationMatrix); + + RenderSkinPartIf("LEG0" , !ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED) , new Vector3(-2f, -16f, 0f), modelRotationMatrix); + RenderSkinPartIf("LEGGING0", !ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_OVERLAY_DISABLED), new Vector3(-2f, -16f, 0f), modelRotationMatrix); - transform = Matrix4.CreateTranslation(new Vector3(-5f, -2f, 0f)); - model = transform * rotation; - - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["ARM0"].GetRenderBuffer()); - - transform = Matrix4.CreateTranslation(new Vector3(5f, -2f, 0f)); - model = transform * rotation; - - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["ARM1"].GetRenderBuffer()); - - transform = Matrix4.CreateTranslation(new Vector3(-2f, -16f, 0f)); - model = transform * rotation; - - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["LEG0"].GetRenderBuffer()); - - transform = Matrix4.CreateTranslation(new Vector3(2f, -16f, 0f)); - model = transform * rotation; - - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, renderGroups["LEG1"].GetRenderBuffer()); + RenderSkinPartIf("LEG1" , !ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED) , new Vector3( 2f, -16f, 0f), modelRotationMatrix); + RenderSkinPartIf("LEGGING1", !ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_OVERLAY_DISABLED) , new Vector3( 2f, -16f, 0f), modelRotationMatrix); +#if flase + RenderAdditionalModelData("HEAD", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); + RenderAdditionalModelData("BODY", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); + RenderAdditionalModelData("ARM0", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); + RenderAdditionalModelData("ARM1", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); + RenderAdditionalModelData("LEG0", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); + RenderAdditionalModelData("LEG1", new Vector3(0f, 28f, 0f), /*Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(180f)) **/ modelRotationMatrix); +#endif SwapBuffers(); } + private void RenderSkinPartIf(string name, bool condition, Vector3 translation, Matrix4 rotation) + { + if (condition) + { + RenderSkinPart(name, translation, rotation); + } + } + + private void RenderSkinPart(string name, Vector3 translation, Matrix4 rotation) + { + var transform = Matrix4.CreateTranslation(translation); + var model = transform * rotation; + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, defaultRenderGroups[name].GetRenderBuffer()); + } + + private void RenderAdditionalModelData(string name, Vector3 translation, Matrix4 rotation) + { + var transform = Matrix4.CreateTranslation(translation); + var model = transform * rotation; + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, additionalModelRenderGroups[name].GetRenderBuffer()); + } + protected override void OnMouseWheel(MouseEventArgs e) { camera.Fov -= e.Delta / System.Windows.Input.Mouse.MouseWheelDeltaForOneLine; @@ -322,24 +440,22 @@ namespace PckStudio.Rendering protected override void OnMouseDown(MouseEventArgs e) { - if (!IsMouseDown && e.Button == MouseButtons.Left) + if (!IsLeftMouseDown && e.Button == MouseButtons.Left) { // If the ray didn't hit the model then rotate the model PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over if (!IsMouseHidden) // Hide the mouse { - Cursor.Hide(); IsMouseHidden = true; } MouseLoc = Cursor.Position; // Store the current mouse position to use it for the rotate action - IsMouseDown = true; + IsLeftMouseDown = true; } else if (!IsRightMouseDown && e.Button == MouseButtons.Right) { PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over if (!IsMouseHidden) // Hide the mouse { - Cursor.Hide(); IsMouseHidden = true; } MouseLoc = Cursor.Position; // Store the current mouse position to use it for the move action @@ -352,19 +468,36 @@ namespace PckStudio.Rendering if (IsMouseHidden) { Cursor.Position = PreviousMouseLocation; - IsMouseDown = IsMouseHidden = IsRightMouseDown = false; - Cursor.Show(); + IsMouseHidden = IsLeftMouseDown = IsRightMouseDown = false; } } - private void Move_Tick(object sender, EventArgs e) + private void animationTimer_Tick(object sender, EventArgs e) { + if (!Focused) + return; + + const float angle = 2f; + + animationRot += animationRotStep; + if (animationRot > angle || animationRot < -angle) + animationRotStep = -animationRotStep; + Refresh(); + } + + private void moveTimer_Tick(object sender, EventArgs e) + { + if (!Focused) + { + return; + } + // Rotate the model - if (IsMouseDown) + if (IsLeftMouseDown) { float rotationYDelta = (float)Math.Round((Cursor.Position.X - MouseLoc.X) * 0.5f); float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - MouseLoc.Y) * 0.5f); - modelRotation += new Vector2(rotationXDelta, rotationYDelta); + GlobalModelRotation += new Vector2(rotationXDelta, rotationYDelta); Refresh(); Cursor.Position = new Point((int)Math.Round(Screen.PrimaryScreen.Bounds.Width / 2d), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height / 2d)); MouseLoc = Cursor.Position; @@ -382,4 +515,4 @@ namespace PckStudio.Rendering } } } -} +} \ No newline at end of file