diff --git a/PCK-Studio/App.config b/PCK-Studio/App.config
index c3b1b2f6..732c8327 100644
--- a/PCK-Studio/App.config
+++ b/PCK-Studio/App.config
@@ -77,6 +77,9 @@
False
+
+ True
+
diff --git a/PCK-Studio/Classes/Models/BackgroundTypes.cs b/PCK-Studio/Classes/Models/BackgroundTypes.cs
deleted file mode 100644
index b460d046..00000000
--- a/PCK-Studio/Classes/Models/BackgroundTypes.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public enum BackgroundTypes
- {
- Color,
- Gradient,
- Texture
- }
-}
diff --git a/PCK-Studio/Classes/Models/Backgrounds.cs b/PCK-Studio/Classes/Models/Backgrounds.cs
deleted file mode 100644
index 692896bc..00000000
--- a/PCK-Studio/Classes/Models/Backgrounds.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public enum Backgrounds
- {
- LightStone,
- DarkStone,
- DaySky,
- NightSky,
- Sunset,
- Transparent
- }
-}
diff --git a/PCK-Studio/Classes/Models/Box.cs b/PCK-Studio/Classes/Models/Box.cs
deleted file mode 100644
index 23d64a9d..00000000
--- a/PCK-Studio/Classes/Models/Box.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-using System;
-using System.Drawing;
-
-namespace PckStudio.Models
-{
- public class Box : Object3D
- {
- public override Image Image
- {
- set
- {
- SetImage(value);
- }
- }
-
- internal override MinecraftModelView Viewport
- {
- set
- {
- base.Viewport = value;
- top.Viewport = value;
- bottom.Viewport = value;
- front.Viewport = value;
- back.Viewport = value;
- left.Viewport = value;
- right.Viewport = value;
- Update();
- }
- }
-
- internal override void Update()
- {
- Matrix3D a = globalTransformation * localTransformation;
- top.LocalTransformation = a * topLocalTransformation;
- bottom.LocalTransformation = a * bottomLocalTransformation;
- front.LocalTransformation = a * frontLocalTransformation;
- back.LocalTransformation = a * backLocalTransformation;
- left.LocalTransformation = a * leftLocalTransformation;
- right.LocalTransformation = a * rightLocalTransformation;
- }
-
- public Box(Image image, Rectangle srcTopBottom, Rectangle srcSides, Point3D origin, Effects effects = Effects.None)
- {
- this.effects = effects;
- Origin = origin;
- SetImage(image, srcTopBottom, srcSides);
- }
-
- private void SetImage(Image image, Rectangle srcTopBottom, Rectangle srcSides)
- {
- int num = srcTopBottom.Width / 2;
- int height = srcSides.Height;
- int height2 = srcTopBottom.Height;
- srcTop = new Rectangle(srcTopBottom.Location, new Size(num, height2));
- srcBottom = new Rectangle(srcTopBottom.X + num, srcTopBottom.Y, num, height2);
- srcFront = new Rectangle(srcSides.X + height2, srcSides.Y, num, height);
- srcBack = new Rectangle(srcSides.X + height2 + num + height2, srcSides.Y, num, height);
- srcLeft = new Rectangle(srcSides.Location, new Size(height2, height));
- srcRight = new Rectangle(srcSides.X + height2 + num, srcSides.Y, height2, height);
- SetImage(image);
- }
-
- private void SetImage(Image image)
- {
- bool flag = (byte)(effects & Effects.FlipHorizontally) == 1;
- bool flag2 = (byte)(effects & Effects.FlipVertically) == 2;
- int width = srcFront.Width;
- int height = srcFront.Height;
- int width2 = srcLeft.Width;
- top = new TexturePlane(image, flag2 ? srcBottom : srcTop, new Point3D(width * 0.5f, width2 * 0.5f, (float)(-(float)height) * 0.5f), new Point3D(0f, 1f, 0f), effects & Effects.FlipHorizontally);
- bottom = new TexturePlane(image, flag2 ? srcTop : srcBottom, new Point3D(width / 2f, width2 / 2f, height / 2f), new Point3D(0f, -1f, 0f), effects & Effects.FlipHorizontally);
- front = new TexturePlane(image, srcFront, new Point3D(width * 0.5f, height * 0.5f, (float)(-(float)width2) * 0.5f), new Point3D(0f, 0f, 1f), effects);
- back = new TexturePlane(image, srcBack, new Point3D(width * 0.5f, height * 0.5f, (float)(-(float)width2) * 0.5f), new Point3D(0f, 0f, -1f), effects);
- left = new TexturePlane(image, flag ? srcRight : srcLeft, new Point3D(width2 * 0.5f, height * 0.5f, (float)(-(float)width) * 0.5f), new Point3D(-1f, 0f, 0f), effects);
- right = new TexturePlane(image, flag ? srcLeft : srcRight, new Point3D(width2 * 0.5f, height * 0.5f, (float)(-(float)width) * 0.5f), new Point3D(1f, 0f, 0f), effects);
- top.Viewport = viewport;
- bottom.Viewport = viewport;
- front.Viewport = viewport;
- back.Viewport = viewport;
- left.Viewport = viewport;
- right.Viewport = viewport;
- }
-
- public override float HitTest(PointF location)
- {
- float num = -1000f;
- float num2 = top.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- num2 = bottom.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- num2 = front.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- num2 = back.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- num2 = left.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- num2 = right.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- return num;
- }
-
- private TexturePlane top;
-
- private TexturePlane bottom;
-
- private TexturePlane front;
-
- private TexturePlane back;
-
- private TexturePlane left;
-
- private TexturePlane right;
-
- private Rectangle srcTop;
-
- private Rectangle srcBottom;
-
- private Rectangle srcFront;
-
- private Rectangle srcBack;
-
- private Rectangle srcLeft;
-
- private Rectangle srcRight;
-
- private Matrix3D topLocalTransformation = Matrix3D.CreateRotationX(-1.57079637f);
-
- private Matrix3D bottomLocalTransformation = Matrix3D.CreateRotationX(-1.57079637f);
-
- private Matrix3D frontLocalTransformation = Matrix3D.Identity;
-
- private Matrix3D backLocalTransformation = Matrix3D.CreateRotationY(3.14159274f);
-
- private Matrix3D leftLocalTransformation = Matrix3D.CreateRotationY(-1.57079637f);
-
- private Matrix3D rightLocalTransformation = Matrix3D.CreateRotationY(1.57079637f);
-
- private Effects effects;
- }
-}
diff --git a/PCK-Studio/Classes/Models/DefaultModels/ModelBase.cs b/PCK-Studio/Classes/Models/DefaultModels/ModelBase.cs
deleted file mode 100644
index 66a759c9..00000000
--- a/PCK-Studio/Classes/Models/DefaultModels/ModelBase.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using PckStudio.Models;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Drawing;
-
-namespace PckStudio.Models
-{
- public abstract class ModelBase
- {
- public ModelBase()
- { }
-
- protected Image[] textures;
-
- public EventHandler OnUpdate;
- protected const float OverlayScale = 1.16f;
-
- public Image[] Textures => textures;
-
- public event EventHandler Updatedx
- {
- add
- {
- EventHandler eventHandler = OnUpdate;
- EventHandler eventHandler2;
- do
- {
- eventHandler2 = eventHandler;
- EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
- eventHandler = Interlocked.CompareExchange(ref OnUpdate, value2, eventHandler2);
- }
- while (eventHandler != eventHandler2);
- }
- remove
- {
- EventHandler eventHandler = OnUpdate;
- EventHandler eventHandler2;
- do
- {
- eventHandler2 = eventHandler;
- EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value);
- eventHandler = Interlocked.CompareExchange(ref OnUpdate, value2, eventHandler2);
- }
- while (eventHandler != eventHandler2);
- }
- }
-
- protected void OnUpdated()
- {
- if (OnUpdate != null)
- {
- OnUpdate(this, EventArgs.Empty);
- }
- }
-
- public abstract void AddToModelView(MinecraftModelView modelView);
- }
-}
diff --git a/PCK-Studio/Classes/Models/DefaultModels/Steve64x32Model.cs b/PCK-Studio/Classes/Models/DefaultModels/Steve64x32Model.cs
deleted file mode 100644
index 0af00dfc..00000000
--- a/PCK-Studio/Classes/Models/DefaultModels/Steve64x32Model.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-using System;
-using System.IO;
-using System.Drawing;
-using PckStudio.Models;
-using PckStudio.Properties;
-
-namespace PckStudio.Models
-{
- internal class Steve64x32Model : ModelBase
- {
- public Steve64x32Model(Image texture)
- {
- textures = new Image[1] { texture };
- }
-
- public override void AddToModelView(MinecraftModelView modelView)
- {
- _ = Textures[0] ?? throw new NullReferenceException(nameof(Textures));
- Image source = Textures[0];
- Box head = new Box(source, new Rectangle( 8, 0, 16, 8), new Rectangle( 0, 8, 32, 8), new Point3D(0f, 0f, 0f));
- Box headOverlay = new Box(source, new Rectangle(40, 0, 16, 8), new Rectangle(32, 8, 32, 8), new Point3D(0f, 0f, 0f));
- headOverlay.Scale = OverlayScale;
-
- Box body = new Box(source, new Rectangle(20, 16, 16, 4), new Rectangle(16, 20, 24, 12), new Point3D(0f, 0f, 0f));
-
- Box leftArm = new Box(source, new Rectangle(44, 16, 8, 4), new Rectangle(40, 20, 32, 12), new Point3D(0f, 4f, 0f));
- Box rightArm = new Box(source, new Rectangle(44, 16, 8, 4), new Rectangle(40, 20, 32, 12), new Point3D(0f, 4f, 0f));
-
- Box leftLeg = new Box(source, new Rectangle(4, 16, 8, 4), new Rectangle(0, 20, 16, 12), new Point3D(0f, 6f, 0f));
- Box rightLeg = new Box(source, new Rectangle(4, 16, 8, 4), new Rectangle(0, 20, 16, 12), new Point3D(0f, 6f, 0f));
-
- Object3DGroup headGroup = new Object3DGroup();
-
- headGroup.RotationOrder = RotationOrders.XY;
- headGroup.MinDegrees1 = -80f;
- headGroup.MaxDegrees1 = 80f;
-
- headGroup.MinDegrees2 = -57f;
- headGroup.MaxDegrees2 = 57f;
-
- headGroup.Add(head);
- headGroup.Add(headOverlay);
-
- headGroup.Position = new Point3D(0f, 8f, 0f);
- headGroup.Origin = new Point3D(0f, -4f, 0f);
- headGroup.RotationOrder = RotationOrders.XY;
-
- body.Position = new Point3D(0f, 2f, 0f);
-
- leftArm.Position = new Point3D(6f, 6f, 0f);
- leftArm.RotationOrder = RotationOrders.ZX;
- leftArm.MinDegrees1 = 0f;
- leftArm.MaxDegrees1 = 160f;
- leftArm.MinDegrees2 = -170f;
- leftArm.MaxDegrees2 = 60f;
-
- rightArm.Position = new Point3D(-6f, 6f, 0f);
- rightArm.RotationOrder = RotationOrders.ZX;
- rightArm.MinDegrees1 = -160f;
- rightArm.MaxDegrees1 = 0f;
- rightArm.MinDegrees2 = -170f;
- rightArm.MaxDegrees2 = 60f;
-
- leftLeg.Position = new Point3D(2f, -4f, 0f);
- leftLeg.RotationOrder = RotationOrders.ZX;
- leftLeg.MinDegrees1 = 0f;
- leftLeg.MaxDegrees1 = 70f;
- leftLeg.MinDegrees2 = -110f;
- leftLeg.MaxDegrees2 = 60f;
-
- rightLeg.Position = new Point3D(-2f, -4f, 0f);
- rightLeg.RotationOrder = RotationOrders.ZX;
- rightLeg.MinDegrees1 = -70f;
- rightLeg.MaxDegrees1 = 0f;
- rightLeg.MinDegrees2 = -110f;
- rightLeg.MaxDegrees2 = 60f;
-
- modelView.AddDynamic(headGroup);
- modelView.AddStatic(body);
- modelView.AddDynamic(rightArm);
- modelView.AddDynamic(leftArm);
- modelView.AddDynamic(rightLeg);
- modelView.AddDynamic(leftLeg);
- }
-
- public override string ToString() => nameof(Steve64x32Model);
- }
-}
diff --git a/PCK-Studio/Classes/Models/DefaultModels/Steve64x64Model.cs b/PCK-Studio/Classes/Models/DefaultModels/Steve64x64Model.cs
deleted file mode 100644
index e7442333..00000000
--- a/PCK-Studio/Classes/Models/DefaultModels/Steve64x64Model.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Security.Policy;
-using System.Text;
-using System.Threading.Tasks;
-using PckStudio.Internal;
-using PckStudio.Models;
-
-namespace PckStudio.Classes.Models.DefaultModels
-{
- internal class Steve64x64Model : ModelBase
- {
- SkinANIM _skinANIM;
- public Steve64x64Model(Image texture, SkinANIM anim)
- {
- textures = new Image[1] { texture };
- _skinANIM = anim;
- }
-
- public override void AddToModelView(MinecraftModelView modelView)
- {
- _ = Textures[0] ?? throw new NullReferenceException(nameof(Textures));
- Image source = Textures[0];
-
- (int top, int side) armWidth = _skinANIM.GetFlag(SkinAnimFlag.SLIM_MODEL) ? (6, 14) : (8, 16);
-
- Box head = new Box(source, new Rectangle(8, 0, 16, 8), new Rectangle(0, 8, 32, 8), new Point3D(0f, 0f, 0f));
- Box headOverlay = new Box(source, new Rectangle(40, 0, 16, 8), new Rectangle(32, 8, 32, 8), new Point3D(0f, 0f, 0f));
- headOverlay.Scale = OverlayScale;
-
- Box body = new Box(source, new Rectangle(20, 16, 16, 4), new Rectangle(16, 20, 24, 12), new Point3D(0f, 0f, 0f));
- Box bodyOverlay = new Box(source, new Rectangle(20, 32, 16, 4), new Rectangle(16, 36, 24, 12), new Point3D(0f, 0f, 0f));
- bodyOverlay.Scale = OverlayScale;
-
- Box rightArm = new Box(source, new Rectangle(44, 16, armWidth.top, 4), new Rectangle(40, 20, armWidth.side, 12), new Point3D(0f, 4f, 0f));
- Box rightArmOverlay = new Box(source, new Rectangle(44, 32, armWidth.top, 4), new Rectangle(40, 36, armWidth.side, 12), new Point3D(0f, 4f, 0f));
- rightArmOverlay.Scale = OverlayScale;
-
- Box leftArm = new Box(source, new Rectangle(36, 48, armWidth.top, 4), new Rectangle(32, 52, armWidth.side, 12), new Point3D(0f, 4f, 0f));
- Box leftArmOverlay = new Box(source, new Rectangle(52, 48, armWidth.top, 4), new Rectangle(48, 52, armWidth.side, 12), new Point3D(0f, 4f, 0f));
- leftArmOverlay.Scale = OverlayScale;
-
- Box rightLeg = new Box(source, new Rectangle(4, 16, 8, 4), new Rectangle(0, 20, 16, 12), new Point3D(0f, 6f, 0f));
- Box rightLegOverlay = new Box(source, new Rectangle(4, 32, 8, 4), new Rectangle(0, 52, 16, 12), new Point3D(0f, 6f, 0f));
- rightLegOverlay.Scale = OverlayScale;
-
- Box leftLeg = new Box(source, new Rectangle(20, 48, 8, 4), new Rectangle(16, 52, 16, 12), new Point3D(0f, 6f, 0f));
- Box leftLegOverlay = new Box(source, new Rectangle( 4, 48, 8, 4), new Rectangle( 0, 52, 16, 12), new Point3D(0f, 6f, 0f));
- leftLegOverlay.Scale = OverlayScale;
-
- Object3DGroup headGroup = new Object3DGroup();
- Object3DGroup bodyGroup = new Object3DGroup();
- Object3DGroup leftArmGroup = new Object3DGroup();
- Object3DGroup rightArmGroup = new Object3DGroup();
- Object3DGroup leftLegGroup = new Object3DGroup();
- Object3DGroup rightLegGroup = new Object3DGroup();
-
- headGroup.RotationOrder = RotationOrders.XY;
- headGroup.MinDegrees1 = -80f;
- headGroup.MaxDegrees1 = 80f;
-
- headGroup.MinDegrees2 = -57f;
- headGroup.MaxDegrees2 = 57f;
-
- headGroup.Origin = new Point3D(0f, -4f, 0f);
- headGroup.RotationOrder = RotationOrders.XY;
-
- headGroup.Position = new Point3D(0f, 8f, 0f);
- headGroup.Add(head);
- headGroup.Add(headOverlay);
-
- bodyGroup.Position = new Point3D(0f, 2f, 0f);
- bodyGroup.Add(body);
- bodyGroup.Add(bodyOverlay);
-
- leftArmGroup.Position = new Point3D(6f, 6f, 0f);
- leftArmGroup.RotationOrder = RotationOrders.ZX;
- leftArmGroup.MinDegrees1 = 0f;
- leftArmGroup.MaxDegrees1 = 160f;
- leftArmGroup.MinDegrees2 = -170f;
- leftArmGroup.MaxDegrees2 = 60f;
- leftArmGroup.Add(leftArm);
- leftArmGroup.Add(leftArmOverlay);
-
- rightArmGroup.Position = new Point3D(-6f, 6f, 0f);
- rightArmGroup.RotationOrder = RotationOrders.ZX;
- rightArmGroup.MinDegrees1 = -160f;
- rightArmGroup.MaxDegrees1 = 0f;
- rightArmGroup.MinDegrees2 = -170f;
- rightArmGroup.MaxDegrees2 = 60f;
- rightArmGroup.Add(rightArm);
- rightArmGroup.Add(rightArmOverlay);
-
- leftLegGroup.Position = new Point3D(2f, -4f, 0f);
- leftLegGroup.RotationOrder = RotationOrders.ZX;
- leftLegGroup.MinDegrees1 = 0f;
- leftLegGroup.MaxDegrees1 = 70f;
- leftLegGroup.MinDegrees2 = -110f;
- leftLegGroup.MaxDegrees2 = 60f;
- leftLegGroup.Add(leftLeg);
- leftLegGroup.Add(leftLegOverlay);
-
- rightLegGroup.Position = new Point3D(-2f, -4f, 0f);
- rightLegGroup.RotationOrder = RotationOrders.ZX;
- rightLegGroup.MinDegrees1 = -70f;
- rightLegGroup.MaxDegrees1 = 0f;
- rightLegGroup.MinDegrees2 = -110f;
- rightLegGroup.MaxDegrees2 = 60f;
- rightLegGroup.Add(rightLeg);
- rightLegGroup.Add(rightLegOverlay);
-
- modelView.AddDynamic(headGroup);
- modelView.AddStatic(bodyGroup);
- modelView.AddDynamic(rightArmGroup);
- modelView.AddDynamic(leftArmGroup);
- modelView.AddDynamic(rightLegGroup);
- modelView.AddDynamic(leftLegGroup);
- }
- }
-}
diff --git a/PCK-Studio/Classes/Models/Effects.cs b/PCK-Studio/Classes/Models/Effects.cs
deleted file mode 100644
index 418101b2..00000000
--- a/PCK-Studio/Classes/Models/Effects.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- [Flags]
- public enum Effects : byte
- {
- None = 0,
- FlipHorizontally = 1,
- FlipVertically = 2
- }
-}
diff --git a/PCK-Studio/Classes/Models/Matrix3D.cs b/PCK-Studio/Classes/Models/Matrix3D.cs
deleted file mode 100644
index 071528dd..00000000
--- a/PCK-Studio/Classes/Models/Matrix3D.cs
+++ /dev/null
@@ -1,177 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public struct Matrix3D
- {
- public Matrix3D(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
- {
- M11 = m11;
- M12 = m12;
- M13 = m13;
- M14 = m14;
- M21 = m21;
- M22 = m22;
- M23 = m23;
- M24 = m24;
- M31 = m31;
- M32 = m32;
- M33 = m33;
- M34 = m34;
- M41 = m41;
- M42 = m42;
- M43 = m43;
- M44 = m44;
- }
-
- public static Matrix3D CreateRotationX(float radians)
- {
- float num = (float)Math.Sin((double)radians);
- float num2 = (float)Math.Cos((double)radians);
- return new Matrix3D(1f, 0f, 0f, 0f, 0f, num2, -num, 0f, 0f, num, num2, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateRotationX(float sin, float cos)
- {
- return new Matrix3D(1f, 0f, 0f, 0f, 0f, cos, -sin, 0f, 0f, sin, cos, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateRotationY(float radians)
- {
- float num = (float)Math.Sin((double)radians);
- float num2 = (float)Math.Cos((double)radians);
- return new Matrix3D(num2, 0f, num, 0f, 0f, 1f, 0f, 0f, -num, 0f, num2, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateRotationY(float sin, float cos)
- {
- return new Matrix3D(cos, 0f, sin, 0f, 0f, 1f, 0f, 0f, -sin, 0f, cos, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateRotationZ(float radians)
- {
- float num = (float)Math.Sin((double)radians);
- float num2 = (float)Math.Cos((double)radians);
- return new Matrix3D(num2, -num, 0f, 0f, num, num2, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateRotationZ(float sin, float cos)
- {
- return new Matrix3D(cos, -sin, 0f, 0f, sin, cos, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateTranslation(float x, float y, float z)
- {
- return new Matrix3D(1f, 0f, 0f, x, 0f, 1f, 0f, y, 0f, 0f, 1f, z, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateTranslation(Point3D point)
- {
- return new Matrix3D(1f, 0f, 0f, point.X, 0f, 1f, 0f, point.Y, 0f, 0f, 1f, point.Z, 0f, 0f, 0f, 1f);
- }
-
- public static Matrix3D CreateScale(float s)
- {
- return new Matrix3D(s, 0f, 0f, 0f, 0f, s, 0f, 0f, 0f, 0f, s, 0f, 0f, 0f, 0f, 1f);
- }
-
- public float Determinant
- {
- get
- {
- return M11 * M22 * M33 * M44 + M21 * M32 * M43 * M14 + M31 * M42 * M13 * M24 + M41 * M12 * M23 * M34 - M14 * M23 * M32 * M41 - M24 * M33 * M42 * M11 - M34 * M43 * M12 * M21 - M44 * M13 * M22 * M31;
- }
- }
-
- public static Matrix3D Identity
- {
- get
- {
- return new Matrix3D(1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1f);
- }
- }
-
- public static Matrix3D Transpose(Matrix3D m)
- {
- return new Matrix3D(m.M11, m.M21, m.M31, m.M41, m.M12, m.M22, m.M32, m.M42, m.M13, m.M23, m.M33, m.M43, m.M14, m.M24, m.M34, m.M44);
- }
-
- public static Matrix3D Invert(Matrix3D m)
- {
- float determinant = m.Determinant;
- return new Matrix3D((m.M22 * m.M33 * m.M44 + m.M32 * m.M43 * m.M24 + m.M42 * m.M23 * m.M34 - m.M24 * m.M33 * m.M42 - m.M34 * m.M43 * m.M22 - m.M44 * m.M23 * m.M32) / determinant, -(m.M12 * m.M33 * m.M44 + m.M32 * m.M43 * m.M14 + m.M42 * m.M13 * m.M34 - m.M14 * m.M33 * m.M42 - m.M34 * m.M43 * m.M12 - m.M44 * m.M13 * m.M32) / determinant, (m.M12 * m.M23 * m.M44 + m.M22 * m.M43 * m.M14 + m.M42 * m.M13 * m.M24 - m.M14 * m.M23 * m.M42 - m.M24 * m.M43 * m.M12 - m.M44 * m.M13 * m.M22) / determinant, -(m.M12 * m.M23 * m.M34 + m.M22 * m.M33 * m.M14 + m.M32 * m.M13 * m.M24 - m.M14 * m.M23 * m.M32 - m.M24 * m.M33 * m.M12 - m.M34 * m.M13 * m.M22) / determinant, -(m.M21 * m.M33 * m.M44 + m.M31 * m.M43 * m.M24 + m.M41 * m.M23 * m.M34 - m.M24 * m.M33 * m.M41 - m.M34 * m.M43 * m.M21 - m.M44 * m.M23 * m.M31) / determinant, (m.M11 * m.M33 * m.M44 + m.M31 * m.M43 * m.M14 + m.M41 * m.M13 * m.M34 - m.M14 * m.M33 * m.M41 - m.M34 * m.M43 * m.M11 - m.M44 * m.M13 * m.M31) / determinant, -(m.M11 * m.M23 * m.M44 + m.M21 * m.M43 * m.M14 + m.M41 * m.M13 * m.M24 - m.M14 * m.M23 * m.M41 - m.M24 * m.M43 * m.M11 - m.M44 * m.M13 * m.M21) / determinant, (m.M11 * m.M23 * m.M34 + m.M21 * m.M33 * m.M14 + m.M31 * m.M13 * m.M24 - m.M14 * m.M23 * m.M31 - m.M24 * m.M33 * m.M11 - m.M34 * m.M13 * m.M21) / determinant, (m.M21 * m.M32 * m.M44 + m.M31 * m.M42 * m.M24 + m.M41 * m.M22 * m.M34 - m.M24 * m.M32 * m.M41 - m.M34 * m.M42 * m.M21 - m.M44 * m.M22 * m.M31) / determinant, -(m.M11 * m.M32 * m.M44 + m.M31 * m.M42 * m.M14 + m.M41 * m.M12 * m.M34 - m.M14 * m.M32 * m.M41 - m.M34 * m.M42 * m.M11 - m.M44 * m.M12 * m.M31) / determinant, (m.M11 * m.M32 * m.M44 + m.M21 * m.M42 * m.M14 + m.M41 * m.M12 * m.M24 - m.M14 * m.M22 * m.M41 - m.M24 * m.M42 * m.M11 - m.M44 * m.M12 * m.M21) / determinant, -(m.M11 * m.M22 * m.M34 + m.M21 * m.M32 * m.M14 + m.M31 * m.M12 * m.M24 - m.M14 * m.M22 * m.M31 - m.M24 * m.M32 * m.M11 - m.M34 * m.M12 * m.M21) / determinant, -(m.M21 * m.M32 * m.M43 + m.M31 * m.M42 * m.M23 + m.M41 * m.M22 * m.M33 - m.M23 * m.M32 * m.M41 - m.M33 * m.M42 * m.M21 - m.M43 * m.M22 * m.M31) / determinant, (m.M11 * m.M32 * m.M43 + m.M31 * m.M42 * m.M13 + m.M41 * m.M12 * m.M33 - m.M13 * m.M32 * m.M41 - m.M33 * m.M42 * m.M11 - m.M43 * m.M12 * m.M31) / determinant, -(m.M11 * m.M22 * m.M43 + m.M21 * m.M42 * m.M13 + m.M41 * m.M12 * m.M23 - m.M13 * m.M22 * m.M41 - m.M23 * m.M42 * m.M11 - m.M43 * m.M12 * m.M21) / determinant, (m.M11 * m.M22 * m.M33 + m.M21 * m.M32 * m.M13 + m.M31 * m.M12 * m.M23 - m.M13 * m.M22 * m.M31 - m.M23 * m.M32 * m.M11 - m.M33 * m.M12 * m.M21) / determinant);
- }
-
- public static Matrix3D operator +(Matrix3D a, Matrix3D b)
- {
- return new Matrix3D(a.M11 + b.M11, a.M12 + b.M12, a.M13 + b.M13, a.M14 + b.M14, a.M21 + b.M21, a.M22 + b.M22, a.M23 + b.M23, a.M24 + b.M24, a.M31 + b.M31, a.M32 + b.M32, a.M33 + b.M33, a.M34 + b.M34, a.M41 + b.M41, a.M42 + b.M42, a.M43 + b.M43, a.M44 + b.M44);
- }
-
- public static Matrix3D operator -(Matrix3D a, Matrix3D b)
- {
- return new Matrix3D(a.M11 - b.M11, a.M12 - b.M12, a.M13 - b.M13, a.M14 - b.M14, a.M21 - b.M21, a.M22 - b.M22, a.M23 - b.M23, a.M24 - b.M24, a.M31 - b.M31, a.M32 - b.M32, a.M33 - b.M33, a.M34 - b.M34, a.M41 - b.M41, a.M42 - b.M42, a.M43 - b.M43, a.M44 - b.M44);
- }
-
- public static Matrix3D operator *(Matrix3D a, Matrix3D b)
- {
- return new Matrix3D(a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31 + a.M14 * b.M41, a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32 + a.M14 * b.M42, a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33 + a.M14 * b.M43, a.M11 * b.M14 + a.M12 * b.M24 + a.M13 * b.M34 + a.M14 * b.M44, a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31 + a.M24 * b.M41, a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32 + a.M24 * b.M42, a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33 + a.M24 * b.M43, a.M21 * b.M14 + a.M22 * b.M24 + a.M23 * b.M34 + a.M24 * b.M44, a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31 + a.M34 * b.M41, a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32 + a.M34 * b.M42, a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33 + a.M34 * b.M43, a.M31 * b.M14 + a.M32 * b.M24 + a.M33 * b.M34 + a.M34 * b.M44, a.M41 * b.M11 + a.M42 * b.M21 + a.M43 * b.M31 + a.M44 * b.M41, a.M41 * b.M12 + a.M42 * b.M22 + a.M43 * b.M32 + a.M44 * b.M42, a.M41 * b.M13 + a.M42 * b.M23 + a.M43 * b.M33 + a.M44 * b.M43, a.M41 * b.M14 + a.M42 * b.M24 + a.M43 * b.M34 + a.M44 * b.M44);
- }
-
- public static Point3D operator *(Matrix3D m, Point3D p)
- {
- return new Point3D(p.X * m.M11 + p.Y * m.M12 + p.Z * m.M13 + m.M14, p.X * m.M21 + p.Y * m.M22 + p.Z * m.M23 + m.M24, p.X * m.M31 + p.Y * m.M32 + p.Z * m.M33 + m.M34);
- }
-
- public static Matrix3D operator +(Matrix3D m, float n)
- {
- return new Matrix3D(m.M11 + n, m.M12 + n, m.M13 + n, m.M14 + n, m.M21 + n, m.M22 + n, m.M23 + n, m.M24 + n, m.M31 + n, m.M32 + n, m.M33 + n, m.M34 + n, m.M41 + n, m.M42 + n, m.M43 + n, m.M44 + n);
- }
-
- public static Matrix3D operator -(Matrix3D m, float n)
- {
- return new Matrix3D(m.M11 - n, m.M12 - n, m.M13 - n, m.M14 - n, m.M21 - n, m.M22 - n, m.M23 - n, m.M24 - n, m.M31 - n, m.M32 - n, m.M33 - n, m.M34 - n, m.M41 - n, m.M42 - n, m.M43 - n, m.M44 - n);
- }
-
- public static Matrix3D operator *(Matrix3D m, float n)
- {
- return new Matrix3D(m.M11 * n, m.M12 * n, m.M13 * n, m.M14 * n, m.M21 * n, m.M22 * n, m.M23 * n, m.M24 * n, m.M31 * n, m.M32 * n, m.M33 * n, m.M34 * n, m.M41 * n, m.M42 * n, m.M43 * n, m.M44 * n);
- }
-
- public static Matrix3D operator /(Matrix3D m, float n)
- {
- return new Matrix3D(m.M11 / n, m.M12 / n, m.M13 / n, m.M14 / n, m.M21 / n, m.M22 / n, m.M23 / n, m.M24 / n, m.M31 / n, m.M32 / n, m.M33 / n, m.M34 / n, m.M41 / n, m.M42 / n, m.M43 / n, m.M44 / n);
- }
-
- public float M11;
-
- public float M12;
-
- public float M13;
-
- public float M14;
-
- public float M21;
-
- public float M22;
-
- public float M23;
-
- public float M24;
-
- public float M31;
-
- public float M32;
-
- public float M33;
-
- public float M34;
-
- public float M41;
-
- public float M42;
-
- public float M43;
-
- public float M44;
- }
-}
diff --git a/PCK-Studio/Classes/Models/ModelView.Designer.cs b/PCK-Studio/Classes/Models/ModelView.Designer.cs
deleted file mode 100644
index bfedcec8..00000000
--- a/PCK-Studio/Classes/Models/ModelView.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-
-namespace PckStudio.Models
-{
- partial class MinecraftModelView
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
-
-
-
- protected override void Dispose(bool disposing)
- {
- if (disposing && this.components != null)
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
-
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
-
- private PckStudio.Models.BackgroundTypes backgroundType;
-
- private System.Drawing.Brush backgroundBrush = new System.Drawing.SolidBrush(System.Drawing.Color.SkyBlue);
-
- private System.ComponentModel.BackgroundWorker downloader = new System.ComponentModel.BackgroundWorker();
-
- private System.Drawing.Point mouseLastLocation;
-
- private PckStudio.Models.Object3D rotatingObject3D;
-
- private System.Drawing.Color backgroundColor = System.Drawing.Color.Transparent;
-
- private System.Drawing.Color backgroundGradientColor1 = System.Drawing.SystemColors.ControlDarkDark;
-
- private System.Drawing.Color backgroundGradientColor2 = System.Drawing.SystemColors.ControlLightLight;
-
- private static System.Drawing.Color textShadowColor = System.Drawing.Color.FromArgb(0x3F, 0x3F, 0x3F);
-
- private System.Drawing.Image backgroundTexture;
-
- internal PckStudio.Models.Matrix3D GlobalTransformation = PckStudio.Models.Matrix3D.Identity;
-
- private System.Collections.Generic.List texelList = new System.Collections.Generic.List();
-
- private PckStudio.Models.TexelComparer texelComparer = new PckStudio.Models.TexelComparer();
-
- private System.Collections.Generic.List object3DList = new System.Collections.Generic.List();
-
- private System.Collections.Generic.List dynamicObject3DtList = new System.Collections.Generic.List();
- #endregion
- }
-}
diff --git a/PCK-Studio/Classes/Models/ModelView.cs b/PCK-Studio/Classes/Models/ModelView.cs
deleted file mode 100644
index 070e51ec..00000000
--- a/PCK-Studio/Classes/Models/ModelView.cs
+++ /dev/null
@@ -1,431 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
-using System.Drawing.Text;
-using System.IO;
-using System.Net;
-using System.Threading;
-using System.Windows.Forms;
-
-namespace PckStudio.Models
-{
- public partial class MinecraftModelView : Control
- {
- private const int IsometricFOV = 46;
-
- internal float cameraZ = 31.4285717f;
-
- private int Fov = 70;
-
- private float scale = 1f;
-
- internal float RotationX;
-
- internal float RotationY;
-
- private bool perspective = true;
-
- private float PiBy180 = 0.0174532924f;
-
- protected override void OnBackColorChanged(EventArgs e)
- {
- base.OnBackColorChanged(e);
- backgroundColor = BackColor;
- UpdateBackgroundBrush();
- Invalidate();
- }
-
- [Browsable(true)]
- [Category("Appearance")]
- public System.Drawing.Color BackGradientColor1
- {
- get
- {
- return backgroundGradientColor1;
- }
- set
- {
- backgroundGradientColor1 = value;
- UpdateBackgroundBrush();
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("Appearance")]
- public System.Drawing.Color BackGradientColor2
- {
- get
- {
- return backgroundGradientColor2;
- }
- set
- {
- backgroundGradientColor2 = value;
- UpdateBackgroundBrush();
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("Appearance")]
- public new System.Drawing.Image BackgroundImage
- {
- get
- {
- return backgroundTexture;
- }
- set
- {
- backgroundTexture = value;
- UpdateBackgroundBrush();
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("Appearance")]
- public BackgroundTypes BackgroundType
- {
- get
- {
- return backgroundType;
- }
- set
- {
- backgroundType = value;
- UpdateBackgroundBrush();
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("View")]
- public ProjectionTypes Projection
- {
- get
- {
- return perspective ? ProjectionTypes.Perspective : ProjectionTypes.Isometric;
- }
- set
- {
- perspective = value == ProjectionTypes.Perspective;
- SetupProjection();
- foreach (Object3D object3D in object3DList)
- {
- object3D.Update();
- }
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("View")]
- public int FOV
- {
- get
- {
- return Fov;
- }
- set
- {
- Fov = value;
- SetupProjection();
- foreach (Object3D object3D in object3DList)
- {
- object3D.Update();
- }
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("View")]
- public int DegreesX
- {
- get
- {
- return (int)RotationX;
- }
- set
- {
- RotationX = value;
- Matrix3D globalTransformation = Matrix3D.CreateRotationX(RotationX * PiBy180) * Matrix3D.CreateRotationY(RotationY * PiBy180);
- foreach (Object3D object3D in object3DList)
- {
- object3D.GlobalTransformation = globalTransformation;
- }
- Invalidate();
- }
- }
-
- [Browsable(true)]
- [Category("View")]
- public int DegreesY
- {
- get
- {
- return (int)RotationY;
- }
- set
- {
- RotationY = value;
- Matrix3D globalTransformation = Matrix3D.CreateRotationX(RotationX * PiBy180) * Matrix3D.CreateRotationY(RotationY * PiBy180);
- foreach (Object3D object3D in object3DList)
- {
- object3D.GlobalTransformation = globalTransformation;
- }
- Invalidate();
- }
- }
-
- public ModelBase Model
- {
- set
- {
- Clear();
- value.AddToModelView(this);
- Matrix3D globalTransformation = Matrix3D.CreateRotationX(RotationX * 3.14159274f / 180f) * Matrix3D.CreateRotationY(RotationY * 3.14159274f / 180f);
- foreach (Object3D object3D in object3DList)
- {
- object3D.GlobalTransformation = globalTransformation;
- }
- Invalidate();
- }
- }
-
- private void Clear()
- {
- texelList.Clear();
- object3DList.Clear();
- dynamicObject3DtList.Clear();
- rotatingObject3D = null;
- }
-
- protected override void OnPaintBackground(PaintEventArgs pevent)
- {
- base.OnPaintBackground(pevent);
- System.Drawing.Graphics graphics = pevent.Graphics;
- graphics.CompositingQuality = CompositingQuality.HighSpeed;
- graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
- graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
- graphics.SmoothingMode = SmoothingMode.HighSpeed;
- graphics.CompositingMode = CompositingMode.SourceCopy;
- graphics.FillRectangle(backgroundBrush, ClientRectangle);
- graphics.CompositingMode = CompositingMode.SourceOver;
- }
-
- protected override void OnPaint(PaintEventArgs pe)
- {
- texelList.Sort(texelComparer);
- System.Drawing.Graphics graphics = pe.Graphics;
- graphics.TranslateTransform(Width / 2, Height / 2);
- graphics.ScaleTransform(scale, -scale);
- graphics.CompositingQuality = CompositingQuality.HighSpeed;
- graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
- graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
- graphics.SmoothingMode = SmoothingMode.HighSpeed;
- graphics.CompositingMode = CompositingMode.SourceCopy;
- for (int i = 0; i < texelList.Count; i++)
- {
- texelList[i].Draw(graphics);
- }
- }
-
- public System.Drawing.Image RenderToImage(System.Drawing.Size size, System.Drawing.RectangleF crop)
- {
- if (size.Width / size.Height != crop.Width / crop.Height)
- {
- throw new ArgumentException("Aspect ratio is ambiguous");
- }
- System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(size.Width, size.Height);
- using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
- {
- System.Drawing.Size size2 = new System.Drawing.Size((int)(size.Width / crop.Width), (int)(size.Height / crop.Height));
- texelList.Sort(texelComparer);
- graphics.TranslateTransform(-crop.Left * size2.Width, -crop.Top * size2.Height);
- graphics.TranslateTransform(size2.Width / 2, size2.Height / 2);
- float num = Math.Min(size2.Width, size2.Height) * 0.01f / (float)Math.Tan((perspective ? Fov : IsometricFOV) * 3.1415926535897931 / 360.0);
- graphics.ScaleTransform(num, -num);
- graphics.CompositingQuality = CompositingQuality.HighSpeed;
- graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
- graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
- graphics.SmoothingMode = SmoothingMode.HighSpeed;
- graphics.Clear(System.Drawing.Color.Transparent);
- for (int i = 0; i < texelList.Count; i++)
- {
- texelList[i].Draw(graphics);
- }
- }
- return bitmap;
- }
-
- private System.Drawing.Image RenderVersionText()
- {
- System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(0x154, 0x12);
- Version version = new Version(Application.ProductVersion);
- string s = string.Format("{0} {1}.{2}{3}", Application.ProductName, version.Major, version.Minor, (version.Build != 0) ? ("." + version.Build) : "");
- using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
- {
- using (System.Drawing.Brush brush = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(0x7F, System.Drawing.Color.Gray)))
- {
- graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
- graphics.DrawString(s, Font, brush, 1f, 1f);
- graphics.DrawString(s, Font, System.Drawing.Brushes.White, 0f, 0f);
- }
- }
- return bitmap;
- }
-
- private void UpdateBackgroundBrush()
- {
- backgroundBrush = ((backgroundType == BackgroundTypes.Texture) ? new System.Drawing.TextureBrush(backgroundTexture) : ((backgroundType == BackgroundTypes.Gradient) ? new System.Drawing.Drawing2D.LinearGradientBrush(new System.Drawing.Point(0, 0), new System.Drawing.Point(0, System.Math.Max(1, base.Height)), backgroundGradientColor1, backgroundGradientColor2) : new System.Drawing.SolidBrush(backgroundColor)));
- }
-
- public System.Drawing.Brush GetBackgroundBrush(System.Drawing.Size size)
- {
- if (backgroundType == BackgroundTypes.Texture)
- {
- return new System.Drawing.TextureBrush(backgroundTexture);
- }
- if (backgroundType != BackgroundTypes.Gradient)
- {
- return new System.Drawing.SolidBrush(backgroundColor);
- }
- return new LinearGradientBrush(new System.Drawing.Point(0, 0), new System.Drawing.Point(0, Math.Max(1, size.Height)), backgroundGradientColor1, backgroundGradientColor2);
- }
-
- private void SetupProjection()
- {
- cameraZ = 2400f / Fov;
- scale = Math.Min(Width, Height) * 0.01f / (float)Math.Tan((perspective ? Fov : IsometricFOV) * Math.PI / 360.0);
- }
-
- protected override void OnResize(EventArgs e)
- {
- SetupProjection();
- UpdateBackgroundBrush();
- base.OnResize(e);
- }
-
- internal void RemoveTexelsOf(TexturePlane texturePlane)
- {
- for (int i = 0; i < texelList.Count; i++)
- {
- if (texelList[i].TexturePlane == texturePlane)
- {
- texelList.RemoveAt(i);
- i--;
- }
- }
- }
-
- internal void AddTexel(Texel texel)
- {
- texelList.Add(texel);
- }
-
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- System.Drawing.PointF location = new System.Drawing.PointF((e.X - Width * 0.5f) / scale, -(e.Y - Height * 0.5f) / scale);
- rotatingObject3D = null;
- Object3D item = null;
- float num = -1000f;
- foreach (Object3D object3D in object3DList)
- {
- float num2 = object3D.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- item = object3D;
- }
- }
- if (num > -1000f && dynamicObject3DtList.Contains(item))
- {
- rotatingObject3D = item;
- }
- mouseLastLocation = e.Location;
- Invalidate();
- }
-
- protected override void OnMouseUp(MouseEventArgs e)
- {
- base.OnMouseUp(e);
- rotatingObject3D = null;
- }
-
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- if (e.Button != MouseButtons.Left)
- {
- return;
- }
- if (rotatingObject3D != null)
- {
- rotatingObject3D.RotateByMouse((e.X - mouseLastLocation.X) * 400f / Height, (e.Y - mouseLastLocation.Y) * 400f / Height);
- mouseLastLocation = e.Location;
- Invalidate();
- return;
- }
- RotationY += (e.X - mouseLastLocation.X) * 400f / Height;
- RotationX += (e.Y - mouseLastLocation.Y) * 400f / Height;
- mouseLastLocation = e.Location;
- Matrix3D globalTransformation = Matrix3D.CreateRotationX(RotationX * 3.14159274f / 180f) * Matrix3D.CreateRotationY(RotationY * 3.14159274f / 180f);
- foreach (Object3D object3D in object3DList)
- {
- object3D.GlobalTransformation = globalTransformation;
- }
- Invalidate();
- }
-
- public void AddStatic(Object3D object3D)
- {
- object3D.Viewport = this;
- object3DList.Add(object3D);
- foreach (Object3D object3D2 in object3DList)
- {
- object3D2.Update();
- }
- }
-
- public void AddDynamic(Object3D object3D)
- {
- AddStatic(object3D);
- dynamicObject3DtList.Add(object3D);
- }
-
- internal System.Drawing.PointF Point3DTo2D(Point3D point3D)
- {
- if (perspective)
- {
- return new System.Drawing.PointF(point3D.X * (-50f / (point3D.Z - cameraZ)), point3D.Y * (-50f / (point3D.Z - cameraZ)));
- }
- return new System.Drawing.PointF(point3D.X, point3D.Y);
- }
-
- internal float GetZOrder(Point3D point3D)
- {
- if (perspective)
- {
- return point3D.X * point3D.X + point3D.Y * point3D.Y + (cameraZ - point3D.Z) * (cameraZ - point3D.Z);
- }
- return -point3D.Z;
- }
-
- public MinecraftModelView()
- {
- SetStyle(ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
- InitializeComponent();
- texelComparer = new TexelComparer();
- }
-
- public MinecraftModelView(IContainer container) : this()
- {
- container.Add(this);
- }
- }
-}
diff --git a/PCK-Studio/Classes/Models/Object3D.cs b/PCK-Studio/Classes/Models/Object3D.cs
deleted file mode 100644
index f9aa9f6a..00000000
--- a/PCK-Studio/Classes/Models/Object3D.cs
+++ /dev/null
@@ -1,461 +0,0 @@
-using System;
-using System.Drawing;
-
-namespace PckStudio.Models
-{
- public abstract class Object3D
- {
- public abstract Image Image { set; }
-
- public float Angle1
- {
- get
- {
- return angle1;
- }
- set
- {
- angle1 = value;
- OnUpdateRotation();
- }
- }
-
- public float Angle2
- {
- get
- {
- return angle2;
- }
- set
- {
- angle2 = value;
- OnUpdateRotation();
- }
- }
-
- public float MinAngle1
- {
- get
- {
- return minAngle1;
- }
- set
- {
- minAngle1 = value;
- }
- }
-
- public float MinAngle2
- {
- get
- {
- return minAngle2;
- }
- set
- {
- minAngle2 = value;
- }
- }
-
- public float MaxAngle1
- {
- get
- {
- return maxAngle1;
- }
- set
- {
- maxAngle1 = value;
- }
- }
-
- public float MaxAngle2
- {
- get
- {
- return maxAngle2;
- }
- set
- {
- maxAngle2 = value;
- }
- }
-
- public float AngleRange1
- {
- get
- {
- return maxAngle1 - minAngle1;
- }
- set
- {
- minAngle1 = angle1 - value / 2f;
- maxAngle1 = angle1 + value / 2f;
- }
- }
-
- public float AngleRange2
- {
- get
- {
- return maxAngle2 - minAngle2;
- }
- set
- {
- minAngle2 = angle2 - value / 2f;
- maxAngle2 = angle2 + value / 2f;
- }
- }
-
- public float MinDegrees1
- {
- get
- {
- return minAngle1 / PIby180;
- }
- set
- {
- minAngle1 = value * PIby180;
- }
- }
-
- public float MinDegrees2
- {
- get
- {
- return minAngle2 / PIby180;
- }
- set
- {
- minAngle2 = value * PIby180;
- }
- }
-
- public float MaxDegrees1
- {
- get
- {
- return maxAngle1 / PIby180;
- }
- set
- {
- maxAngle1 = value * PIby180;
- }
- }
-
- public float MaxDegrees2
- {
- get
- {
- return maxAngle2 / PIby180;
- }
- set
- {
- maxAngle2 = value * PIby180;
- }
- }
-
- public float DegreesRange1
- {
- get
- {
- return AngleRange1 / PIby180;
- }
- set
- {
- AngleRange1 = value * PIby180;
- }
- }
-
- public float DegreesRange2
- {
- get
- {
- return AngleRange2 / PIby180;
- }
- set
- {
- AngleRange2 = value * PIby180;
- }
- }
-
- public float Scale
- {
- get
- {
- return scaleTransformation.M11;
- }
- set
- {
- scaleTransformation = Matrix3D.CreateScale(value);
- UpdateRotation();
- }
- }
-
- public RotationOrders RotationOrder
- {
- get
- {
- return order;
- }
- set
- {
- order = value;
- switch (order)
- {
- case RotationOrders.XY:
- Rotate = new RotateMethod(RotateXY);
- OnUpdateRotation = UpdateRotationXY;
- return;
- case RotationOrders.YX:
- Rotate = new RotateMethod(RotateYX);
- OnUpdateRotation = UpdateRotationYX;
- return;
- case RotationOrders.XZ:
- Rotate = new RotateMethod(RotateXZ);
- OnUpdateRotation = UpdateRotationXZ;
- return;
- case RotationOrders.ZX:
- Rotate = new RotateMethod(RotateZX);
- OnUpdateRotation = UpdateRotationZX;
- return;
- case RotationOrders.YZ:
- Rotate = new RotateMethod(RotateYZ);
- OnUpdateRotation = UpdateRotationYZ;
- return;
- case RotationOrders.ZY:
- Rotate = new RotateMethod(RotateZY);
- OnUpdateRotation = UpdateRotationZY;
- return;
- default:
- return;
- }
- }
- }
-
- internal virtual MinecraftModelView Viewport
- {
- set
- {
- viewport = value;
- }
- }
-
- public Point3D Origin
- {
- get
- {
- return new Point3D(-originTranslation.M14, -originTranslation.M24, -originTranslation.M34);
- }
- set
- {
- originTranslation = Matrix3D.CreateTranslation(-value.X, -value.Y, -value.Z);
- UpdateRotation();
- }
- }
-
- public Point3D Position
- {
- get
- {
- return new Point3D(positionTranslation.M14, positionTranslation.M24, positionTranslation.M34);
- }
- set
- {
- positionTranslation = Matrix3D.CreateTranslation(value);
- UpdateRotation();
- Update();
- }
- }
-
- internal abstract void Update();
-
- public Matrix3D GlobalTransformation
- {
- get
- {
- return globalTransformation;
- }
- set
- {
- globalTransformation = value;
- Update();
- }
- }
-
- public Matrix3D LocalTransformation
- {
- get
- {
- return localTransformation;
- }
- set
- {
- localTransformation = value;
- Update();
- }
- }
-
- public void SetRotation(float angle1, float angle2)
- {
- this.angle1 = angle1;
- this.angle2 = angle2;
- OnUpdateRotation();
- }
-
- public void RotateByMouse(float deltaX, float deltaY)
- {
- if (Rotate != null)
- {
- Rotate(deltaX, deltaY);
- Update();
- }
- }
-
- private void CorrectAngles()
- {
- if (angle1 > maxAngle1)
- {
- angle1 = maxAngle1;
- }
- else if (angle1 < minAngle1)
- {
- angle1 = minAngle1;
- }
- if (angle2 > maxAngle2)
- {
- angle2 = maxAngle2;
- return;
- }
- if (angle2 < minAngle2)
- {
- angle2 = minAngle2;
- }
- }
-
- public abstract float HitTest(PointF location);
-
- private void RotateXY(float delta1, float delta2)
- {
- angle1 += delta1 * PIby180;
- angle2 += delta2 * PIby180 * (float)Math.Cos((double)(viewport.RotationY * PIby180));
- UpdateRotationXY();
- }
-
- private void RotateYX(float delta1, float delta2)
- {
- angle1 += delta1 * PIby180;
- angle2 += delta2 * PIby180 * (float)Math.Cos(viewport.RotationY * 3.1415926535897931 / 180.0);
- UpdateRotationYX();
- }
-
- private void RotateXZ(float delta1, float delta2)
- {
- angle1 += delta1 * PIby180 * (float)Math.Cos((double)(viewport.RotationY * PIby180)) + delta2 * PIby180 * (float)Math.Sin((double)(viewport.RotationY * PIby180));
- angle2 += delta2 * PIby180 * (float)Math.Cos((double)(viewport.RotationY * PIby180)) - delta1 * PIby180 * (float)Math.Sin((double)(viewport.RotationY * PIby180));
- UpdateRotationXZ();
- }
-
- private void RotateZX(float delta1, float delta2)
- {
- angle1 += delta1 * PIby180 * (float)Math.Cos((double)(viewport.RotationY * PIby180)) + delta2 * PIby180 * (float)Math.Sin((double)(viewport.RotationY * PIby180));
- angle2 += delta2 * PIby180 * (float)Math.Cos((double)(viewport.RotationY * PIby180)) - delta1 * PIby180 * (float)Math.Sin((double)(viewport.RotationY * PIby180));
- UpdateRotationZX();
- }
-
- private void RotateZY(float delta1, float delta2)
- {
- angle1 -= delta2 * PIby180;
- angle2 += delta1 * PIby180;
- UpdateRotationZY();
- }
-
- private void RotateYZ(float delta1, float delta2)
- {
- angle1 += delta1 * PIby180;
- angle2 += delta2 * PIby180 * (float)Math.Sin((double)(viewport.RotationY * PIby180));
- UpdateRotationYZ();
- }
-
- private void UpdateRotationXY()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationY(angle1) * Matrix3D.CreateRotationX(angle2);
- UpdateRotation();
- }
-
- private void UpdateRotationYX()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationX(angle2) * Matrix3D.CreateRotationY(angle1);
- UpdateRotation();
- }
-
- private void UpdateRotationXZ()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationZ(angle1) * Matrix3D.CreateRotationX(angle2);
- UpdateRotation();
- }
-
- private void UpdateRotationZX()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationX(angle2) * Matrix3D.CreateRotationZ(angle1);
- UpdateRotation();
- }
-
- private void UpdateRotationZY()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationY(angle2) * Matrix3D.CreateRotationZ(angle1);
- UpdateRotation();
- }
-
- private void UpdateRotationYZ()
- {
- CorrectAngles();
- localRotation = Matrix3D.CreateRotationZ(angle2) * Matrix3D.CreateRotationY(angle1);
- UpdateRotation();
- }
-
- private void UpdateRotation()
- {
- localTransformation = positionTranslation * localRotation * originTranslation * scaleTransformation;
- }
-
- public const float PIby180 = 0.0174532924f;
-
- protected Matrix3D originTranslation = Matrix3D.Identity;
-
- protected Matrix3D positionTranslation = Matrix3D.Identity;
-
- protected Matrix3D scaleTransformation = Matrix3D.Identity;
-
- protected Matrix3D localRotation = Matrix3D.Identity;
-
- protected Matrix3D localTransformation = Matrix3D.Identity;
-
- protected Matrix3D globalTransformation = Matrix3D.Identity;
-
- private float angle1;
-
- private float angle2;
-
- private float maxAngle1 = (float)Math.PI;
- private float minAngle1 = (float)-Math.PI;
-
- private float maxAngle2 = (float)Math.PI;
- private float minAngle2 = (float)-Math.PI;
-
- private RotationOrders order;
-
- protected MinecraftModelView viewport;
-
- private RotateMethod Rotate;
-
- private Action OnUpdateRotation;
-
- private delegate void RotateMethod(float deltaX, float deltaY);
- }
-}
diff --git a/PCK-Studio/Classes/Models/Object3DGroup.cs b/PCK-Studio/Classes/Models/Object3DGroup.cs
deleted file mode 100644
index fc3cd524..00000000
--- a/PCK-Studio/Classes/Models/Object3DGroup.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace PckStudio.Models
-{
- public class Object3DGroup : Object3D
- {
- internal override MinecraftModelView Viewport
- {
- set
- {
- base.Viewport = value;
- foreach (Object3D object3D in objects)
- {
- object3D.Viewport = value;
- }
- }
- }
-
- public override System.Drawing.Image Image
- {
- set
- {
- foreach (Object3D object3D in objects)
- {
- object3D.Image = value;
- }
- }
- }
-
- internal override void Update()
- {
- Matrix3D globalTransformation = this.globalTransformation * localTransformation;
- for (int i = 0; i < objects.Count; i++)
- {
- objects[i].GlobalTransformation = globalTransformation;
- }
- }
-
- public override float HitTest(System.Drawing.PointF location)
- {
- float num = -1000f;
- foreach (Object3D object3D in objects)
- {
- float num2 = object3D.HitTest(location);
- if (num2 > num)
- {
- num = num2;
- }
- }
- return num;
- }
-
- public void Add(Object3D object3D)
- {
- if (object3D == this)
- {
- throw new ArgumentException("Cannot add Object3D into itself.");
- }
- objects.Add(object3D);
- }
-
- private List objects = new List();
- }
-}
diff --git a/PCK-Studio/Classes/Models/Point3D.cs b/PCK-Studio/Classes/Models/Point3D.cs
deleted file mode 100644
index e69ebf0b..00000000
--- a/PCK-Studio/Classes/Models/Point3D.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public struct Point3D
- {
- public float X;
- public float Y;
- public float Z;
-
- public Point3D(float x, float y, float z)
- {
- (X, Y, Z) = (x, y, z);
- }
-
- public static Point3D Zero => default(Point3D);
-
- public override string ToString()
- {
- return string.Format("({0};{1};{2})", X, Y, Z);
- }
-
- public static Point3D operator +(Point3D a, Point3D b) => new Point3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
-
- public static Point3D operator -(Point3D a, Point3D b) => new Point3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
-
- public static Point3D operator *(Point3D p, float s) => new Point3D(p.X * s, p.Y * s, p.Z * s);
-
- public static Point3D operator /(Point3D p, float s) => new Point3D(p.X / s, p.Y / s, p.Z / s);
- }
-}
diff --git a/PCK-Studio/Classes/Models/Positions.cs b/PCK-Studio/Classes/Models/Positions.cs
deleted file mode 100644
index 004ba901..00000000
--- a/PCK-Studio/Classes/Models/Positions.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public enum Positions
- {
- Default,
- Outstretched,
- Walking,
- Running,
- Sitting,
- Zombie
- }
-}
diff --git a/PCK-Studio/Classes/Models/ProjectionTypes.cs b/PCK-Studio/Classes/Models/ProjectionTypes.cs
deleted file mode 100644
index 04d81550..00000000
--- a/PCK-Studio/Classes/Models/ProjectionTypes.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public enum ProjectionTypes : byte
- {
- Perspective,
- Isometric
- }
-}
diff --git a/PCK-Studio/Classes/Models/RotationOrders.cs b/PCK-Studio/Classes/Models/RotationOrders.cs
deleted file mode 100644
index 0ca2c041..00000000
--- a/PCK-Studio/Classes/Models/RotationOrders.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- public enum RotationOrders : byte
- {
- XY,
- YX,
- XZ,
- ZX,
- YZ,
- ZY
- }
-}
diff --git a/PCK-Studio/Classes/Models/Texel.cs b/PCK-Studio/Classes/Models/Texel.cs
deleted file mode 100644
index 736bcb21..00000000
--- a/PCK-Studio/Classes/Models/Texel.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-
-namespace PckStudio.Models
-{
- internal struct Texel
- {
- internal Texel(TexturePlane texturePlane, int x, int y, System.Drawing.Color color)
- {
- TexturePlane = texturePlane;
- X = x;
- Y = y;
- this.color = color;
- brush = new System.Drawing.SolidBrush(color);
- pen = new System.Drawing.Pen(System.Drawing.Color.White, 0.01f);
- }
-
- internal double Z
- {
- get
- {
- return TexturePlane.ZOrder[X + 1, Y + 1];
- }
- }
-
- internal void Draw(System.Drawing.Graphics g)
- {
- System.Drawing.PointF[] points = new System.Drawing.PointF[]
- {
- TexturePlane.Points[X, Y],
- TexturePlane.Points[X + 1, Y],
- TexturePlane.Points[X + 1, Y + 1],
- TexturePlane.Points[X, Y + 1]
- };
- g.FillPolygon(brush, points);
- }
-
- internal TexturePlane TexturePlane;
-
- internal int X;
-
- internal int Y;
-
- private System.Drawing.Color color;
-
- private System.Drawing.Brush brush;
-
- private System.Drawing.Pen pen;
- }
-}
diff --git a/PCK-Studio/Classes/Models/TexelComparer.cs b/PCK-Studio/Classes/Models/TexelComparer.cs
deleted file mode 100644
index d7187760..00000000
--- a/PCK-Studio/Classes/Models/TexelComparer.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace PckStudio.Models
-{
- internal class TexelComparer : IComparer
- {
- public int Compare(Texel x, Texel y)
- {
- return -x.Z.CompareTo(y.Z);
- }
-
- public TexelComparer()
- {
- }
- }
-}
diff --git a/PCK-Studio/Classes/Models/TexturePlane.cs b/PCK-Studio/Classes/Models/TexturePlane.cs
deleted file mode 100644
index 0b7b7edf..00000000
--- a/PCK-Studio/Classes/Models/TexturePlane.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
-using System.Drawing;
-
-namespace PckStudio.Models
-{
- public class TexturePlane : Object3D
- {
- public override Image Image
- {
- set
- {
- Bitmap = (Bitmap)value;
- }
- }
-
- internal override MinecraftModelView Viewport
- {
- set
- {
- base.Viewport = value;
- if (bitmap != null && value != null)
- {
- UpdateBitmap();
- }
- }
- }
-
- internal override void Update()
- {
- if (Points == null || viewport == null)
- {
- return;
- }
- Matrix3D m = globalTransformation * localTransformation * originTranslation;
- for (int i = 0; i <= width; i++)
- {
- for (int j = 0; j <= height; j++)
- {
- Point3D point3D = m * new Point3D(i, j, 0f);
- Points[i, j] = viewport.Point3DTo2D(point3D);
- double num = (double)viewport.GetZOrder(point3D);
- ZOrder[i, j] += num;
- ZOrder[i + 1, j] += num;
- ZOrder[i, j + 1] += num;
- ZOrder[i + 1, j + 1] = num;
- }
- }
- }
-
- private Bitmap Bitmap
- {
- set
- {
- if (viewport == null)
- {
- bitmap = value;
- return;
- }
- texelList.Clear();
- if (bitmap != null)
- {
- viewport.RemoveTexelsOf(this);
- Points = null;
- }
- bitmap = value;
- if (bitmap != null)
- {
- UpdateBitmap();
- Update();
- }
- }
- }
-
- private void UpdateBitmap()
- {
- width = bitmap.Width;
- height = bitmap.Height;
- visibility = new bool[width, height];
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- Color pixel = bitmap.GetPixel(i, j);
- int num = flipHorizontally ? (width - i - 1) : i;
- int num2 = flipVertically ? j : (height - j - 1);
- if (pixel.A == 0)
- {
- visibility[num, num2] = false;
- }
- else
- {
- visibility[num, num2] = true;
- Texel texel = new Texel(this, num, num2, pixel);
- viewport.AddTexel(texel);
- texelList.Add(texel);
- }
- }
- }
- Points = new PointF[width + 1, height + 1];
- ZOrder = new double[width + 2, height + 2];
- }
-
- public TexturePlane(Image bitmap, Rectangle srcRect, Point3D origin, Point3D normal, Effects effects)
- {
- Origin = origin;
- this.normal = normal;
- if (bitmap == null)
- {
- Bitmap = null;
- return;
- }
- Bitmap bitmap2 = new Bitmap(srcRect.Width, srcRect.Height);
- using (Graphics graphics = Graphics.FromImage(bitmap2))
- {
- graphics.DrawImage(bitmap, new Rectangle(0, 0, bitmap2.Width, bitmap2.Height), srcRect, GraphicsUnit.Pixel);
- }
- flipHorizontally = (byte)(effects & Effects.FlipHorizontally) == 1;
- flipVertically = (byte)(effects & Effects.FlipVertically) == 2;
- Bitmap = bitmap2;
- }
-
- public override float HitTest(PointF location)
- {
- if (Points == null)
- {
- return -1000f;
- }
- GraphicsPath graphicsPath = new GraphicsPath();
- graphicsPath.AddPolygon(new PointF[]
- {
- Points[0, 0],
- Points[Points.GetLength(0) - 1, 0],
- Points[Points.GetLength(0) - 1, Points.GetLength(1) - 1],
- Points[0, Points.GetLength(1) - 1]
- });
- Region region = new Region(graphicsPath);
- if (region.IsVisible(location))
- {
- for (int i = 0; i < Points.GetLength(0) - 1; i++)
- {
- for (int j = 0; j < Points.GetLength(1) - 1; j++)
- {
- if (visibility[i, j])
- {
- graphicsPath.Reset();
- graphicsPath.AddPolygon(new PointF[]
- {
- Points[i, j],
- Points[i + 1, j],
- Points[i + 1, j + 1],
- Points[i, j + 1]
- });
- if (graphicsPath.IsVisible(location))
- {
- return (globalTransformation * localTransformation * originTranslation * new Point3D(i, j, 0f)).Z;
- }
- }
- }
- }
- }
- return -1000f;
- }
-
- private List texelList = new List();
-
- internal PointF[,] Points;
-
- internal double[,] ZOrder;
-
- internal bool IsVisible = true;
-
- private bool[,] visibility;
-
- private Bitmap bitmap;
-
- private bool flipHorizontally;
-
- private bool flipVertically;
-
- private int width;
-
- private int height;
-
- private Point3D normal;
- }
-}
diff --git a/PCK-Studio/Controls/CustomTabControl.cs b/PCK-Studio/Controls/CustomTabControl.cs
new file mode 100644
index 00000000..a9e09f03
--- /dev/null
+++ b/PCK-Studio/Controls/CustomTabControl.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+
+using MetroFramework.Controls;
+using MetroFramework.Drawing;
+
+
+namespace PckStudio.Controls
+{
+ internal class CustomTabControl : MetroTabControl
+ {
+ private const string CloseChar = "×";
+ private Size CloseButtonSize = new Size(7, 7);
+ private const int StartIndex = 1;
+
+ [Browsable(true)]
+ public event EventHandler PageClosing;
+
+ public CustomTabControl()
+ : base()
+ {
+ }
+
+ private Rectangle GetCloseButtonArea(Rectangle tabArea)
+ {
+ Size closeBtnSz = CloseButtonSize;
+ var closeBtnPt = new Point(
+ tabArea.Right - closeBtnSz.Width,
+ tabArea.Top + 2 + (tabArea.Height - closeBtnSz.Height) / 2);
+ return new Rectangle(closeBtnPt, closeBtnSz);
+ }
+
+ protected override void OnMouseClick(MouseEventArgs e)
+ {
+ base.OnMouseClick(e);
+ if (SelectedIndex < StartIndex)
+ return;
+ Rectangle tabArea = GetTabRect(SelectedIndex);
+ Rectangle buttonArea = GetCloseButtonArea(tabArea);
+ if (buttonArea.Contains(e.Location))
+ {
+ var eventArg = new PageClosingEventArgs(TabPages[SelectedIndex]);
+ PageClosing?.Invoke(this, eventArg);
+ if (!eventArg.Cancel)
+ {
+ SelectedIndex -= 1;
+ TabPages.RemoveAt(SelectedIndex + 1);
+ }
+ }
+ }
+
+ protected override void OnCustomPaintForeground(MetroPaintEventArgs e)
+ {
+ base.OnCustomPaintForeground(e);
+ if (SelectedIndex < StartIndex)
+ return;
+ // Draw Close button
+ Rectangle tabArea = GetTabRect(SelectedIndex);
+
+ Rectangle buttonArea = GetCloseButtonArea(tabArea);
+
+ e.Graphics.FillRectangle(MetroPaint.GetStyleBrush(Style), buttonArea);
+ e.Graphics.DrawString(
+ CloseChar,
+ Font,
+ new SolidBrush(MetroPaint.ForeColor.Title(Theme)),
+ buttonArea.Right - buttonArea.Width - 2, buttonArea.Top - 4);
+ }
+
+ //protected override void OnPaintForeground(PaintEventArgs e)
+ //{
+ // base.OnPaintForeground(e);
+ // for (int i = StartIndex; i < TabPages.Count; i++)
+ // {
+ // // Draw Close button
+ // Rectangle tabArea = GetTabRect(i);
+
+ // Rectangle buttonArea = GetCloseButtonArea(tabArea);
+
+ // e.Graphics.FillRectangle(MetroPaint.GetStyleBrush(Style), buttonArea);
+ // e.Graphics.DrawString(
+ // CloseChar,
+ // Font,
+ // new SolidBrush(MetroPaint.ForeColor.Title(Theme)),
+ // buttonArea.Right - buttonArea.Width - 2, buttonArea.Top - 4);
+ // }
+ //}
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Controls/EditorControl.cs b/PCK-Studio/Controls/EditorControl.cs
new file mode 100644
index 00000000..6a7259fa
--- /dev/null
+++ b/PCK-Studio/Controls/EditorControl.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using PckStudio.Interfaces;
+
+namespace PckStudio.Controls
+{
+ internal class EditorControl : UserControl, IEditor where T : class
+ {
+ public T EditorValue { get; }
+
+ public ISaveContext SaveContext { get; }
+
+ public EditorControl()
+ {
+ }
+
+ protected EditorControl(T value, ISaveContext saveContext)
+ {
+ _ = value ?? throw new ArgumentNullException(nameof(value));
+ EditorValue = value;
+ SaveContext = saveContext;
+ }
+
+ protected override void OnControlRemoved(ControlEventArgs e)
+ {
+ if (SaveContext.AutoSave)
+ Save();
+ base.OnControlRemoved(e);
+ }
+
+ public void Save() => SaveContext.Save(EditorValue);
+
+ public virtual void SaveAs() => throw new NotImplementedException();
+
+ public virtual void Close() => throw new NotImplementedException();
+
+ public virtual void UpdateView() => throw new NotImplementedException();
+ }
+}
diff --git a/PCK-Studio/Controls/EditorForm.cs b/PCK-Studio/Controls/EditorForm.cs
new file mode 100644
index 00000000..e492f697
--- /dev/null
+++ b/PCK-Studio/Controls/EditorForm.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using MetroFramework.Forms;
+using PckStudio.Interfaces;
+
+namespace PckStudio.Controls
+{
+ public class EditorForm : MetroForm where T : class
+ {
+ protected T EditorValue;
+ private readonly ISaveContext SaveContext;
+
+ private EditorForm()
+ {
+ }
+
+ protected EditorForm(T value, ISaveContext saveContext)
+ {
+ _ = value ?? throw new ArgumentNullException(nameof(value));
+ EditorValue = value;
+ SaveContext = saveContext;
+ }
+
+ protected void Save() => SaveContext.Save(EditorValue);
+
+ protected override void OnFormClosing(FormClosingEventArgs e)
+ {
+ if (SaveContext.AutoSave)
+ Save();
+ base.OnFormClosing(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Controls/PageClosingEventArgs.cs b/PCK-Studio/Controls/PageClosingEventArgs.cs
new file mode 100644
index 00000000..ac8de3a4
--- /dev/null
+++ b/PCK-Studio/Controls/PageClosingEventArgs.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace PckStudio.Controls
+{
+ internal class PageClosingEventArgs : CancelEventArgs
+ {
+ private readonly TabPage page;
+ public TabPage Page => page;
+
+ public PageClosingEventArgs(TabPage page)
+ : base()
+ {
+ this.page = page;
+ }
+ }
+}
diff --git a/PCK-Studio/Controls/PckEditor.Designer.cs b/PCK-Studio/Controls/PckEditor.Designer.cs
new file mode 100644
index 00000000..a5351572
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.Designer.cs
@@ -0,0 +1,824 @@
+using System.Windows.Forms;
+
+namespace PckStudio.Controls
+{
+ partial class PckEditor
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.PictureBox logoPictureBox;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PckEditor));
+ this.pckFileLabel = new MetroFramework.Controls.MetroLabel();
+ this.labelImageSize = new MetroFramework.Controls.MetroLabel();
+ this.fileEntryCountLabel = new MetroFramework.Controls.MetroLabel();
+ this.PropertiesTabControl = new MetroFramework.Controls.MetroTabControl();
+ this.MetaTab = new MetroFramework.Controls.MetroTabPage();
+ this.metroLabel2 = new MetroFramework.Controls.MetroLabel();
+ this.entryTypeTextBox = new MetroFramework.Controls.MetroTextBox();
+ this.entryDataTextBox = new MetroFramework.Controls.MetroTextBox();
+ this.buttonEdit = new MetroFramework.Controls.MetroButton();
+ this.metroLabel1 = new MetroFramework.Controls.MetroLabel();
+ this.treeMeta = new System.Windows.Forms.TreeView();
+ this.contextMenuMetaTree = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.addEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addBOXEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addANIMEntryToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.addMultipleEntriesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.deleteEntryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.editAllEntriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.label11 = new MetroFramework.Controls.MetroLabel();
+ this.treeViewMain = new System.Windows.Forms.TreeView();
+ this.contextMenuPCKEntries = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.createToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.folderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.createAnimatedTextureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.audiopckToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.colourscolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.CreateSkinsPCKToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.behavioursbinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.entityMaterialsbinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importSkinsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importSkinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importExtractedSkinsFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addTextureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.addFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.as3DSTextureFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setFileTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.capeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.textureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.languagesFileLOCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.gameRulesFileGRFToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.audioPCKFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.coloursCOLFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.gameRulesHeaderGRHToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.skinsPCKToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.modelsFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.behavioursFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.entityMaterialsFileBINToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
+ this.miscFunctionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.generateMipMapTextureToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.viewFileInfoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.correctSkinDecimalsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setSubPCKEndiannessToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.setModelContainerFormatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.version3114ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.extractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
+ this.cloneFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.renameFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.replaceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.deleteFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.imageList = new System.Windows.Forms.ImageList(this.components);
+ this.addMultipleEntriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.LittleEndianCheckBox = new MetroFramework.Controls.MetroCheckBox();
+ this.previewPictureBox = new PckStudio.ToolboxItems.InterpolationPictureBox();
+ logoPictureBox = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(logoPictureBox)).BeginInit();
+ this.PropertiesTabControl.SuspendLayout();
+ this.MetaTab.SuspendLayout();
+ this.contextMenuMetaTree.SuspendLayout();
+ this.contextMenuPCKEntries.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // logoPictureBox
+ //
+ resources.ApplyResources(logoPictureBox, "logoPictureBox");
+ logoPictureBox.Name = "logoPictureBox";
+ logoPictureBox.TabStop = false;
+ //
+ // pckFileLabel
+ //
+ this.pckFileLabel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
+ resources.ApplyResources(this.pckFileLabel, "pckFileLabel");
+ this.pckFileLabel.Name = "pckFileLabel";
+ this.pckFileLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // labelImageSize
+ //
+ resources.ApplyResources(this.labelImageSize, "labelImageSize");
+ this.labelImageSize.Name = "labelImageSize";
+ this.labelImageSize.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // fileEntryCountLabel
+ //
+ resources.ApplyResources(this.fileEntryCountLabel, "fileEntryCountLabel");
+ this.fileEntryCountLabel.Name = "fileEntryCountLabel";
+ this.fileEntryCountLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // PropertiesTabControl
+ //
+ this.PropertiesTabControl.Controls.Add(this.MetaTab);
+ resources.ApplyResources(this.PropertiesTabControl, "PropertiesTabControl");
+ this.PropertiesTabControl.Name = "PropertiesTabControl";
+ this.PropertiesTabControl.SelectedIndex = 0;
+ this.PropertiesTabControl.Style = MetroFramework.MetroColorStyle.Silver;
+ this.PropertiesTabControl.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.PropertiesTabControl.UseSelectable = true;
+ //
+ // MetaTab
+ //
+ this.MetaTab.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
+ this.MetaTab.Controls.Add(this.metroLabel2);
+ this.MetaTab.Controls.Add(this.entryTypeTextBox);
+ this.MetaTab.Controls.Add(this.entryDataTextBox);
+ this.MetaTab.Controls.Add(this.buttonEdit);
+ this.MetaTab.Controls.Add(this.metroLabel1);
+ this.MetaTab.Controls.Add(this.treeMeta);
+ this.MetaTab.HorizontalScrollbarBarColor = true;
+ this.MetaTab.HorizontalScrollbarHighlightOnWheel = false;
+ this.MetaTab.HorizontalScrollbarSize = 10;
+ resources.ApplyResources(this.MetaTab, "MetaTab");
+ this.MetaTab.Name = "MetaTab";
+ this.MetaTab.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.MetaTab.VerticalScrollbarBarColor = true;
+ this.MetaTab.VerticalScrollbarHighlightOnWheel = false;
+ this.MetaTab.VerticalScrollbarSize = 10;
+ //
+ // metroLabel2
+ //
+ resources.ApplyResources(this.metroLabel2, "metroLabel2");
+ this.metroLabel2.Name = "metroLabel2";
+ this.metroLabel2.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // entryTypeTextBox
+ //
+ resources.ApplyResources(this.entryTypeTextBox, "entryTypeTextBox");
+ //
+ //
+ //
+ this.entryTypeTextBox.CustomButton.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image")));
+ this.entryTypeTextBox.CustomButton.ImeMode = ((System.Windows.Forms.ImeMode)(resources.GetObject("resource.ImeMode")));
+ this.entryTypeTextBox.CustomButton.Location = ((System.Drawing.Point)(resources.GetObject("resource.Location")));
+ this.entryTypeTextBox.CustomButton.Name = "";
+ this.entryTypeTextBox.CustomButton.Size = ((System.Drawing.Size)(resources.GetObject("resource.Size")));
+ this.entryTypeTextBox.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
+ this.entryTypeTextBox.CustomButton.TabIndex = ((int)(resources.GetObject("resource.TabIndex")));
+ this.entryTypeTextBox.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
+ this.entryTypeTextBox.CustomButton.UseSelectable = true;
+ this.entryTypeTextBox.CustomButton.Visible = ((bool)(resources.GetObject("resource.Visible")));
+ this.entryTypeTextBox.Lines = new string[0];
+ this.entryTypeTextBox.MaxLength = 32767;
+ this.entryTypeTextBox.Name = "entryTypeTextBox";
+ this.entryTypeTextBox.PasswordChar = '\0';
+ this.entryTypeTextBox.ScrollBars = System.Windows.Forms.ScrollBars.None;
+ this.entryTypeTextBox.SelectedText = "";
+ this.entryTypeTextBox.SelectionLength = 0;
+ this.entryTypeTextBox.SelectionStart = 0;
+ this.entryTypeTextBox.ShortcutsEnabled = true;
+ this.entryTypeTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.entryTypeTextBox.UseSelectable = true;
+ this.entryTypeTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
+ this.entryTypeTextBox.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
+ //
+ // entryDataTextBox
+ //
+ resources.ApplyResources(this.entryDataTextBox, "entryDataTextBox");
+ //
+ //
+ //
+ this.entryDataTextBox.CustomButton.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image1")));
+ this.entryDataTextBox.CustomButton.ImeMode = ((System.Windows.Forms.ImeMode)(resources.GetObject("resource.ImeMode1")));
+ this.entryDataTextBox.CustomButton.Location = ((System.Drawing.Point)(resources.GetObject("resource.Location1")));
+ this.entryDataTextBox.CustomButton.Name = "";
+ this.entryDataTextBox.CustomButton.Size = ((System.Drawing.Size)(resources.GetObject("resource.Size1")));
+ this.entryDataTextBox.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
+ this.entryDataTextBox.CustomButton.TabIndex = ((int)(resources.GetObject("resource.TabIndex1")));
+ this.entryDataTextBox.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
+ this.entryDataTextBox.CustomButton.UseSelectable = true;
+ this.entryDataTextBox.CustomButton.Visible = ((bool)(resources.GetObject("resource.Visible1")));
+ this.entryDataTextBox.Lines = new string[0];
+ this.entryDataTextBox.MaxLength = 32767;
+ this.entryDataTextBox.Name = "entryDataTextBox";
+ this.entryDataTextBox.PasswordChar = '\0';
+ this.entryDataTextBox.ScrollBars = System.Windows.Forms.ScrollBars.None;
+ this.entryDataTextBox.SelectedText = "";
+ this.entryDataTextBox.SelectionLength = 0;
+ this.entryDataTextBox.SelectionStart = 0;
+ this.entryDataTextBox.ShortcutsEnabled = true;
+ this.entryDataTextBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.entryDataTextBox.UseSelectable = true;
+ this.entryDataTextBox.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
+ this.entryDataTextBox.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
+ //
+ // buttonEdit
+ //
+ resources.ApplyResources(this.buttonEdit, "buttonEdit");
+ this.buttonEdit.Name = "buttonEdit";
+ this.buttonEdit.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.buttonEdit.UseSelectable = true;
+ this.buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click);
+ //
+ // metroLabel1
+ //
+ resources.ApplyResources(this.metroLabel1, "metroLabel1");
+ this.metroLabel1.Name = "metroLabel1";
+ this.metroLabel1.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // treeMeta
+ //
+ this.treeMeta.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(13)))), ((int)(((byte)(13)))), ((int)(((byte)(13)))));
+ this.treeMeta.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.treeMeta.ContextMenuStrip = this.contextMenuMetaTree;
+ resources.ApplyResources(this.treeMeta, "treeMeta");
+ this.treeMeta.ForeColor = System.Drawing.SystemColors.Window;
+ this.treeMeta.Name = "treeMeta";
+ this.treeMeta.PathSeparator = "/";
+ this.treeMeta.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeMeta_AfterSelect);
+ this.treeMeta.DoubleClick += new System.EventHandler(this.treeMeta_DoubleClick);
+ this.treeMeta.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeMeta_KeyDown);
+ //
+ // contextMenuMetaTree
+ //
+ this.contextMenuMetaTree.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addEntryToolStripMenuItem,
+ this.addMultipleEntriesToolStripMenuItem1,
+ this.deleteEntryToolStripMenuItem,
+ this.editAllEntriesToolStripMenuItem});
+ this.contextMenuMetaTree.Name = "contextMenuStrip1";
+ resources.ApplyResources(this.contextMenuMetaTree, "contextMenuMetaTree");
+ //
+ // addEntryToolStripMenuItem
+ //
+ this.addEntryToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addEntryToolStripMenuItem1,
+ this.addBOXEntryToolStripMenuItem1,
+ this.addANIMEntryToolStripMenuItem1});
+ resources.ApplyResources(this.addEntryToolStripMenuItem, "addEntryToolStripMenuItem");
+ this.addEntryToolStripMenuItem.Name = "addEntryToolStripMenuItem";
+ //
+ // addEntryToolStripMenuItem1
+ //
+ this.addEntryToolStripMenuItem1.Name = "addEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addEntryToolStripMenuItem1, "addEntryToolStripMenuItem1");
+ this.addEntryToolStripMenuItem1.Click += new System.EventHandler(this.addEntryToolStripMenuItem_Click);
+ //
+ // addBOXEntryToolStripMenuItem1
+ //
+ this.addBOXEntryToolStripMenuItem1.Name = "addBOXEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addBOXEntryToolStripMenuItem1, "addBOXEntryToolStripMenuItem1");
+ this.addBOXEntryToolStripMenuItem1.Click += new System.EventHandler(this.addBOXEntryToolStripMenuItem1_Click);
+ //
+ // addANIMEntryToolStripMenuItem1
+ //
+ this.addANIMEntryToolStripMenuItem1.Name = "addANIMEntryToolStripMenuItem1";
+ resources.ApplyResources(this.addANIMEntryToolStripMenuItem1, "addANIMEntryToolStripMenuItem1");
+ this.addANIMEntryToolStripMenuItem1.Click += new System.EventHandler(this.addANIMEntryToolStripMenuItem1_Click);
+ //
+ // addMultipleEntriesToolStripMenuItem1
+ //
+ this.addMultipleEntriesToolStripMenuItem1.Name = "addMultipleEntriesToolStripMenuItem1";
+ resources.ApplyResources(this.addMultipleEntriesToolStripMenuItem1, "addMultipleEntriesToolStripMenuItem1");
+ this.addMultipleEntriesToolStripMenuItem1.Click += new System.EventHandler(this.addMultipleEntriesToolStripMenuItem1_Click);
+ //
+ // deleteEntryToolStripMenuItem
+ //
+ this.deleteEntryToolStripMenuItem.Image = global::PckStudio.Properties.Resources.file_delete;
+ this.deleteEntryToolStripMenuItem.Name = "deleteEntryToolStripMenuItem";
+ resources.ApplyResources(this.deleteEntryToolStripMenuItem, "deleteEntryToolStripMenuItem");
+ this.deleteEntryToolStripMenuItem.Click += new System.EventHandler(this.deleteEntryToolStripMenuItem_Click);
+ //
+ // editAllEntriesToolStripMenuItem
+ //
+ this.editAllEntriesToolStripMenuItem.Name = "editAllEntriesToolStripMenuItem";
+ resources.ApplyResources(this.editAllEntriesToolStripMenuItem, "editAllEntriesToolStripMenuItem");
+ this.editAllEntriesToolStripMenuItem.Click += new System.EventHandler(this.editAllEntriesToolStripMenuItem_Click);
+ //
+ // label11
+ //
+ resources.ApplyResources(this.label11, "label11");
+ this.label11.Name = "label11";
+ //
+ // treeViewMain
+ //
+ this.treeViewMain.AllowDrop = true;
+ this.treeViewMain.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(12)))), ((int)(((byte)(12)))), ((int)(((byte)(12)))));
+ this.treeViewMain.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.treeViewMain.ContextMenuStrip = this.contextMenuPCKEntries;
+ resources.ApplyResources(this.treeViewMain, "treeViewMain");
+ this.treeViewMain.ForeColor = System.Drawing.Color.White;
+ this.treeViewMain.ImageList = this.imageList;
+ this.treeViewMain.LabelEdit = true;
+ this.treeViewMain.Name = "treeViewMain";
+ this.treeViewMain.PathSeparator = "/";
+ this.treeViewMain.BeforeLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.treeViewMain_BeforeLabelEdit);
+ this.treeViewMain.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.treeViewMain_ItemDrag);
+ this.treeViewMain.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeViewMain_AfterSelect);
+ this.treeViewMain.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeViewMain_NodeMouseClick);
+ this.treeViewMain.DragDrop += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragDrop);
+ this.treeViewMain.DragEnter += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragEnter);
+ this.treeViewMain.DragOver += new System.Windows.Forms.DragEventHandler(this.treeViewMain_DragOver);
+ this.treeViewMain.DoubleClick += new System.EventHandler(this.treeViewMain_DoubleClick);
+ this.treeViewMain.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeViewMain_KeyDown);
+ //
+ // contextMenuPCKEntries
+ //
+ this.contextMenuPCKEntries.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.createToolStripMenuItem,
+ this.importSkinsToolStripMenuItem,
+ this.exportToolStripMenuItem,
+ this.setFileTypeToolStripMenuItem,
+ this.toolStripSeparator5,
+ this.miscFunctionsToolStripMenuItem,
+ this.extractToolStripMenuItem,
+ this.toolStripSeparator6,
+ this.cloneFileToolStripMenuItem,
+ this.renameFileToolStripMenuItem,
+ this.replaceToolStripMenuItem,
+ this.deleteFileToolStripMenuItem});
+ this.contextMenuPCKEntries.Name = "contextMenuStrip1";
+ resources.ApplyResources(this.contextMenuPCKEntries, "contextMenuPCKEntries");
+ this.contextMenuPCKEntries.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuPCKEntries_Opening);
+ //
+ // createToolStripMenuItem
+ //
+ this.createToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.folderToolStripMenuItem,
+ this.skinToolStripMenuItem,
+ this.createAnimatedTextureToolStripMenuItem,
+ this.audiopckToolStripMenuItem,
+ this.colourscolToolStripMenuItem,
+ this.CreateSkinsPCKToolStripMenuItem1,
+ this.behavioursbinToolStripMenuItem,
+ this.entityMaterialsbinToolStripMenuItem});
+ resources.ApplyResources(this.createToolStripMenuItem, "createToolStripMenuItem");
+ this.createToolStripMenuItem.Name = "createToolStripMenuItem";
+ //
+ // folderToolStripMenuItem
+ //
+ resources.ApplyResources(this.folderToolStripMenuItem, "folderToolStripMenuItem");
+ this.folderToolStripMenuItem.Name = "folderToolStripMenuItem";
+ this.folderToolStripMenuItem.Click += new System.EventHandler(this.folderToolStripMenuItem_Click);
+ //
+ // skinToolStripMenuItem
+ //
+ resources.ApplyResources(this.skinToolStripMenuItem, "skinToolStripMenuItem");
+ this.skinToolStripMenuItem.Name = "skinToolStripMenuItem";
+ this.skinToolStripMenuItem.Click += new System.EventHandler(this.createSkinToolStripMenuItem_Click);
+ //
+ // createAnimatedTextureToolStripMenuItem
+ //
+ resources.ApplyResources(this.createAnimatedTextureToolStripMenuItem, "createAnimatedTextureToolStripMenuItem");
+ this.createAnimatedTextureToolStripMenuItem.Name = "createAnimatedTextureToolStripMenuItem";
+ this.createAnimatedTextureToolStripMenuItem.Click += new System.EventHandler(this.createAnimatedTextureToolStripMenuItem_Click);
+ //
+ // audiopckToolStripMenuItem
+ //
+ this.audiopckToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BINKA_ICON;
+ this.audiopckToolStripMenuItem.Name = "audiopckToolStripMenuItem";
+ resources.ApplyResources(this.audiopckToolStripMenuItem, "audiopckToolStripMenuItem");
+ this.audiopckToolStripMenuItem.Click += new System.EventHandler(this.audiopckToolStripMenuItem_Click);
+ //
+ // colourscolToolStripMenuItem
+ //
+ this.colourscolToolStripMenuItem.Image = global::PckStudio.Properties.Resources.COL_ICON;
+ this.colourscolToolStripMenuItem.Name = "colourscolToolStripMenuItem";
+ resources.ApplyResources(this.colourscolToolStripMenuItem, "colourscolToolStripMenuItem");
+ this.colourscolToolStripMenuItem.Click += new System.EventHandler(this.colourscolToolStripMenuItem_Click);
+ //
+ // CreateSkinsPCKToolStripMenuItem1
+ //
+ this.CreateSkinsPCKToolStripMenuItem1.Image = global::PckStudio.Properties.Resources.SKINS_ICON;
+ this.CreateSkinsPCKToolStripMenuItem1.Name = "CreateSkinsPCKToolStripMenuItem1";
+ resources.ApplyResources(this.CreateSkinsPCKToolStripMenuItem1, "CreateSkinsPCKToolStripMenuItem1");
+ this.CreateSkinsPCKToolStripMenuItem1.Click += new System.EventHandler(this.CreateSkinsPCKToolStripMenuItem1_Click);
+ //
+ // behavioursbinToolStripMenuItem
+ //
+ this.behavioursbinToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BEHAVIOURS_ICON;
+ this.behavioursbinToolStripMenuItem.Name = "behavioursbinToolStripMenuItem";
+ resources.ApplyResources(this.behavioursbinToolStripMenuItem, "behavioursbinToolStripMenuItem");
+ this.behavioursbinToolStripMenuItem.Click += new System.EventHandler(this.behavioursbinToolStripMenuItem_Click);
+ //
+ // entityMaterialsbinToolStripMenuItem
+ //
+ this.entityMaterialsbinToolStripMenuItem.Image = global::PckStudio.Properties.Resources.ENTITY_MATERIALS_ICON;
+ this.entityMaterialsbinToolStripMenuItem.Name = "entityMaterialsbinToolStripMenuItem";
+ resources.ApplyResources(this.entityMaterialsbinToolStripMenuItem, "entityMaterialsbinToolStripMenuItem");
+ this.entityMaterialsbinToolStripMenuItem.Click += new System.EventHandler(this.entityMaterialsbinToolStripMenuItem_Click);
+ //
+ // importSkinsToolStripMenuItem
+ //
+ this.importSkinsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.importSkinToolStripMenuItem,
+ this.importExtractedSkinsFolderToolStripMenuItem,
+ this.addTextureToolStripMenuItem,
+ this.addFileToolStripMenuItem});
+ resources.ApplyResources(this.importSkinsToolStripMenuItem, "importSkinsToolStripMenuItem");
+ this.importSkinsToolStripMenuItem.Name = "importSkinsToolStripMenuItem";
+ //
+ // importSkinToolStripMenuItem
+ //
+ resources.ApplyResources(this.importSkinToolStripMenuItem, "importSkinToolStripMenuItem");
+ this.importSkinToolStripMenuItem.Name = "importSkinToolStripMenuItem";
+ this.importSkinToolStripMenuItem.Click += new System.EventHandler(this.importSkinToolStripMenuItem_Click);
+ //
+ // importExtractedSkinsFolderToolStripMenuItem
+ //
+ resources.ApplyResources(this.importExtractedSkinsFolderToolStripMenuItem, "importExtractedSkinsFolderToolStripMenuItem");
+ this.importExtractedSkinsFolderToolStripMenuItem.Name = "importExtractedSkinsFolderToolStripMenuItem";
+ this.importExtractedSkinsFolderToolStripMenuItem.Click += new System.EventHandler(this.importExtractedSkinsFolder);
+ //
+ // addTextureToolStripMenuItem
+ //
+ this.addTextureToolStripMenuItem.Image = global::PckStudio.Properties.Resources.AddTexture;
+ this.addTextureToolStripMenuItem.Name = "addTextureToolStripMenuItem";
+ resources.ApplyResources(this.addTextureToolStripMenuItem, "addTextureToolStripMenuItem");
+ this.addTextureToolStripMenuItem.Click += new System.EventHandler(this.addTextureToolStripMenuItem_Click);
+ //
+ // addFileToolStripMenuItem
+ //
+ this.addFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.blank;
+ this.addFileToolStripMenuItem.Name = "addFileToolStripMenuItem";
+ resources.ApplyResources(this.addFileToolStripMenuItem, "addFileToolStripMenuItem");
+ this.addFileToolStripMenuItem.Click += new System.EventHandler(this.addFileToolStripMenuItem_Click);
+ //
+ // exportToolStripMenuItem
+ //
+ this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.as3DSTextureFileToolStripMenuItem});
+ this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
+ resources.ApplyResources(this.exportToolStripMenuItem, "exportToolStripMenuItem");
+ //
+ // as3DSTextureFileToolStripMenuItem
+ //
+ this.as3DSTextureFileToolStripMenuItem.Name = "as3DSTextureFileToolStripMenuItem";
+ resources.ApplyResources(this.as3DSTextureFileToolStripMenuItem, "as3DSTextureFileToolStripMenuItem");
+ this.as3DSTextureFileToolStripMenuItem.Click += new System.EventHandler(this.as3DSTextureFileToolStripMenuItem_Click);
+ //
+ // setFileTypeToolStripMenuItem
+ //
+ this.setFileTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.skinToolStripMenuItem1,
+ this.capeToolStripMenuItem,
+ this.textureToolStripMenuItem,
+ this.languagesFileLOCToolStripMenuItem,
+ this.gameRulesFileGRFToolStripMenuItem,
+ this.audioPCKFileToolStripMenuItem,
+ this.coloursCOLFileToolStripMenuItem,
+ this.gameRulesHeaderGRHToolStripMenuItem,
+ this.skinsPCKToolStripMenuItem,
+ this.modelsFileBINToolStripMenuItem,
+ this.behavioursFileBINToolStripMenuItem,
+ this.entityMaterialsFileBINToolStripMenuItem});
+ this.setFileTypeToolStripMenuItem.Name = "setFileTypeToolStripMenuItem";
+ resources.ApplyResources(this.setFileTypeToolStripMenuItem, "setFileTypeToolStripMenuItem");
+ //
+ // skinToolStripMenuItem1
+ //
+ this.skinToolStripMenuItem1.Image = global::PckStudio.Properties.Resources.SKIN_ICON;
+ this.skinToolStripMenuItem1.Name = "skinToolStripMenuItem1";
+ resources.ApplyResources(this.skinToolStripMenuItem1, "skinToolStripMenuItem1");
+ //
+ // capeToolStripMenuItem
+ //
+ this.capeToolStripMenuItem.Image = global::PckStudio.Properties.Resources.CAPE_ICON;
+ this.capeToolStripMenuItem.Name = "capeToolStripMenuItem";
+ resources.ApplyResources(this.capeToolStripMenuItem, "capeToolStripMenuItem");
+ //
+ // textureToolStripMenuItem
+ //
+ this.textureToolStripMenuItem.Image = global::PckStudio.Properties.Resources.TEXTURE_ICON;
+ this.textureToolStripMenuItem.Name = "textureToolStripMenuItem";
+ resources.ApplyResources(this.textureToolStripMenuItem, "textureToolStripMenuItem");
+ //
+ // languagesFileLOCToolStripMenuItem
+ //
+ this.languagesFileLOCToolStripMenuItem.Image = global::PckStudio.Properties.Resources.LOC_ICON;
+ this.languagesFileLOCToolStripMenuItem.Name = "languagesFileLOCToolStripMenuItem";
+ resources.ApplyResources(this.languagesFileLOCToolStripMenuItem, "languagesFileLOCToolStripMenuItem");
+ //
+ // gameRulesFileGRFToolStripMenuItem
+ //
+ this.gameRulesFileGRFToolStripMenuItem.Image = global::PckStudio.Properties.Resources.GRF_ICON;
+ this.gameRulesFileGRFToolStripMenuItem.Name = "gameRulesFileGRFToolStripMenuItem";
+ resources.ApplyResources(this.gameRulesFileGRFToolStripMenuItem, "gameRulesFileGRFToolStripMenuItem");
+ //
+ // audioPCKFileToolStripMenuItem
+ //
+ this.audioPCKFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BINKA_ICON;
+ this.audioPCKFileToolStripMenuItem.Name = "audioPCKFileToolStripMenuItem";
+ resources.ApplyResources(this.audioPCKFileToolStripMenuItem, "audioPCKFileToolStripMenuItem");
+ //
+ // coloursCOLFileToolStripMenuItem
+ //
+ this.coloursCOLFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.COL_ICON;
+ this.coloursCOLFileToolStripMenuItem.Name = "coloursCOLFileToolStripMenuItem";
+ resources.ApplyResources(this.coloursCOLFileToolStripMenuItem, "coloursCOLFileToolStripMenuItem");
+ //
+ // gameRulesHeaderGRHToolStripMenuItem
+ //
+ this.gameRulesHeaderGRHToolStripMenuItem.Image = global::PckStudio.Properties.Resources.GRH_ICON;
+ this.gameRulesHeaderGRHToolStripMenuItem.Name = "gameRulesHeaderGRHToolStripMenuItem";
+ resources.ApplyResources(this.gameRulesHeaderGRHToolStripMenuItem, "gameRulesHeaderGRHToolStripMenuItem");
+ //
+ // skinsPCKToolStripMenuItem
+ //
+ this.skinsPCKToolStripMenuItem.Image = global::PckStudio.Properties.Resources.SKINS_ICON;
+ this.skinsPCKToolStripMenuItem.Name = "skinsPCKToolStripMenuItem";
+ resources.ApplyResources(this.skinsPCKToolStripMenuItem, "skinsPCKToolStripMenuItem");
+ //
+ // modelsFileBINToolStripMenuItem
+ //
+ this.modelsFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.MODELS_ICON;
+ this.modelsFileBINToolStripMenuItem.Name = "modelsFileBINToolStripMenuItem";
+ resources.ApplyResources(this.modelsFileBINToolStripMenuItem, "modelsFileBINToolStripMenuItem");
+ //
+ // behavioursFileBINToolStripMenuItem
+ //
+ this.behavioursFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.BEHAVIOURS_ICON;
+ this.behavioursFileBINToolStripMenuItem.Name = "behavioursFileBINToolStripMenuItem";
+ resources.ApplyResources(this.behavioursFileBINToolStripMenuItem, "behavioursFileBINToolStripMenuItem");
+ //
+ // entityMaterialsFileBINToolStripMenuItem
+ //
+ this.entityMaterialsFileBINToolStripMenuItem.Image = global::PckStudio.Properties.Resources.ENTITY_MATERIALS_ICON;
+ this.entityMaterialsFileBINToolStripMenuItem.Name = "entityMaterialsFileBINToolStripMenuItem";
+ resources.ApplyResources(this.entityMaterialsFileBINToolStripMenuItem, "entityMaterialsFileBINToolStripMenuItem");
+ //
+ // toolStripSeparator5
+ //
+ this.toolStripSeparator5.Name = "toolStripSeparator5";
+ resources.ApplyResources(this.toolStripSeparator5, "toolStripSeparator5");
+ //
+ // miscFunctionsToolStripMenuItem
+ //
+ this.miscFunctionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.generateMipMapTextureToolStripMenuItem1,
+ this.viewFileInfoToolStripMenuItem,
+ this.correctSkinDecimalsToolStripMenuItem,
+ this.setSubPCKEndiannessToolStripMenuItem,
+ this.setModelContainerFormatToolStripMenuItem});
+ this.miscFunctionsToolStripMenuItem.Name = "miscFunctionsToolStripMenuItem";
+ resources.ApplyResources(this.miscFunctionsToolStripMenuItem, "miscFunctionsToolStripMenuItem");
+ //
+ // generateMipMapTextureToolStripMenuItem1
+ //
+ this.generateMipMapTextureToolStripMenuItem1.Name = "generateMipMapTextureToolStripMenuItem1";
+ resources.ApplyResources(this.generateMipMapTextureToolStripMenuItem1, "generateMipMapTextureToolStripMenuItem1");
+ this.generateMipMapTextureToolStripMenuItem1.Click += new System.EventHandler(this.generateMipMapTextureToolStripMenuItem_Click);
+ //
+ // viewFileInfoToolStripMenuItem
+ //
+ this.viewFileInfoToolStripMenuItem.Name = "viewFileInfoToolStripMenuItem";
+ resources.ApplyResources(this.viewFileInfoToolStripMenuItem, "viewFileInfoToolStripMenuItem");
+ this.viewFileInfoToolStripMenuItem.Click += new System.EventHandler(this.viewFileInfoToolStripMenuItem_Click);
+ //
+ // correctSkinDecimalsToolStripMenuItem
+ //
+ this.correctSkinDecimalsToolStripMenuItem.Name = "correctSkinDecimalsToolStripMenuItem";
+ resources.ApplyResources(this.correctSkinDecimalsToolStripMenuItem, "correctSkinDecimalsToolStripMenuItem");
+ this.correctSkinDecimalsToolStripMenuItem.Click += new System.EventHandler(this.correctSkinDecimalsToolStripMenuItem_Click);
+ //
+ // setSubPCKEndiannessToolStripMenuItem
+ //
+ this.setSubPCKEndiannessToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem,
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem});
+ this.setSubPCKEndiannessToolStripMenuItem.Name = "setSubPCKEndiannessToolStripMenuItem";
+ resources.ApplyResources(this.setSubPCKEndiannessToolStripMenuItem, "setSubPCKEndiannessToolStripMenuItem");
+ //
+ // bigEndianXbox360PS3WiiUToolStripMenuItem
+ //
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem.Name = "bigEndianXbox360PS3WiiUToolStripMenuItem";
+ resources.ApplyResources(this.bigEndianXbox360PS3WiiUToolStripMenuItem, "bigEndianXbox360PS3WiiUToolStripMenuItem");
+ this.bigEndianXbox360PS3WiiUToolStripMenuItem.Click += new System.EventHandler(this.bigEndianToolStripMenuItem_Click);
+ //
+ // littleEndianPS4PSVitaSwitchToolStripMenuItem
+ //
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem.Name = "littleEndianPS4PSVitaSwitchToolStripMenuItem";
+ resources.ApplyResources(this.littleEndianPS4PSVitaSwitchToolStripMenuItem, "littleEndianPS4PSVitaSwitchToolStripMenuItem");
+ this.littleEndianPS4PSVitaSwitchToolStripMenuItem.Click += new System.EventHandler(this.littleEndianToolStripMenuItem_Click);
+ //
+ // setModelContainerFormatToolStripMenuItem
+ //
+ this.setModelContainerFormatToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.version1ToolStripMenuItem,
+ this.version2ToolStripMenuItem,
+ this.version3114ToolStripMenuItem});
+ this.setModelContainerFormatToolStripMenuItem.Name = "setModelContainerFormatToolStripMenuItem";
+ resources.ApplyResources(this.setModelContainerFormatToolStripMenuItem, "setModelContainerFormatToolStripMenuItem");
+ //
+ // version1ToolStripMenuItem
+ //
+ this.version1ToolStripMenuItem.Name = "version1ToolStripMenuItem";
+ resources.ApplyResources(this.version1ToolStripMenuItem, "version1ToolStripMenuItem");
+ this.version1ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion1ToolStripMenuItem_Click);
+ //
+ // version2ToolStripMenuItem
+ //
+ this.version2ToolStripMenuItem.Name = "version2ToolStripMenuItem";
+ resources.ApplyResources(this.version2ToolStripMenuItem, "version2ToolStripMenuItem");
+ this.version2ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion2ToolStripMenuItem_Click);
+ //
+ // version3114ToolStripMenuItem
+ //
+ this.version3114ToolStripMenuItem.Name = "version3114ToolStripMenuItem";
+ resources.ApplyResources(this.version3114ToolStripMenuItem, "version3114ToolStripMenuItem");
+ this.version3114ToolStripMenuItem.Click += new System.EventHandler(this.setModelVersion3ToolStripMenuItem_Click);
+ //
+ // extractToolStripMenuItem
+ //
+ resources.ApplyResources(this.extractToolStripMenuItem, "extractToolStripMenuItem");
+ this.extractToolStripMenuItem.Name = "extractToolStripMenuItem";
+ this.extractToolStripMenuItem.Click += new System.EventHandler(this.extractToolStripMenuItem_Click);
+ //
+ // toolStripSeparator6
+ //
+ this.toolStripSeparator6.Name = "toolStripSeparator6";
+ resources.ApplyResources(this.toolStripSeparator6, "toolStripSeparator6");
+ //
+ // cloneFileToolStripMenuItem
+ //
+ this.cloneFileToolStripMenuItem.Name = "cloneFileToolStripMenuItem";
+ resources.ApplyResources(this.cloneFileToolStripMenuItem, "cloneFileToolStripMenuItem");
+ this.cloneFileToolStripMenuItem.Click += new System.EventHandler(this.cloneFileToolStripMenuItem_Click);
+ //
+ // renameFileToolStripMenuItem
+ //
+ resources.ApplyResources(this.renameFileToolStripMenuItem, "renameFileToolStripMenuItem");
+ this.renameFileToolStripMenuItem.Name = "renameFileToolStripMenuItem";
+ this.renameFileToolStripMenuItem.Click += new System.EventHandler(this.renameFileToolStripMenuItem_Click);
+ //
+ // replaceToolStripMenuItem
+ //
+ resources.ApplyResources(this.replaceToolStripMenuItem, "replaceToolStripMenuItem");
+ this.replaceToolStripMenuItem.Name = "replaceToolStripMenuItem";
+ this.replaceToolStripMenuItem.Click += new System.EventHandler(this.replaceToolStripMenuItem_Click);
+ //
+ // deleteFileToolStripMenuItem
+ //
+ this.deleteFileToolStripMenuItem.Image = global::PckStudio.Properties.Resources.file_delete;
+ this.deleteFileToolStripMenuItem.Name = "deleteFileToolStripMenuItem";
+ resources.ApplyResources(this.deleteFileToolStripMenuItem, "deleteFileToolStripMenuItem");
+ this.deleteFileToolStripMenuItem.Click += new System.EventHandler(this.deleteFileToolStripMenuItem_Click);
+ //
+ // imageList
+ //
+ this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
+ resources.ApplyResources(this.imageList, "imageList");
+ this.imageList.TransparentColor = System.Drawing.Color.Transparent;
+ //
+ // addMultipleEntriesToolStripMenuItem
+ //
+ resources.ApplyResources(this.addMultipleEntriesToolStripMenuItem, "addMultipleEntriesToolStripMenuItem");
+ this.addMultipleEntriesToolStripMenuItem.Name = "addMultipleEntriesToolStripMenuItem";
+ //
+ // LittleEndianCheckBox
+ //
+ resources.ApplyResources(this.LittleEndianCheckBox, "LittleEndianCheckBox");
+ this.LittleEndianCheckBox.BackColor = System.Drawing.Color.Transparent;
+ this.LittleEndianCheckBox.Name = "LittleEndianCheckBox";
+ this.LittleEndianCheckBox.Style = MetroFramework.MetroColorStyle.White;
+ this.LittleEndianCheckBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.LittleEndianCheckBox.UseSelectable = true;
+ //
+ // previewPictureBox
+ //
+ resources.ApplyResources(this.previewPictureBox, "previewPictureBox");
+ this.previewPictureBox.BackColor = System.Drawing.Color.Transparent;
+ this.previewPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
+ this.previewPictureBox.Image = global::PckStudio.Properties.Resources.NoImageFound;
+ this.previewPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
+ this.previewPictureBox.Name = "previewPictureBox";
+ this.previewPictureBox.TabStop = false;
+ //
+ // PckEditor
+ //
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(18)))), ((int)(((byte)(18)))), ((int)(((byte)(18)))));
+ resources.ApplyResources(this, "$this");
+ this.Controls.Add(this.previewPictureBox);
+ this.Controls.Add(this.LittleEndianCheckBox);
+ this.Controls.Add(this.pckFileLabel);
+ this.Controls.Add(this.labelImageSize);
+ this.Controls.Add(this.fileEntryCountLabel);
+ this.Controls.Add(this.PropertiesTabControl);
+ this.Controls.Add(this.label11);
+ this.Controls.Add(this.treeViewMain);
+ this.Controls.Add(logoPictureBox);
+ this.ForeColor = System.Drawing.Color.Transparent;
+ this.Name = "PckEditor";
+ this.Load += new System.EventHandler(this.PckEditor_Load);
+ ((System.ComponentModel.ISupportInitialize)(logoPictureBox)).EndInit();
+ this.PropertiesTabControl.ResumeLayout(false);
+ this.MetaTab.ResumeLayout(false);
+ this.MetaTab.PerformLayout();
+ this.contextMenuMetaTree.ResumeLayout(false);
+ this.contextMenuPCKEntries.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private MetroFramework.Controls.MetroLabel pckFileLabel;
+ private MetroFramework.Controls.MetroLabel labelImageSize;
+ private MetroFramework.Controls.MetroLabel fileEntryCountLabel;
+ private MetroFramework.Controls.MetroTabControl PropertiesTabControl;
+ private MetroFramework.Controls.MetroTabPage MetaTab;
+ private System.Windows.Forms.TreeView treeMeta;
+ private MetroFramework.Controls.MetroLabel label11;
+ private System.Windows.Forms.TreeView treeViewMain;
+ private PckStudio.ToolboxItems.InterpolationPictureBox previewPictureBox;
+ private System.Windows.Forms.ContextMenuStrip contextMenuMetaTree;
+ private System.Windows.Forms.ToolStripMenuItem addEntryToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addBOXEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addANIMEntryToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem addMultipleEntriesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem deleteEntryToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem editAllEntriesToolStripMenuItem;
+ private System.Windows.Forms.ContextMenuStrip contextMenuPCKEntries;
+ private System.Windows.Forms.ToolStripMenuItem createToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem folderToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem createAnimatedTextureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem audiopckToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem colourscolToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem CreateSkinsPCKToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem behavioursbinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem entityMaterialsbinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importSkinsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importSkinToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importExtractedSkinsFolderToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addTextureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem addFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem as3DSTextureFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem setFileTypeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem capeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem textureToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem languagesFileLOCToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem gameRulesFileGRFToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem audioPCKFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem coloursCOLFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem gameRulesHeaderGRHToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem skinsPCKToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem modelsFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem behavioursFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem entityMaterialsFileBINToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem miscFunctionsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem generateMipMapTextureToolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem viewFileInfoToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem correctSkinDecimalsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem extractToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem cloneFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem renameFileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem replaceToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem deleteFileToolStripMenuItem;
+ private System.Windows.Forms.ImageList imageList;
+ private System.Windows.Forms.ToolStripMenuItem addMultipleEntriesToolStripMenuItem1;
+ private MetroFramework.Controls.MetroLabel metroLabel2;
+ private MetroFramework.Controls.MetroTextBox entryTypeTextBox;
+ private MetroFramework.Controls.MetroTextBox entryDataTextBox;
+ private MetroFramework.Controls.MetroButton buttonEdit;
+ private MetroFramework.Controls.MetroLabel metroLabel1;
+ private MetroFramework.Controls.MetroCheckBox LittleEndianCheckBox;
+ private System.Windows.Forms.ToolStripMenuItem setSubPCKEndiannessToolStripMenuItem;
+ private ToolStripMenuItem bigEndianXbox360PS3WiiUToolStripMenuItem;
+ private ToolStripMenuItem littleEndianPS4PSVitaSwitchToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem setModelContainerFormatToolStripMenuItem;
+ private ToolStripMenuItem version1ToolStripMenuItem;
+ private ToolStripMenuItem version2ToolStripMenuItem;
+ private ToolStripMenuItem version3114ToolStripMenuItem;
+ private ToolStripSeparator toolStripSeparator5;
+ private ToolStripSeparator toolStripSeparator6;
+ }
+}
diff --git a/PCK-Studio/Controls/PckEditor.cs b/PCK-Studio/Controls/PckEditor.cs
new file mode 100644
index 00000000..dc461bac
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.cs
@@ -0,0 +1,2251 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Windows.Forms;
+using System.Drawing.Drawing2D;
+
+using MetroFramework.Forms;
+
+using OMI.Formats.Languages;
+using OMI.Formats.Pck;
+using OMI.Workers.Language;
+using OMI.Workers.Pck;
+
+using OMI.Workers;
+using OMI.Formats.Model;
+using OMI.Workers.Model;
+using OMI.Formats.GameRule;
+using OMI.Workers.GameRule;
+using OMI.Formats.Material;
+using OMI.Workers.Material;
+using OMI.Formats.Behaviour;
+using OMI.Workers.Behaviour;
+using OMI.Formats.Color;
+using OMI.Workers.Color;
+
+using PckStudio.Core.Extensions;
+using PckStudio.Forms.Editor;
+using PckStudio.Forms.Additional_Popups;
+using PckStudio.Forms.Additional_Popups.Animation;
+using PckStudio.Interfaces;
+using PckStudio.Internal;
+using PckStudio.Popups;
+using PckStudio.Properties;
+
+using PckStudio.Core.Deserializer;
+using PckStudio.Core.Serializer;
+using PckStudio.Core.Json;
+using PckStudio.Core.FileFormats;
+using PckStudio.Core.Skin;
+using PckStudio.Rendering;
+using PckStudio.Core;
+using PckStudio.ModelSupport;
+using PckStudio.Json;
+using PckStudio.Core.IO.PckAudio;
+using PckStudio.Core.IO._3DST;
+using PckStudio.Core.Misc;
+
+namespace PckStudio.Controls
+{
+ internal partial class PckEditor : EditorControl
+ {
+
+ private string _location = string.Empty;
+
+ private readonly OMI.ByteOrder _originalEndianness;
+ private OMI.ByteOrder _currentEndianness;
+ private bool __modified = false;
+ private bool _wasModified
+ {
+ get => __modified;
+ set
+ {
+ if (__modified != value)
+ {
+ __modified = value;
+ _onModifiedChangeDelegate?.Invoke(value);
+ }
+ }
+ }
+
+ private delegate void OnModifiedChangeDelegate(bool state);
+ private OnModifiedChangeDelegate _onModifiedChangeDelegate;
+
+ private int _timesSaved = 0;
+
+ private readonly Dictionary> _pckAssetTypeHandler;
+
+ public PckEditor(PackInfo packInfo, ISaveContext saveContext)
+ : base(packInfo, saveContext)
+ {
+ InitializeComponent();
+ _onModifiedChangeDelegate = OnModify;
+ _originalEndianness = packInfo.Endianness;
+ _currentEndianness = packInfo.Endianness;
+
+ LittleEndianCheckBox.Visible = packInfo.AllowEndianSwap;
+
+ treeViewMain.TreeViewNodeSorter = new PckNodeSorter();
+
+ skinToolStripMenuItem1.Click += (sender, e) => SetFileType(PckAssetType.SkinFile);
+ capeToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.CapeFile);
+ textureToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.TextureFile);
+ languagesFileLOCToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.LocalisationFile);
+ gameRulesFileGRFToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.GameRulesFile);
+ audioPCKFileToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.AudioFile);
+ coloursCOLFileToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.ColourTableFile);
+ gameRulesHeaderGRHToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.GameRulesHeader);
+ skinsPCKToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.SkinDataFile);
+ modelsFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.ModelsFile);
+ behavioursFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.BehavioursFile);
+ entityMaterialsFileBINToolStripMenuItem.Click += (sender, e) => SetFileType(PckAssetType.MaterialFile);
+
+ imageList.Images.Add(Resources.ZZFolder); // Icon for folders
+ imageList.Images.Add(Resources.BINKA_ICON); // Icon for music cue file (audio.pck)
+ imageList.Images.Add(Resources.IMAGE_ICON); // Icon for images (unused for now)
+ imageList.Images.Add(Resources.LOC_ICON); // Icon for string localization files (languages.loc;localisation.loc)
+ imageList.Images.Add(Resources.PCK_ICON); // Icon for generic PCK files (*.pck)
+ imageList.Images.Add(Resources.ZUnknown); // Icon for Unknown formats
+ imageList.Images.Add(Resources.COL_ICON); // Icon for color palette files (colours.col)
+ imageList.Images.Add(Resources.SKINS_ICON); // Icon for Skin.pck archives (skins.pck)
+ imageList.Images.Add(Resources.MODELS_ICON); // Icon for Model files (models.bin)
+ imageList.Images.Add(Resources.GRF_ICON); // Icon for Game Rule files (*.grf)
+ imageList.Images.Add(Resources.GRH_ICON); // Icon for Game Rule Header files (*.grh)
+ imageList.Images.Add(Resources.INFO_ICON); // Icon for Info files (0)
+ imageList.Images.Add(Resources.SKIN_ICON); // Icon for Skin files (*.png)
+ imageList.Images.Add(Resources.CAPE_ICON); // Icon for Cape files (*.png)
+ imageList.Images.Add(Resources.TEXTURE_ICON); // Icon for Texture files (*.png;*.tga)
+ imageList.Images.Add(Resources.BEHAVIOURS_ICON); // Icon for Behaviour files (behaviours.bin)
+ imageList.Images.Add(Resources.ENTITY_MATERIALS_ICON); // Icon for Entity Material files (entityMaterials.bin)
+
+ _pckAssetTypeHandler = new Dictionary>(15)
+ {
+ [PckAssetType.SkinFile] = HandleSkinFile,
+ [PckAssetType.CapeFile] = null,
+ [PckAssetType.TextureFile] = HandleTextureFile,
+ [PckAssetType.UIDataFile] = _ => throw new NotSupportedException("unused in-game"),
+ [PckAssetType.InfoFile] = null,
+ [PckAssetType.TexturePackInfoFile] = HandleInnerPckFile,
+ [PckAssetType.LocalisationFile] = HandleLocalisationFile,
+ [PckAssetType.GameRulesFile] = HandleGameRuleFile,
+ [PckAssetType.AudioFile] = HandleAudioFile,
+ [PckAssetType.ColourTableFile] = HandleColourFile,
+ [PckAssetType.GameRulesHeader] = HandleGameRuleFile,
+ [PckAssetType.SkinDataFile] = HandleInnerPckFile,
+ [PckAssetType.ModelsFile] = HandleModelsFile,
+ [PckAssetType.BehavioursFile] = HandleBehavioursFile,
+ [PckAssetType.MaterialFile] = HandleMaterialFile,
+ };
+ }
+
+ public new void Save()
+ {
+ base.Save();
+ _timesSaved++;
+ _wasModified = false;
+ }
+
+ public override void SaveAs()
+ {
+ using SaveFileDialog saveFileDialog = new SaveFileDialog
+ {
+ Filter = "PCK (Minecraft Console Package)|*.pck",
+ DefaultExt = ".pck",
+ };
+ if (saveFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ SaveTo(saveFileDialog.FileName);
+ pckFileLabel.Text = "Current PCK File: " + Path.GetFileName(_location);
+ }
+ }
+
+ public override void Close()
+ {
+ if (_wasModified && MessageBox.Show("Save PCK?", "Modified PCK", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
+ Save();
+ }
+
+ private void OnModify(bool state)
+ {
+ pckFileLabel.Text = state && !pckFileLabel.Text.StartsWith("*") ? "*" + pckFileLabel.Text : pckFileLabel.Text.Substring(1);
+ }
+
+ public override void UpdateView()
+ {
+ BuildMainTreeView();
+ }
+
+ private void SaveTo(string filepath)
+ {
+ _location = filepath;
+ Save();
+ }
+
+ private void HandleInnerPckFile(PckAsset asset)
+ {
+ if (asset.Type != PckAssetType.SkinDataFile && asset.Type != PckAssetType.TexturePackInfoFile || asset.Size <= 0 || !Settings.Default.LoadSubPcks)
+ return;
+
+ ISaveContext saveContext = new DelegatedSaveContext(false, (packInfo) =>
+ {
+ if (packInfo.IsValid)
+ {
+ asset.SetData(new PckFileWriter(packInfo.File, _currentEndianness));
+ _wasModified = true;
+ }
+ });
+
+ string caption = Path.GetFileName(asset.Filename);
+ string identifier = _location + Path.GetFileName(asset.Filename);
+ PckFile pckFile = asset.GetData(new PckFileReader(_originalEndianness));
+ PackInfo packInfo = PackInfo.Create(pckFile, _originalEndianness, false);
+
+ // TODO: may change to use a new tab page that will be closed when the main pck is closed
+ //Program.MainInstance.OpenNewPckTab(caption, identifier, packInfo, saveContext);
+ }
+
+ private void HandleTextureFile(PckAsset asset)
+ {
+ _ = asset.IsMipmappedFile() && EditorValue.File.TryGetAsset(asset.GetNormalPath(), PckAssetType.TextureFile, out asset);
+
+ if (asset.Size <= 0)
+ {
+ Trace.TraceInformation($"[{nameof(PckEditor)}:{nameof(HandleTextureFile)}] '{asset.Filename}' size is 0.");
+ return;
+ }
+
+ ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename);
+ Debug.WriteLine("Handling Resource file: " + resourceLocation?.ToString());
+
+ switch (resourceLocation.Category)
+ {
+ case ResourceCategory.Unknown:
+ Debug.WriteLine($"Unknown Resource Category.");
+ break;
+ case ResourceCategory.MobEntityTextures:
+ case ResourceCategory.ItemEntityTextures:
+ {
+ string texturePath = asset.Filename.Substring(0, asset.Filename.Length - Path.GetExtension(asset.Filename).Length);
+ string[] modelNames = GameModelImporter.ModelMetaData.Where(kv => kv.Value.TextureLocations.Contains(texturePath)).Select(kv => kv.Key).ToArray();
+
+ if (modelNames.Length == 0)
+ {
+ MessageBox.Show("No Model info found");
+ return;
+ }
+
+ string modelName = modelNames[0];
+ if (modelNames.Length > 1)
+ {
+ using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(modelNames.ToArray());
+ itemSelectionPopUp.ButtonText = "View";
+ itemSelectionPopUp.LabelText = "Models:";
+ if (itemSelectionPopUp.ShowDialog() != DialogResult.OK || !modelNames.IndexInRange(itemSelectionPopUp.SelectedIndex))
+ {
+ return;
+ }
+ modelName = modelNames[itemSelectionPopUp.SelectedIndex];
+ }
+
+ Image texture = asset.GetTexture();
+ string textureName = Path.GetFileName(texturePath);
+
+ NamedData modelTexture = new NamedData(textureName, texture);
+
+ bool hasCustomModel = false;
+ bool hasDefaultModel = TryGetDefaultEntityModel(modelName, out Model model);
+ if (EditorValue.File.TryGetAsset("models.bin", PckAssetType.ModelsFile, out PckAsset modelsAsset))
+ {
+ ModelContainer models = modelsAsset.GetData(new ModelFileReader());
+ hasCustomModel = models.ContainsModel(modelName);
+ if (hasCustomModel)
+ {
+ Debug.WriteLine($"Custom model for '{modelName}' found.");
+ model = models.GetModelByName(modelName);
+ }
+ }
+ if (!hasDefaultModel && !hasCustomModel)
+ {
+ MessageBox.Show(this, $"Not Model found for: {modelName}");
+ return;
+ }
+
+ ShowSimpleModelRender(model, modelTexture);
+ }
+ break;
+
+ case ResourceCategory.ItemAnimation:
+ case ResourceCategory.BlockAnimation:
+ Animation animation = asset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer);
+ string internalName = Path.GetFileNameWithoutExtension(asset.Filename);
+ IList textureInfos = resourceLocation.Category == ResourceCategory.ItemAnimation ? Tiles.ItemTileInfos : Tiles.BlockTileInfos;
+ string displayname = textureInfos.FirstOrDefault(p => p.InternalName == internalName)?.DisplayName ?? internalName;
+
+ string[] specialTileNames = { "clock", "compass" };
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ asset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer);
+ });
+
+ using (AnimationEditor animationEditor = new AnimationEditor(animation, saveContext, displayname, !internalName.ToLower().EqualsAny(specialTileNames)))
+ {
+ if (animationEditor.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+ break;
+ case ResourceCategory.ParticleAtlas:
+ case ResourceCategory.MoonPhaseAtlas:
+ case ResourceCategory.ItemAtlas:
+ case ResourceCategory.BlockAtlas:
+ case ResourceCategory.BannerAtlas:
+ case ResourceCategory.PaintingAtlas:
+ case ResourceCategory.ExplosionAtlas:
+ case ResourceCategory.ExperienceOrbAtlas:
+ case ResourceCategory.MapIconAtlas:
+ case ResourceCategory.AdditionalMapIconsAtlas:
+ Atlas atlas = asset.GetDeserializedData(new AtlasDeserializer(resourceLocation));
+ ColorContainer colorContainer = default;
+ if (EditorValue.File.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out PckAsset colAsset))
+ colorContainer = colAsset.GetData(new COLFileReader());
+
+ ITryGet tryGetAnimation = TryGet.FromDelegate((string key, out Animation animation) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset);
+ if (found)
+ {
+ animation = foundAsset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer);
+ return true;
+ }
+ animation = default;
+ return false;
+ });
+
+ ITryGet> tryGetAnimationSaveContext = TryGet>
+ .FromDelegate((string key, out ISaveContext animationSaveContext) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset);
+
+ if (found)
+ {
+ animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ foundAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer));
+ return true;
+ }
+
+ // you could validate the key(animationAssetPath) for validity. -miku
+ animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ if (animation.FrameCount == 0)
+ {
+ Debug.WriteLine("New animation has 0 frames. Aborting saving.");
+ return;
+ }
+ PckAsset newAnimationAsset = EditorValue.File.CreateNewAsset(key + ".png", PckAssetType.TextureFile);
+ newAnimationAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer);
+ BuildMainTreeView();
+ });
+ return true;
+ });
+
+ ISaveContext textureAtlasSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, atlas => asset.SetTexture(atlas));
+
+ var viewer = new TextureAtlasEditor(atlas, textureAtlasSaveContext, resourceLocation, colorContainer, tryGetAnimation, tryGetAnimationSaveContext);
+ if (viewer.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ break;
+ default:
+ Debug.WriteLine($"Unhandled Resource Category: {resourceLocation.Category}");
+ break;
+ }
+ }
+
+ private void HandleGameRuleFile(PckAsset asset)
+ {
+ const string cDEFLATE = "PS3";
+ const string cXMEM = "Xbox 360";
+ const string cZLIB = "Other Platforms";
+
+ ItemSelectionPopUp dialog = new ItemSelectionPopUp(cZLIB, cDEFLATE, cXMEM);
+ dialog.LabelText = "Type";
+ dialog.ButtonText = "Ok";
+ if (dialog.ShowDialog() != DialogResult.OK)
+ return;
+
+ GameRuleFile.CompressionType compressiontype = dialog.SelectedItem switch
+ {
+ cDEFLATE => GameRuleFile.CompressionType.Deflate,
+ cXMEM => GameRuleFile.CompressionType.XMem,
+ cZLIB => GameRuleFile.CompressionType.Zlib,
+ _ => GameRuleFile.CompressionType.Unknown
+ };
+
+ GameRuleFile grf = asset.GetData(new GameRuleFileReader(compressiontype));
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (gameRuleFile) =>
+ {
+ asset.SetData(new GameRuleFileWriter(gameRuleFile));
+ });
+
+ using GameRuleFileEditor grfEditor = new GameRuleFileEditor(grf, saveContext);
+ if (grfEditor.ShowDialog(this) == DialogResult.OK)
+ {
+ _wasModified = true;
+ UpdateRichPresence();
+ }
+ }
+
+ private void HandleAudioFile(PckAsset asset)
+ {
+ try
+ {
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) =>
+ {
+ asset.SetData(new PckAudioFileWriter(audioFile, _currentEndianness));
+ });
+ PckAudioFile audioFile = asset.GetData(new PckAudioFileReader(_originalEndianness));
+ using AudioEditor audioEditor = new AudioEditor(audioFile, saveContext);
+ _wasModified = audioEditor.ShowDialog(this) == DialogResult.OK;
+ }
+ catch (OverflowException)
+ {
+ MessageBox.Show(this, $"Failed to open {asset.Filename}\n" +
+ "Try converting the file by using the \"Misc. Functions/Set PCK Endianness\" tool and try again.",
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"Failed to open {asset.Filename}\n" + ex.Message,
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private void HandleLocalisationFile(PckAsset asset)
+ {
+ LOCFile locFile = asset.GetData(new LOCFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (locFile) =>
+ {
+ asset.SetData(new LOCFileWriter(locFile, 2));
+ });
+ using LOCEditor locedit = new LOCEditor(locFile, saveContext);
+ _wasModified = locedit.ShowDialog(this) == DialogResult.OK;
+ UpdateRichPresence();
+ }
+
+ private void HandleColourFile(PckAsset asset)
+ {
+ ColorContainer colorContainer = asset.GetData(new COLFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (colorContainer) =>
+ {
+ asset.SetData(new COLFileWriter(colorContainer));
+ });
+ using COLEditor diag = new COLEditor(colorContainer, saveContext);
+ _wasModified = diag.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void HandleSkinFile(PckAsset asset)
+ {
+ Skin skin = asset.GetSkin();
+ if (asset.HasProperty("CAPEPATH"))
+ {
+ string capeAssetPath = asset.GetProperty("CAPEPATH");
+ if (EditorValue.File.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset))
+ {
+ skin.CapeTexture = capeAsset.GetTexture();
+ }
+ }
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (customSkin) =>
+ {
+ if (!TryGetLocFile(out LOCFile locFile))
+ Debug.WriteLine("Failed to aquire loc file.");
+ asset.SetSkin(customSkin, locFile);
+ });
+
+ using CustomSkinEditor skinEditor = new CustomSkinEditor(skin, saveContext, EditorValue.File.HasVerionString);
+ if (skinEditor.ShowDialog() == DialogResult.OK)
+ {
+ entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty;
+ _wasModified = true;
+ ReloadMetaTreeView();
+ }
+ }
+
+ private void HandleModelsFile(PckAsset asset)
+ {
+ ModelContainer modelContainer = asset.GetData(new ModelFileReader());
+ if (modelContainer.ModelCount == 0)
+ {
+ MessageBox.Show("No models found.", "Empty Model file", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return;
+ }
+
+ TryGetDelegate tryGetTexture = (string path, out Image img) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset asset) ||
+ EditorValue.File.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out asset);
+ img = found ? asset.GetTexture() : default;
+ return found;
+ };
+
+ TrySetDelegate trySetTexture = (string path, Image img) =>
+ {
+ bool found = EditorValue.File.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) ||
+ EditorValue.File.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out foundAsset);
+ PckAsset asset = foundAsset ?? EditorValue.File.CreateNewAsset(path + ".png", PckAssetType.TextureFile);
+ asset.SetTexture(img);
+ return true;
+ };
+
+ bool hasMaterialAsset = EditorValue.File.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out PckAsset entityMaterialAsset);
+ IReadOnlyDictionary entityMaterials =
+ hasMaterialAsset
+ ? entityMaterialAsset?.GetData(new MaterialFileReader()).ToDictionary(mat => mat.Name)
+ : new Dictionary();
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (modelContainer) =>
+ {
+ asset.SetData(new ModelFileWriter(modelContainer, modelContainer.Version));
+ });
+
+ var editor = new ModelEditor(modelContainer, saveContext, TryGetSet.FromDelegates(tryGetTexture, trySetTexture), TryGet.FromDelegate(entityMaterials.TryGetValue));
+ if (editor.ShowDialog() == DialogResult.OK)
+ {
+ BuildMainTreeView();
+ _wasModified = true;
+ return;
+ }
+ }
+
+ private void HandleBehavioursFile(PckAsset asset)
+ {
+ BehaviourFile behaviourFile = asset.GetData(new BehavioursReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (behaviourFile) =>
+ {
+ asset.SetData(new BehavioursWriter(behaviourFile));
+ });
+ using BehaviourEditor edit = new BehaviourEditor(behaviourFile, saveContext);
+ _wasModified = edit.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void HandleMaterialFile(PckAsset asset)
+ {
+ MaterialContainer materials = asset.GetData(new MaterialFileReader());
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (materials) =>
+ {
+ asset.SetData(new MaterialFileWriter(materials));
+ });
+ using MaterialsEditor edit = new MaterialsEditor(materials, saveContext);
+ _wasModified = edit.ShowDialog(this) == DialogResult.OK;
+ }
+
+ private void CheckForPasswordAndRemove()
+ {
+ if (EditorValue.File.TryGetAsset("0", PckAssetType.InfoFile, out PckAsset asset))
+ {
+ asset.RemoveProperties("LOCK");
+ }
+ }
+
+ ///
+ /// wrapper that allows the use of in TreeNode.Nodes.Find(, ...) and TreeNode.Nodes.ContainsKey()
+ ///
+ ///
+ ///
+ /// new Created TreeNode
+ private static TreeNode CreateNode(string name, object tag = null)
+ {
+ TreeNode node = new TreeNode(name);
+ node.Name = name;
+ node.Tag = tag;
+ return node;
+ }
+
+ private TreeNode BuildNodeTreeBySeperator(TreeNodeCollection root, string path, char seperator)
+ {
+ _ = root ?? throw new ArgumentNullException(nameof(root));
+ if (!path.Contains(seperator))
+ {
+ TreeNode finalNode = CreateNode(path);
+ root.Add(finalNode);
+ return finalNode;
+ }
+ string nodeText = path.Substring(0, path.IndexOf(seperator));
+ string subPath = path.Substring(path.IndexOf(seperator) + 1);
+
+ if (string.IsNullOrWhiteSpace(nodeText))
+ {
+ return BuildNodeTreeBySeperator(root, subPath, seperator);
+ }
+
+ bool alreadyExists = root.ContainsKey(nodeText);
+ TreeNode subNode = alreadyExists ? root[nodeText] : CreateNode(nodeText);
+ if (!alreadyExists)
+ root.Add(subNode);
+ return BuildNodeTreeBySeperator(subNode.Nodes, subPath, seperator);
+ }
+
+ private void BuildPckTreeView(TreeNodeCollection root, PckFile pckFile)
+ {
+ foreach (PckAsset asset in pckFile.GetAssets())
+ {
+ TreeNode node = BuildNodeTreeBySeperator(root, asset.Filename, '/');
+ node.Tag = asset;
+ int nodeIconId = GetNodeIconId(asset.Type);
+ node.ImageIndex = nodeIconId;
+ node.SelectedImageIndex = nodeIconId;
+ }
+ }
+
+ private void BuildMainTreeView()
+ {
+ // In case the Rename function was just used and the selected node name no longer matches the file name
+ string selectedNodeText = treeViewMain.SelectedNode is TreeNode node ? node.FullPath : string.Empty;
+ previewPictureBox.Image = Resources.NoImageFound;
+ treeMeta.Nodes.Clear();
+ treeViewMain.Nodes.Clear();
+ BuildPckTreeView(treeViewMain.Nodes, EditorValue.File);
+ treeViewMain.Sort();
+
+ TreeNode[] selectedNodes = treeViewMain.FindPath(selectedNodeText);
+ if (selectedNodes.Length > 0)
+ {
+ treeViewMain.SelectedNode = selectedNodes[0];
+ }
+ }
+
+ private int GetNodeIconId(PckAssetType type)
+ {
+ return type switch
+ {
+ PckAssetType.AudioFile => 1,
+ PckAssetType.LocalisationFile => 3,
+ PckAssetType.TexturePackInfoFile => 4,
+ PckAssetType.ColourTableFile => 6,
+ PckAssetType.ModelsFile => 8,
+ PckAssetType.SkinDataFile => 7,
+ PckAssetType.GameRulesFile => 9,
+ PckAssetType.GameRulesHeader => 10,
+ PckAssetType.InfoFile => 11,
+ PckAssetType.SkinFile => 12,
+ PckAssetType.CapeFile => 13,
+ PckAssetType.TextureFile => 14,
+ PckAssetType.BehavioursFile => 15,
+ PckAssetType.MaterialFile => 16,
+ // unknown file format
+ _ => 5,
+ };
+ }
+
+ private List GetAllChildNodes(TreeNodeCollection root)
+ {
+ List childNodes = new List();
+ foreach (TreeNode node in root)
+ {
+ childNodes.Add(node);
+ if (node.Nodes.Count > 0)
+ {
+ childNodes.AddRange(GetAllChildNodes(node.Nodes));
+ }
+ }
+ return childNodes;
+ }
+
+ private bool TryGetLocFile(out LOCFile locFile)
+ {
+ if (!EditorValue.File.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) &&
+ !EditorValue.File.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset))
+ {
+ locFile = null;
+ return false;
+ }
+
+ try
+ {
+ locFile = locAsset.GetData(new LOCFileReader());
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ }
+ locFile = null;
+ return false;
+ }
+
+ private bool TrySetLocFile(in LOCFile locFile)
+ {
+ if (!EditorValue.File.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) &&
+ !EditorValue.File.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset))
+ {
+ return false;
+ }
+
+ try
+ {
+ locAsset.SetData(new LOCFileWriter(locFile, 2));
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ }
+ return false;
+ }
+
+ private void ReloadMetaTreeView()
+ {
+ treeMeta.Nodes.Clear();
+ if (treeViewMain.SelectedNode is TreeNode node &&
+ node.Tag is PckAsset asset)
+ {
+ foreach (KeyValuePair property in asset.GetProperties())
+ {
+ treeMeta.Nodes.Add(CreateNode(property.Key, property));
+ }
+ }
+ }
+
+ private void UpdateRichPresence()
+ {
+ if (EditorValue is not null &&
+ TryGetLocFile(out LOCFile locfile) &&
+ locfile.HasLocEntry("IDS_DISPLAY_NAME") &&
+ locfile.Languages.Contains("en-EN"))
+ {
+ RPC.SetPresence("Editing a Pack:", $" > {locfile.GetLocEntry("IDS_DISPLAY_NAME", "en-EN")}");
+ return;
+ }
+ // default
+ RPC.SetPresence("An Open Source .PCK File Editor");
+ }
+
+ private static PckAsset CreateNewAudioAsset(bool isLittle, PckAudioFile audioFile)
+ {
+ PckAsset newAsset = new PckAsset("audio.pck", PckAssetType.AudioFile);
+ newAsset.SetData(new PckAudioFileWriter(audioFile, isLittle ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+ return newAsset;
+ }
+
+ private static PckAudioFile CreateNewAudioFile()
+ {
+ PckAudioFile audioFile = new PckAudioFile();
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Overworld);
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Nether);
+ audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.End);
+ return audioFile;
+ }
+
+ private void addFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using var ofd = new OpenFileDialog();
+ // Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly?
+ // So now it's formatted correctly and now displays the file type name in the dialog.
+ ofd.Filter = "All files (*.*)|*.*";
+ ofd.Multiselect = false;
+
+ if (ofd.ShowDialog(this) == DialogResult.OK)
+ {
+ using AddFilePrompt diag = new AddFilePrompt("res/" + Path.GetFileName(ofd.FileName));
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (EditorValue.File.Contains(diag.Filepath, diag.Filetype))
+ {
+ MessageBox.Show(this, $"'{diag.Filepath}' of type {diag.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+ PckAsset asset = EditorValue.File.CreateNewAsset(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName));
+
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ return;
+ }
+
+ private void addTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using OpenFileDialog fileDialog = new OpenFileDialog();
+ fileDialog.Filter = "Texture File(*.png,*.tga)|*.png;*.tga";
+ if (fileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ using TextPrompt renamePrompt = new TextPrompt(Path.GetFileName(fileDialog.FileName));
+ renamePrompt.LabelText = "Path";
+ if (renamePrompt.ShowDialog(this) == DialogResult.OK && !string.IsNullOrEmpty(renamePrompt.NewText))
+ {
+ if (EditorValue.File.Contains(renamePrompt.NewText, PckAssetType.TextureFile))
+ {
+ MessageBox.Show(this, $"'{renamePrompt.NewText}' already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+ PckAsset asset = EditorValue.File.CreateNewAsset(renamePrompt.NewText, PckAssetType.TextureFile, () => File.ReadAllBytes(fileDialog.FileName));
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ [Obsolete("Refactor or remove this")]
+ private void importSkinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using (OpenFileDialog contents = new OpenFileDialog())
+ {
+ contents.Title = "Select Extracted Skin File";
+ contents.Filter = "Skin File (*.png)|*.png";
+
+ if (contents.ShowDialog() == DialogResult.OK)
+ {
+ string skinNameImport = Path.GetFileName(contents.FileName);
+ byte[] data = File.ReadAllBytes(contents.FileName);
+ PckAsset mfNew = EditorValue.File.CreateNewAsset(skinNameImport, PckAssetType.SkinFile);
+ mfNew.SetData(data);
+ string propertyFile = Path.GetFileNameWithoutExtension(contents.FileName) + ".txt";
+ if (File.Exists(propertyFile))
+ {
+ string[] txtProperties = File.ReadAllLines(propertyFile);
+ if ((txtProperties.Contains("DISPLAYNAMEID") && txtProperties.Contains("DISPLAYNAME")) ||
+ txtProperties.Contains("THEMENAMEID") && txtProperties.Contains("THEMENAME") &&
+ TryGetLocFile(out LOCFile locFile))
+ {
+ // do stuff
+ //l.AddLocKey(locThemeId, locTheme);
+ //using (var stream = new MemoryStream())
+ //{
+ // LOCFileWriter.Write(stream, locFile);
+ // locdata.SetData(stream.ToArray());
+ //}
+ }
+
+ try
+ {
+ foreach (string prop in txtProperties)
+ {
+ string[] arg = prop.Split(':');
+ if (arg.Length < 2)
+ continue;
+ string key = arg[0];
+ string value = arg[1];
+ if (key == "DISPLNAMEID" || key == "THEMENAMEID")
+ {
+
+ }
+ mfNew.AddProperty(key, value);
+ }
+ _wasModified = true;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+ }
+ }
+ }
+
+ private void folderToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TextPrompt folderNamePrompt = new TextPrompt();
+ if (treeViewMain.SelectedNode is not null)
+ folderNamePrompt.contextLabel.Text =
+ $"New folder at the location of \"{(
+ !treeViewMain.SelectedNode.IsTagOfType()
+ ? "/" + treeViewMain.SelectedNode.FullPath
+ : treeViewMain.SelectedNode.Parent == null ? "/" : "/" + treeViewMain.SelectedNode.Parent.FullPath)}\"";
+ folderNamePrompt.OKButtonText = "Add";
+ if (folderNamePrompt.ShowDialog(this) == DialogResult.OK)
+ {
+ TreeNode folerNode = CreateNode(folderNamePrompt.NewText);
+ folerNode.ImageIndex = 0;
+ folerNode.SelectedImageIndex = 0;
+
+ TreeNodeCollection nodeCollection = treeViewMain.Nodes;
+ if (treeViewMain.SelectedNode is TreeNode node)
+ {
+ if (node.Tag is PckAsset asset &&
+ asset.Type != PckAssetType.TexturePackInfoFile &&
+ asset.Type != PckAssetType.SkinDataFile)
+ {
+ if (node.Parent is TreeNode parentNode)
+ {
+ nodeCollection = parentNode.Nodes;
+ }
+ }
+ else
+ nodeCollection = node.Nodes;
+ }
+ nodeCollection.Add(folerNode);
+ }
+ }
+
+ private void SetFileType(PckAssetType type)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ Debug.WriteLine($"Setting {asset.Type} to {type}");
+ asset.Type = type;
+ int nodeIconId = GetNodeIconId(type);
+ treeViewMain.SelectedNode.ImageIndex = nodeIconId;
+ treeViewMain.SelectedNode.SelectedImageIndex = nodeIconId;
+ }
+ }
+
+ private void treeViewMain_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ ReloadMetaTreeView();
+
+ entryTypeTextBox.Text = entryDataTextBox.Text = labelImageSize.Text = string.Empty;
+ buttonEdit.Visible = false;
+
+ previewPictureBox.Image = Resources.NoImageFound;
+ viewFileInfoToolStripMenuItem.Visible = false;
+
+ if (!e.Node.TryGetTagData(out PckAsset asset))
+ {
+ return;
+ }
+
+ viewFileInfoToolStripMenuItem.Visible = true;
+ if (asset.HasProperty("BOX"))
+ {
+ buttonEdit.Text = "EDIT BOXES";
+ buttonEdit.Visible = true;
+ }
+ else if (asset.HasProperty("ANIM") &&
+ asset.GetProperty("ANIM", s => SkinANIM.FromString(s) == (SkinAnimMask.RESOLUTION_64x64 | SkinAnimMask.SLIM_MODEL)))
+ {
+ buttonEdit.Text = "View Skin";
+ buttonEdit.Visible = true;
+ }
+
+ switch (asset.Type)
+ {
+ case PckAssetType.SkinFile:
+ case PckAssetType.CapeFile:
+ case PckAssetType.TextureFile:
+ {
+ Image img = asset.GetTexture();
+
+ previewPictureBox.Image = img;
+ labelImageSize.Text = $"{previewPictureBox.Image.Size.Width}x{previewPictureBox.Image.Size.Height}";
+
+ if (asset.Type != PckAssetType.TextureFile)
+ break;
+
+ ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename);
+ if (resourceLocation is null || resourceLocation.Category == ResourceCategory.Unknown)
+ break;
+
+ if (resourceLocation.Category == ResourceCategory.ItemAnimation ||
+ resourceLocation.Category == ResourceCategory.BlockAnimation &&
+ !asset.IsMipmappedFile())
+ {
+ buttonEdit.Text = "EDIT TILE ANIMATION";
+ buttonEdit.Visible = true;
+ break;
+ }
+
+ buttonEdit.Text = "EDIT TEXTURE ATLAS";
+ buttonEdit.Visible = true;
+ }
+ break;
+
+ case PckAssetType.LocalisationFile:
+ buttonEdit.Text = "EDIT LOC";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.AudioFile:
+ buttonEdit.Text = "EDIT MUSIC CUES";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.ColourTableFile when asset.Filename == "colours.col":
+ buttonEdit.Text = "EDIT COLORS";
+ buttonEdit.Visible = true;
+ break;
+
+ case PckAssetType.BehavioursFile when asset.Filename == "behaviours.bin":
+ buttonEdit.Text = "EDIT BEHAVIOURS";
+ buttonEdit.Visible = true;
+ break;
+ default:
+ buttonEdit.Visible = false;
+ break;
+ }
+ }
+
+ private void treeViewMain_DoubleClick(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t && t.Tag is PckAsset asset)
+ {
+ if (asset.Size <= 0)
+ {
+ Trace.WriteLine($"'{asset.Filename}' has no data attached.", category: nameof(treeViewMain_DoubleClick));
+ return;
+ }
+ _pckAssetTypeHandler[asset.Type]?.Invoke(asset);
+ }
+ }
+
+ // Most of the code below is modified code from this link:
+ // https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.treeview.itemdrag?view=windowsdesktop-6.0
+ // - MattNL
+
+ private void treeViewMain_ItemDrag(object sender, ItemDragEventArgs e)
+ {
+ if (e.Button != MouseButtons.Left || e.Item is not TreeNode node)
+ return;
+
+ if ((node.TryGetTagData(out PckAsset asset) && EditorValue.File.Contains(asset.Filename, asset.Type)) || node.Parent is TreeNode)
+ {
+ // TODO: add (mouse) scrolling while dragging item(s)
+ treeViewMain.DoDragDrop(node, DragDropEffects.Scroll | DragDropEffects.Move);
+ }
+ }
+
+ private void treeViewMain_DragOver(object sender, DragEventArgs e)
+ {
+ Point dragLocation = new Point(e.X, e.Y);
+ TreeNode node = treeViewMain.GetNodeAt(treeViewMain.PointToClient(dragLocation));
+ treeViewMain.SelectedNode = node.IsTagOfType() ? null : node;
+ }
+
+ private void treeViewMain_DragEnter(object sender, DragEventArgs e)
+ {
+ e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : e.AllowedEffect;
+ BringToFront();
+ Focus();
+ treeViewMain.Focus();
+ }
+
+ private void treeViewMain_DragDrop(object sender, DragEventArgs e)
+ {
+ // Retrieve the client coordinates of the drop location.
+ Point dragLocation = new Point(e.X, e.Y);
+ Point targetPoint = treeViewMain.PointToClient(dragLocation);
+
+ if (!treeViewMain.ClientRectangle.Contains(targetPoint))
+ return;
+
+ // Retrieve the node at the drop location.
+ TreeNode targetNode = treeViewMain.GetNodeAt(targetPoint);
+
+ if (e.Data.GetDataPresent(DataFormats.FileDrop) && e.Data.GetData(DataFormats.FileDrop) is string[] filesDropped)
+ {
+ IEnumerable files = filesDropped.Where(File.Exists);
+ IEnumerable directoryFiles = filesDropped
+ .Where(f => (File.GetAttributes(f) & FileAttributes.Directory) != 0)
+ .SelectMany(dir => Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories));
+
+ string baseDirectory = Path.GetDirectoryName(filesDropped.First());
+
+ IEnumerable importPaths = files.Concat(directoryFiles);
+
+ ImportFiles(baseDirectory, importPaths, string.IsNullOrWhiteSpace(targetNode?.FullPath) ? string.Empty : targetNode?.FullPath);
+ return;
+ }
+
+ string dataFormat = typeof(TreeNode).FullName;
+
+ if (targetNode is null)
+ return;
+
+ if (!e.Data.GetDataPresent(dataFormat))
+ return;
+
+ bool isTargetPckFile = targetNode.IsTagOfType();
+ TreeNode draggedNode = e.Data.GetData(dataFormat) as TreeNode;
+ if (draggedNode == null)
+ {
+ Debug.WriteLine("Dragged node is null.");
+ return;
+ }
+
+ if (targetNode.Equals(draggedNode))
+ {
+ Debug.WriteLine("Dragged node was not moved.");
+ return;
+ }
+
+ if (targetNode.Equals(draggedNode.Parent))
+ {
+ Debug.WriteLine("target node is parent of dragged node... nothing done.");
+ return;
+ }
+
+ if (draggedNode.Equals(targetNode.Parent))
+ {
+ Debug.WriteLine("dragged node is parent of target node... nothing done.");
+ return;
+ }
+
+ if (targetNode.Parent == null && isTargetPckFile && draggedNode.Parent == null)
+ {
+ Debug.WriteLine("target node is file and is in the root... nothing done.");
+ return;
+ }
+
+ if ((targetNode.Parent?.Equals(draggedNode.Parent) ?? false) && isTargetPckFile)
+ {
+ Debug.WriteLine("target node and dragged node have the same parent... nothing done.");
+ return;
+ }
+
+ Debug.WriteLine($"Target drop location is {(isTargetPckFile ? "file" : "folder")}.");
+
+ // Retrieve the node that was dragged.
+ if (draggedNode.TryGetTagData(out PckAsset draggedAsset) &&
+ targetNode.FullPath != draggedAsset.Filename)
+ {
+ Debug.WriteLine(draggedAsset.Filename + " was droped onto " + targetNode.FullPath);
+ string newFilePath = Path.Combine(isTargetPckFile
+ ? Path.GetDirectoryName(targetNode.FullPath)
+ : targetNode.FullPath, Path.GetFileName(draggedAsset.Filename));
+ Debug.WriteLine("New filepath: " + newFilePath);
+ draggedAsset.Filename = newFilePath;
+ _wasModified = true;
+ BuildMainTreeView();
+ return;
+ }
+ else
+ {
+ IEnumerable pckFiles = GetAllChildNodes(draggedNode.Nodes).Where(t => t.IsTagOfType()).Select(t => t.Tag as PckAsset);
+ string oldPath = draggedNode.FullPath;
+ string newPath = Path.Combine(isTargetPckFile ? Path.GetDirectoryName(targetNode.FullPath) : targetNode.FullPath, draggedNode.Text).Replace('\\', '/');
+ foreach (PckAsset pckFile in pckFiles)
+ {
+ pckFile.Filename = Path.Combine(newPath, pckFile.Filename.Substring(oldPath.Length + 1)).Replace('\\', '/');
+ }
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void ImportFiles(string baseDirectory, IEnumerable files, string prefix)
+ {
+ int fileCount = files.Count();
+ int addedCount = 0;
+ int skippedFiles = 0;
+ int skipAttempts = 3;
+ int typeDuplication = 0;
+ PckAssetType lastSelectedAssetType = PckAssetType.SkinFile;
+ bool askForAssetType = true;
+ foreach (var filepath in files)
+ {
+ string assetPath = Path.Combine(prefix + filepath.Substring(baseDirectory.Length)).TrimStart('/', '\\');
+ PckAssetType assetType = lastSelectedAssetType;
+
+ if (askForAssetType)
+ {
+ using AddFilePrompt addFile = new AddFilePrompt(assetPath);
+ if (addFile.ShowDialog(this) != DialogResult.OK)
+ {
+ skippedFiles++;
+ skipAttempts--;
+ if (skipAttempts > 0)
+ continue;
+
+ int remainingFileCount = fileCount - addedCount - skippedFiles;
+ DialogResult abortFurtherImport = MessageBox.Show($"Do you wan't to abort further file imports?\n{remainingFileCount} file(s) left.", "Abort further import", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
+ if (abortFurtherImport == DialogResult.Yes)
+ {
+ skippedFiles += remainingFileCount;
+ break;
+ }
+ skipAttempts = 3;
+ continue;
+ }
+
+ assetType = addFile.Filetype;
+ assetPath = addFile.Filepath;
+
+ if (lastSelectedAssetType == assetType)
+ typeDuplication++;
+ lastSelectedAssetType = addFile.Filetype;
+ if (typeDuplication > 1)
+ {
+ DialogResult useSameTypeForRest = MessageBox.Show($"Do you want to import all remaining files as {lastSelectedAssetType}?", "Import all as", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
+ if (useSameTypeForRest == DialogResult.Yes)
+ {
+ askForAssetType = false;
+ }
+ }
+ }
+
+ if (EditorValue.File.Contains(filepath, assetType))
+ {
+ if (askForAssetType)
+ MessageBox.Show(this, $"'{assetPath}' of type {assetType} already exists.\nSkiping file.", "File already exists", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
+ Debug.WriteLine($"'{assetPath}' of type {assetType} already exists.\nSkiping file.");
+ continue;
+ }
+ PckAsset importedAsset = EditorValue.File.CreateNewAsset(assetPath, assetType, () => File.ReadAllBytes(filepath));
+ string propertyFile = filepath + ".txt";
+ if (File.Exists(propertyFile))
+ {
+ importedAsset.DeserializeProperties(File.ReadAllLines(propertyFile));
+ }
+ addedCount++;
+ }
+ Trace.TraceInformation("[{0}] Imported {1} file(s).", nameof(ImportFiles), addedCount);
+ Trace.TraceInformation("[{0}] Skipped {1} file(s).", nameof(ImportFiles), skippedFiles);
+ if (addedCount > 0)
+ {
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private IEnumerable GetEndingNodes(TreeNodeCollection collection)
+ {
+ List trailingNodes = new List(collection.Count);
+ foreach (TreeNode node in collection)
+ {
+ if (node.Nodes.Count > 0)
+ {
+ trailingNodes.AddRange(GetEndingNodes(node.Nodes));
+ continue;
+ }
+ trailingNodes.Add(node);
+ }
+ return trailingNodes;
+ }
+
+ private void ImportFiles(string[] files)
+ {
+ int addedCount = 0;
+ foreach (var file in files)
+ {
+ using AddFilePrompt addFile = new AddFilePrompt(Path.GetFileName(file));
+ if (addFile.ShowDialog(this) != DialogResult.OK)
+ continue;
+
+ if (EditorValue.File.Contains(addFile.Filepath, addFile.Filetype))
+ {
+ MessageBox.Show(this, $"'{addFile.Filepath}' of type {addFile.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ continue;
+ }
+ EditorValue.File.CreateNewAsset(addFile.Filepath, addFile.Filetype, () => File.ReadAllBytes(file));
+ addedCount++;
+
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ Trace.TraceInformation("[{0}] Imported {1} file(s).", nameof(ImportFiles), addedCount);
+ }
+
+ private void createSkinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using (AddSkinPrompt addNewSkinDialog = new AddSkinPrompt())
+ if (addNewSkinDialog.ShowDialog() == DialogResult.OK)
+ {
+ TryGetLocFile(out LOCFile locFile);
+ PckAsset skinAsset = addNewSkinDialog.NewSkin.CreateFile(locFile);
+ EditorValue.File.AddAsset(skinAsset);
+
+ bool hasSkinsFolder = treeViewMain.Nodes.ContainsKey("Skins");
+ if (hasSkinsFolder)
+ skinAsset.Filename = skinAsset.Filename.Insert(0, "Skins/"); // Then Skins folder
+ EditorValue.File.AddAsset(skinAsset);
+
+ if (addNewSkinDialog.NewSkin.HasCape)
+ {
+ PckAsset capeFile = addNewSkinDialog.NewSkin.CreateCapeFile();
+ if (hasSkinsFolder)
+ capeFile.Filename = capeFile.Filename.Insert(0, "Skins/"); // Then Skins folder
+ EditorValue.File.AddAsset(capeFile);
+ }
+
+ TrySetLocFile(locFile);
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void createAnimatedTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ using ChangeTile diag = new ChangeTile();
+ if (diag.ShowDialog(this) != DialogResult.OK)
+ return;
+
+ string animationFilepath = $"{ResourceLocation.GetPathFromCategory(diag.Category)}/{diag.SelectedTile.InternalName}.png";
+
+ if (EditorValue.File.Contains(animationFilepath, PckAssetType.TextureFile))
+ {
+ MessageBox.Show(this, $"{diag.SelectedTile.DisplayName} is already present.", "File already present");
+ return;
+ }
+
+ Animation newAnimation = default;
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) =>
+ {
+ newAnimation = animation;
+ });
+
+ using AnimationEditor animationEditor = new AnimationEditor(Animation.CreateEmpty(), saveContext, diag.SelectedTile.DisplayName, !diag.SelectedTile.InternalName.EqualsAny("clock", "compass"));
+ if (animationEditor.ShowDialog() == DialogResult.OK && newAnimation is not null)
+ {
+ _wasModified = true;
+ PckAsset asset = EditorValue.File.CreateNewAsset(animationFilepath, PckAssetType.TextureFile);
+ asset.SetSerializedData(newAnimation, AnimationSerializer.DefaultSerializer);
+ BuildMainTreeView();
+ ReloadMetaTreeView();
+ }
+ }
+
+ private void audiopckToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.Contains(PckAssetType.AudioFile))
+ {
+ // the chance of this happening is really really slim but just in case
+ MessageBox.Show(this, "There is already an audio file in this PCK!", "Can't create audio.pck");
+ return;
+ }
+
+ if (string.IsNullOrEmpty(_location))
+ {
+ MessageBox.Show(this, "You must save your pck before creating or opening a music cues PCK file", "Can't create audio.pck");
+ return;
+ }
+
+ PckAudioFile newAudioFile = CreateNewAudioFile();
+ PckAsset newAudioAsset = CreateNewAudioAsset(LittleEndianCheckBox.Checked, newAudioFile);
+
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) =>
+ {
+ newAudioAsset.SetData(new PckAudioFileWriter(audioFile, LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+ });
+
+ AudioEditor diag = new AudioEditor(newAudioFile, saveContext);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ EditorValue.File.AddAsset(newAudioAsset);
+ }
+ diag.Dispose();
+ BuildMainTreeView();
+ }
+
+ private void colourscolToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out _))
+ {
+ MessageBox.Show(this, "A color table file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+ PckAsset newColorAsset = EditorValue.File.CreateNewAsset("colours.col", PckAssetType.ColourTableFile);
+ newColorAsset.SetData(Resources.tu69colours);
+ BuildMainTreeView();
+ }
+
+ private void CreateSkinsPCKToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("Skins.pck", PckAssetType.SkinDataFile, out _))
+ {
+ MessageBox.Show(this, "A Skins.pck file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+
+ EditorValue.File.CreateNewAsset("Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true),
+ LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian));
+
+ BuildMainTreeView();
+ }
+
+ private void behavioursbinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("behaviours.bin", PckAssetType.BehavioursFile, out _))
+ {
+ MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+
+ EditorValue.File.CreateNewAsset("behaviours.bin", PckAssetType.BehavioursFile, new BehavioursWriter(new BehaviourFile()));
+ BuildMainTreeView();
+ }
+
+ private void entityMaterialsbinToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (EditorValue.File.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out _))
+ {
+ MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted");
+ return;
+ }
+ var materialContainer = new MaterialContainer();
+ materialContainer.InitializeDefault();
+ EditorValue.File.CreateNewAsset("entityMaterials.bin", PckAssetType.MaterialFile, new MaterialFileWriter(materialContainer));
+ BuildMainTreeView();
+ }
+
+ [Obsolete("Refactor or remove this")]
+ private void importExtractedSkinsFolder(object sender, EventArgs e)
+ {
+ OpenFolderDialog contents = new OpenFolderDialog();
+ if (contents.ShowDialog(Handle) == true)
+ {
+ //checks to make sure selected path exist
+ if (!Directory.Exists(contents.ResultPath))
+ {
+ MessageBox.Show("Directory Lost");
+ return;
+ }
+ // creates variable to indicate wether current pck skin structure is mashup or regular skin
+ bool hasSkinsPck = EditorValue.File.HasAsset("Skins.pck", PckAssetType.SkinDataFile);
+
+ foreach (var fullfilename in Directory.GetFiles(contents.ResultPath, "*.png"))
+ {
+ string filename = Path.GetFileNameWithoutExtension(fullfilename);
+ // sets file type based on wether its a cape or skin
+ PckAssetType pckfiletype = filename.StartsWith("dlccape", StringComparison.OrdinalIgnoreCase)
+ ? PckAssetType.CapeFile
+ : PckAssetType.SkinFile;
+ string pckfilepath = (hasSkinsPck ? "Skins/" : string.Empty) + filename + ".png";
+
+
+ PckAsset newFile = new PckAsset(pckfilepath, pckfiletype);
+ byte[] filedata = File.ReadAllBytes(fullfilename);
+ newFile.SetData(filedata);
+
+ if (File.Exists(fullfilename + ".txt"))
+ {
+ string[] properties = File.ReadAllText(fullfilename + ".txt").Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string property in properties)
+ {
+ string[] param = property.Split(':');
+ if (param.Length < 2)
+ continue;
+ newFile.AddProperty(param[0], param[1]);
+ //switch (param[0])
+ //{
+ // case "DISPLAYNAMEID":
+ // locNameId = param[1];
+ // continue;
+
+ // case "DISPLAYNAME":
+ // locName = param[1];
+ // continue;
+
+ // case "THEMENAMEID":
+ // locThemeId = param[1];
+ // continue;
+
+ // case "THEMENAME":
+ // locTheme = param[1];
+ // continue;
+ //}
+ }
+ }
+ if (hasSkinsPck)
+ {
+ PckAsset skinsFileAsset = EditorValue.File.GetAsset("Skins.pck", PckAssetType.SkinDataFile);
+ using (var ms = new MemoryStream(skinsFileAsset.Data))
+ {
+ //var reader = new PckFileReader(LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
+ //var skinspck = reader.FromStream(ms);
+ //skinspck.Files.Add(newFile);
+ //ms.Position = 0;
+ //var writer = new PckFileWriter(skinspck, LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
+ //writer.WriteToStream(ms);
+ //skinsfile.SetData(ms.ToArray());
+ }
+ continue;
+ }
+ EditorValue.File.AddAsset(newFile);
+ }
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+
+ private void as3DSTextureFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset) &&
+ asset.Type == PckAssetType.SkinFile)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Filter = "3DS Texture|*.3dst";
+ saveFileDialog.DefaultExt = ".3dst";
+ if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ Image img = asset.GetTexture();
+ var writer = new _3DSTextureWriter(img);
+ writer.WriteToFile(saveFileDialog.FileName);
+ }
+ }
+ }
+
+ private void generateMipMapTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && asset.Type == PckAssetType.TextureFile)
+ {
+ string textureDirectory = Path.GetDirectoryName(asset.Filename);
+ string textureName = Path.GetFileNameWithoutExtension(asset.Filename);
+
+ if (asset.IsMipmappedFile())
+ return;
+
+ string textureExtension = Path.GetExtension(asset.Filename);
+
+ using NumericPrompt numericPrompt = new NumericPrompt(0);
+ numericPrompt.Minimum = 1;
+ numericPrompt.Maximum = 4; // 5 is the presumed max MipMap level
+ numericPrompt.ToolTipText = "You can enter the amount of MipMap levels that you would like to generate. " +
+ "For example: if you enter 2, MipMapLevel1.png and MipMapLevel2.png will be generated";
+ numericPrompt.TextLabel.Text = "Levels";
+
+ if (numericPrompt.ShowDialog(this) == DialogResult.OK)
+ {
+ for (int i = 2; i < 2 + numericPrompt.SelectedValueAsInt; i++)
+ {
+ string mippedPath = $"{textureDirectory}/{textureName}MipMapLevel{i}{textureExtension}";
+ Debug.WriteLine(mippedPath);
+ if (EditorValue.File.HasAsset(mippedPath, PckAssetType.TextureFile))
+ EditorValue.File.RemoveAsset(EditorValue.File.GetAsset(mippedPath, PckAssetType.TextureFile));
+ PckAsset mipMappedAsset = new PckAsset(mippedPath, PckAssetType.TextureFile);
+
+ Image originalTexture = asset.GetTexture();
+ int newWidth = Math.Max(originalTexture.Width / (int)Math.Pow(2, i - 1), 1);
+ int newHeight = Math.Max(originalTexture.Height / (int)Math.Pow(2, i - 1), 1);
+
+ Rectangle tileArea = new Rectangle(0, 0, newWidth, newHeight);
+ Image mippedTexture = new Bitmap(newWidth, newHeight);
+ using (Graphics gfx = Graphics.FromImage(mippedTexture))
+ {
+ gfx.SmoothingMode = SmoothingMode.None;
+ gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
+ gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ gfx.DrawImage(originalTexture, tileArea);
+ }
+
+ mipMappedAsset.SetTexture(mippedTexture);
+
+ EditorValue.File.InsertAsset(EditorValue.File.IndexOfAsset(asset) + i - 1, mipMappedAsset);
+ }
+ BuildMainTreeView();
+ }
+ }
+ }
+
+ private void viewFileInfoToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset)
+ {
+ MessageBox.Show(
+ $"Asset path: {asset.Filename}" +
+ $"\nAsset type: {(int)asset.Type} ({asset.Type})" +
+ $"\nAsset size: {asset.Size}" +
+ $"\nProperties count: {asset.PropertyCount}"
+ , Path.GetFileName(asset.Filename) + " Asset info");
+ }
+ }
+
+ private void correctSkinDecimalsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset) &&
+ asset.Type == PckAssetType.SkinFile)
+ {
+ foreach (KeyValuePair p in asset.GetProperties().ToList())
+ {
+ if (p.Key == "BOX" || p.Key == "OFFSET")
+ asset.SetProperty(asset.GetPropertyIndex(p), new KeyValuePair(p.Key, p.Value.Replace(',', '.')));
+ }
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+
+ private void extractToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ if (node == null)
+ {
+ MessageBox.Show(this, "The selected node was null. Please select a node and try again.", "Node not extracted");
+
+ return;
+ }
+
+ if (node.Tag == null)
+ {
+ OpenFolderDialog dialog = new OpenFolderDialog();
+ dialog.Title = @"Select destination folder";
+
+ if (dialog.ShowDialog(Handle) == true)
+ extractFolder(dialog.ResultPath);
+ }
+ else if (node.TryGetTagData(out PckAsset asset))
+ {
+ using SaveFileDialog exFile = new SaveFileDialog();
+ exFile.FileName = Path.GetFileName(asset.Filename);
+ exFile.Filter = Path.GetExtension(asset.Filename).Replace(".", string.Empty) + " File|*" + Path.GetExtension(asset.Filename);
+ if (exFile.ShowDialog(this) != DialogResult.OK ||
+ // Makes sure chosen directory isn't null or whitespace AKA makes sure its usable
+ string.IsNullOrWhiteSpace(Path.GetDirectoryName(exFile.FileName)))
+ {
+ MessageBox.Show(this, "The chosen directory is invalid. Please choose a different one and try again.", "Node not extracted");
+
+ return;
+ }
+
+ extractFile(exFile.FileName, asset);
+ }
+
+ // Verification that file extraction path was successful
+ MessageBox.Show(this, $"\"{node.Text}\" successfully extracted");
+ }
+
+ private void extractFolder(string outPath)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ string selectedFolder = node.FullPath;
+
+ foreach (PckAsset asset in EditorValue.File.GetAssets().Where(asset => asset.Filename.StartsWith(selectedFolder)))
+ {
+ extractFolderFile(outPath, asset);
+ }
+ }
+
+ private void extractFolderFile(string outPath, PckAsset asset)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+
+ // abb = "Abbreviated Path"
+ string abbPath = Path.GetDirectoryName(asset.Filename);
+ int startIndex = abbPath.IndexOf(node.Text);
+ abbPath = abbPath.Substring(startIndex, abbPath.Length - startIndex);
+ string finalPath = ($"{outPath}/{abbPath}/").Replace('\\', '/');
+
+ if (!Directory.Exists(finalPath))
+ Directory.CreateDirectory(finalPath);
+
+ extractFile(finalPath + "/" + Path.GetFileName(asset.Filename), asset);
+ }
+
+ private void extractFile(string outFilePath, PckAsset asset)
+ {
+ File.WriteAllBytes(outFilePath, asset.Data);
+ if (asset.PropertyCount > 0)
+ {
+ File.WriteAllLines($"{outFilePath}.txt", asset.SerializeProperties());
+ }
+ }
+
+ private void cloneFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null || !node.IsTagOfType())
+ return;
+ string path = node.FullPath;
+
+ using TextPrompt diag = new TextPrompt(node.Tag is null ? Path.GetFileName(node.FullPath) : node.FullPath);
+ diag.contextLabel.Text = $"Creating a clone of \"{path}\". Ensure that the path isn't yet.";
+ diag.OKButtonText = "Clone";
+
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (node.Tag is PckAsset asset)
+ {
+ TreeNode newNode = new TreeNode();
+ newNode.Text = Path.GetFileName(diag.NewText);
+ var newFile = new PckAsset(diag.NewText, asset.Type);
+ foreach (KeyValuePair property in asset.GetProperties())
+ {
+ newFile.AddProperty(property);
+ }
+ newFile.SetData(asset.Data);
+ newFile.Filename = diag.NewText;
+ newNode.Tag = newFile;
+ newNode.ImageIndex = node.ImageIndex;
+ newNode.SelectedImageIndex = node.SelectedImageIndex;
+
+ if (GetAllChildNodes(treeViewMain.Nodes).FirstOrDefault(n => n.FullPath == diag.NewText) is not null)
+ {
+ MessageBox.Show(
+ this,
+ $"A file with the path \"{diag.NewText}\" already exists. " +
+ $"Please try again with a different name.",
+ "Key already exists");
+ return;
+ }
+
+ TreeNodeCollection nodeCollection = node.Parent?.Nodes ?? treeViewMain.Nodes;
+ nodeCollection.Insert(node.Index + 1, newNode);
+
+ EditorValue.File.InsertAsset(node.Index + 1, newFile);
+ BuildMainTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private void renameFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null)
+ return;
+ string path = node.FullPath;
+
+ bool isFile = node.TryGetTagData(out PckAsset asset);
+
+ using TextPrompt diag = new TextPrompt(isFile ? asset.Filename : Path.GetFileName(node.FullPath));
+
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ if (isFile)
+ {
+ if (EditorValue.File.Contains(diag.NewText, asset.Type))
+ {
+ MessageBox.Show(this, $"{diag.NewText} already exists", "File already exists");
+ return;
+ }
+ asset.Filename = diag.NewText;
+ }
+ else // folders
+ {
+ node.Text = diag.NewText;
+ foreach (TreeNode childNode in GetAllChildNodes(node.Nodes))
+ {
+ if (childNode.Tag is PckAsset folderAsset)
+ {
+ if (folderAsset.Filename == diag.NewText)
+ continue;
+ folderAsset.Filename = childNode.FullPath;
+ }
+ }
+ }
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ }
+
+ private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset)
+ {
+ using var ofd = new OpenFileDialog();
+ // Suddenly, and randomly, this started throwing an exception because it wasn't formatted correctly? So now it's formatted correctly and now displays the file type name in the dialog.
+
+ string extra_extensions = "";
+
+ switch (asset.Type)
+ {
+ case PckAssetType.TextureFile:
+ if (Path.GetExtension(asset.Filename) == ".png")
+ extra_extensions = ";*.tga";
+ else if (Path.GetExtension(asset.Filename) == ".tga")
+ extra_extensions = ";*.png";
+ break;
+ }
+
+ string fileExt = Path.GetExtension(asset.Filename);
+
+ ofd.Filter = $"{asset.Type} (*{fileExt}{extra_extensions})|*{fileExt}{extra_extensions}";
+ if (ofd.ShowDialog(this) == DialogResult.OK)
+ {
+ string newFileExt = Path.GetExtension(ofd.FileName);
+ asset.SetData(File.ReadAllBytes(ofd.FileName));
+ asset.Filename = asset.Filename.Replace(fileExt, newFileExt);
+ _wasModified = true;
+ BuildMainTreeView();
+ }
+ return;
+ }
+ MessageBox.Show(this, "Can't replace a folder.");
+ }
+
+ ///
+ /// Action to run before an asset will be deleted
+ ///
+ /// Asset to remove
+ /// True if the remove should be canceled, otherwise False
+ private bool BeforeFileRemove(PckAsset asset)
+ {
+ string itemPath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation);
+
+ // warn the user about deleting compass.png and clock.png
+ if (asset.Type == PckAssetType.TextureFile &&
+ (asset.Filename == itemPath + "/compass.png" || asset.Filename == itemPath + "/clock.png"))
+ {
+ if (MessageBox.Show(this, "Are you sure want to delete this file? If \"compass.png\" or \"clock.png\" are missing, your game will crash upon loading this pack.", "Warning",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
+ return true;
+ }
+
+ // remove loc key if its a skin/cape
+ if (asset.Type == PckAssetType.SkinFile || asset.Type == PckAssetType.CapeFile)
+ {
+ if (TryGetLocFile(out LOCFile locFile))
+ {
+ if (asset.TryGetProperty("THEMENAMEID", out string value))
+ locFile.RemoveLocKey(value);
+ if (asset.TryGetProperty("DISPLAYNAMEID", out value))
+ locFile.RemoveLocKey(value);
+ TrySetLocFile(locFile);
+ }
+ }
+ return false;
+ }
+
+ private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ TreeNode node = treeViewMain.SelectedNode;
+ if (node == null)
+ return;
+
+ string path = node.FullPath;
+
+ if (node.TryGetTagData(out PckAsset asset))
+ {
+ if (!BeforeFileRemove(asset) && EditorValue.File.RemoveAsset(asset))
+ {
+ node.Remove();
+ _wasModified = true;
+ }
+ }
+ else if (MessageBox.Show(this, "Are you sure want to delete this folder? All contents will be deleted", "Warning",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
+ {
+ string pckFolderDir = node.FullPath;
+ EditorValue.File.RemoveAll(file => file.Filename.StartsWith(pckFolderDir) && !BeforeFileRemove(file));
+ node.Remove();
+ _wasModified = true;
+ }
+ }
+
+ private void treeMeta_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ if (e.Node is TreeNode t && t.Tag is KeyValuePair property)
+ {
+ entryTypeTextBox.Text = property.Key;
+ entryDataTextBox.Text = property.Value;
+ }
+ }
+
+ private void treeViewMain_KeyDown(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Delete:
+ deleteFileToolStripMenuItem_Click(sender, e);
+ break;
+ case Keys.F2:
+ renameFileToolStripMenuItem_Click(sender, e);
+ break;
+ }
+ }
+
+ private void treeViewMain_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
+ {
+ // for now name edits are done through the 'rename' context menu item
+ // TODO: add folder renaming
+ //e.CancelEdit = e.Node.Tag is PckAsset;
+ e.CancelEdit = true;
+ }
+
+ private void editAllEntriesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ IEnumerable props = asset.SerializeProperties(seperater: " ");
+ using (var input = new MultiTextPrompt(props))
+ {
+ if (input.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.ClearProperties();
+ asset.DeserializeProperties(input.TextOutput);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+ }
+
+ private void treeMeta_DoubleClick(object sender, EventArgs e)
+ {
+ if (treeMeta.SelectedNode is TreeNode subnode && subnode.Tag is KeyValuePair property &&
+ treeViewMain.SelectedNode is TreeNode node && node.Tag is PckAsset asset)
+ {
+ if (asset.HasProperty(property.Key))
+ {
+ switch (property.Key)
+ {
+ case "ANIM" when asset.Type == PckAssetType.SkinFile:
+ try
+ {
+ using ANIMEditor diag = new ANIMEditor(SkinANIM.FromString(property.Value));
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair("ANIM", diag.ResultAnim.ToString()));
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Trace.WriteLine("Invalid ANIM value: " + property.Value);
+ MessageBox.Show(this, "Failed to parse ANIM value, aborting to normal functionality. Please make sure the value only includes hexadecimal characters (0-9,A-F) and has no more than 8 characters.");
+ }
+ break;
+
+ case "BOX" when asset.Type == PckAssetType.SkinFile:
+ try
+ {
+ using BoxEditor diag = new BoxEditor(property.Value, false);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair("BOX", diag.Result.ToString()));
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Trace.WriteLine("Invalid BOX value: " + property.Value);
+ MessageBox.Show(this, "Failed to parse BOX value, aborting to normal functionality.");
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ using (AddPropertyPrompt addProperty = new AddPropertyPrompt(property))
+ {
+ if (addProperty.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.SetProperty(asset.GetPropertyIndex(property), addProperty.Property);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+ }
+ }
+
+ private void treeMeta_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyData == Keys.Delete)
+ deleteEntryToolStripMenuItem_Click(sender, e);
+ }
+
+ private void addMultipleEntriesToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ using var input = new MultiTextPrompt();
+ if (input.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.DeserializeProperties(input.TextOutput);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private void addBOXEntryToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t && t.Tag is PckAsset asset)
+ {
+ using BoxEditor diag = new BoxEditor(SkinBOX.DefaultHead, false);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty("BOX", diag.Result);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ }
+
+ private void addANIMEntryToolStripMenuItem1_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
+ {
+ using ANIMEditor diag = new ANIMEditor(SkinANIM.Empty);
+ if (diag.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty("ANIM", diag.ResultAnim);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ return;
+ }
+ }
+
+ private void deleteEntryToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeMeta.SelectedNode is TreeNode t && t.Tag is KeyValuePair property &&
+ treeViewMain.SelectedNode is TreeNode main && main.Tag is PckAsset asset &&
+ asset.RemoveProperty(property))
+ {
+ treeMeta.SelectedNode.Remove();
+ _wasModified = true;
+ }
+ }
+
+ private void addEntryToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (treeViewMain.SelectedNode is TreeNode t &&
+ t.Tag is PckAsset asset)
+ {
+ using AddPropertyPrompt addProperty = new AddPropertyPrompt();
+ if (addProperty.ShowDialog(this) == DialogResult.OK)
+ {
+ asset.AddProperty(addProperty.Property);
+ ReloadMetaTreeView();
+ _wasModified = true;
+ }
+ }
+ }
+
+ private static bool TryGetDefaultEntityModel(string modelName, out Model model)
+ {
+ if (!GameModelImporter.DefaultModels.TryGetValue(modelName, out DefaultModel defaultModel) || defaultModel is null)
+ {
+ model = default;
+ return false;
+ }
+ model = new Model(modelName, new Size((int)defaultModel.TextureSize.X, (int)defaultModel.TextureSize.Y));
+
+ foreach (DefaultPart defaultPart in defaultModel.Parts)
+ {
+ ModelPart modelPart = new ModelPart(defaultPart.Name, "", defaultPart.Translation, defaultPart.Rotation, System.Numerics.Vector3.Zero);
+ modelPart.AddBoxes(defaultPart.Boxes.Select(defaultBox => new ModelBox(defaultBox.Position, defaultBox.Size, defaultBox.Uv, defaultBox.Inflate, defaultBox.Mirror)));
+ model.AddPart(modelPart);
+ }
+
+ return true;
+ }
+
+ private void ShowSimpleModelRender(Model model, NamedData modelTexture)
+ {
+ MetroForm form = new MetroForm();
+ form.Icon = Resources.ProjectLogo;
+ form.Theme = MetroFramework.MetroThemeStyle.Dark;
+ form.Style = MetroFramework.MetroColorStyle.Silver;
+ form.StartPosition = FormStartPosition.CenterParent;
+ form.Text = $"{model.Name} - {modelTexture.Name}";
+ form.Size = new Size(600, 500);
+ form.MinimumSize = new Size(300, 300);
+
+ void ExportToolStripItem_Click(object sender, EventArgs e)
+ {
+ GameModelImporter.Default.ExportSettings.CreateModelOutline =
+ MessageBox.Show(
+ $"Do you wish to have all model parts contained in a group called '{model.Name}'?",
+ "Group model parts", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
+
+ using SaveFileDialog openFileDialog = new SaveFileDialog();
+ openFileDialog.FileName = model.Name;
+ openFileDialog.Filter = GameModelImporter.Default.SupportedModelFileFormatsFilter;
+
+ if (openFileDialog.ShowDialog(this) == DialogResult.OK)
+ {
+ var modelInfo = new GameModelInfo(model, new NamedData[1] { modelTexture });
+ GameModelImporter.Default.Export(openFileDialog.FileName, modelInfo);
+ }
+ }
+ ToolStripItem exportToolStripItem = new ToolStripButton("Export");
+ exportToolStripItem.Click += ExportToolStripItem_Click;
+
+ MenuStrip menu = new MenuStrip();
+ menu.BackColor = Color.FromArgb(35, 35, 35);
+ menu.ForeColor = Color.WhiteSmoke;
+ menu.Anchor = AnchorStyles.Top;
+ menu.Dock = DockStyle.Top;
+ menu.Items.Add(exportToolStripItem);
+
+ ModelRenderer renderer = new ModelRenderer();
+ form.Controls.Add(menu);
+ form.Controls.Add(renderer);
+
+ renderer.VSync = true;
+ renderer.BackColor = Color.FromArgb(30, 30, 30);
+ renderer.Dock = DockStyle.Fill;
+ renderer.Texture = modelTexture.Value;
+ renderer.LoadModel(model);
+ renderer.ResetCamera();
+
+ form.ShowDialog(this);
+
+ renderer.Dispose();
+ form.Dispose();
+ }
+
+ private void PckEditor_Load(object sender, EventArgs e)
+ {
+ CheckForPasswordAndRemove();
+ BuildMainTreeView();
+ UpdateRichPresence();
+ }
+
+ private void SetEndianess(OMI.ByteOrder endianness)
+ {
+ LittleEndianCheckBox.Checked = endianness == OMI.ByteOrder.LittleEndian;
+ }
+
+ private OMI.ByteOrder GetEndianess()
+ {
+ return LittleEndianCheckBox.Checked ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian;
+ }
+
+ private void buttonEdit_Click(object sender, EventArgs e)
+ {
+ treeViewMain_DoubleClick(sender, e);
+ }
+
+ private void SetPckEndianness(OMI.ByteOrder endianness)
+ {
+ try
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && (asset.Type is PckAssetType.AudioFile || asset.Type is PckAssetType.SkinDataFile || asset.Type is PckAssetType.TexturePackInfoFile))
+ {
+ IDataFormatReader reader = asset.Type is PckAssetType.AudioFile
+ ? new PckAudioFileReader(endianness == OMI.ByteOrder.BigEndian ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian)
+ : new PckFileReader(endianness == OMI.ByteOrder.BigEndian ? OMI.ByteOrder.LittleEndian : OMI.ByteOrder.BigEndian);
+ object pck = reader.FromStream(new MemoryStream(asset.Data));
+
+ IDataFormatWriter writer = asset.Type is PckAssetType.AudioFile
+ ? new PckAudioFileWriter((PckAudioFile)pck, endianness)
+ : new PckFileWriter((PckFile)pck, endianness);
+ asset.SetData(writer);
+ _wasModified = true;
+ MessageBox.Show($"\"{asset.Filename}\" successfully converted to {(endianness == OMI.ByteOrder.LittleEndian ? "little" : "big")} endian.", "Converted PCK file");
+ }
+ }
+ catch (OverflowException)
+ {
+ MessageBox.Show(this, $"File was not a valid {(endianness != OMI.ByteOrder.LittleEndian ? "little" : "big")} endian PCK File.", "Not a valid PCK file");
+ return;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(this, ex.Message, "Not a valid PCK file");
+ return;
+ }
+ }
+
+ private void littleEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.ByteOrder.LittleEndian);
+
+ private void bigEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.ByteOrder.BigEndian);
+
+ private void SetModelVersion(int version)
+ {
+ if (treeViewMain.SelectedNode.Tag is PckAsset asset && asset.Type is PckAssetType.ModelsFile)
+ {
+ try
+ {
+ ModelContainer container = asset.GetData(new ModelFileReader());
+
+ if (container.Version == version)
+ {
+ MessageBox.Show(
+ this,
+ $"This model container is already Version {version + 1}.",
+ "Can't convert", MessageBoxButtons.OK, MessageBoxIcon.Error
+ );
+ return;
+ }
+
+ if (version == 2 &&
+ MessageBox.Show(
+ this,
+ "Conversion to 1.14 models.bin format does not yet support parent declaration and may not be 100% accurate.\n" +
+ "Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes
+ )
+ {
+ return;
+ }
+
+ if (container.Version > 1 &&
+ MessageBox.Show(
+ this,
+ "Conversion from 1.14 models.bin format does not yet support parent parts and may not be 100% accurate.\n" +
+ "Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes
+ )
+ {
+ return;
+ }
+
+ asset.SetData(new ModelFileWriter(container, version));
+ _wasModified = true;
+ MessageBox.Show(
+ this,
+ $"\"{asset.Filename}\" successfully converted to Version {version + 1} format.",
+ "Converted model container file"
+ );
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(this, ex.Message, "Not a valid model container file.");
+ return;
+ }
+ }
+ }
+
+ private void setModelVersion1ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(0);
+
+ private void setModelVersion2ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(1);
+
+ private void setModelVersion3ToolStripMenuItem_Click(object sender, EventArgs e) => SetModelVersion(2);
+
+ private void treeViewMain_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
+ {
+ if (e.Node is not null)
+ treeViewMain.SelectedNode = e.Node;
+ }
+
+ private void contextMenuPCKEntries_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ correctSkinDecimalsToolStripMenuItem.Visible = false;
+ generateMipMapTextureToolStripMenuItem1.Visible = false;
+ setModelContainerFormatToolStripMenuItem.Visible = false;
+ setSubPCKEndiannessToolStripMenuItem.Visible = false;
+ exportToolStripMenuItem.Visible = false;
+ toolStripSeparator5.Visible = false;
+ toolStripSeparator6.Visible = false;
+ if (treeViewMain?.SelectedNode.TryGetTagData(out PckAsset asset) ?? false)
+ {
+ replaceToolStripMenuItem.Visible = true;
+ cloneFileToolStripMenuItem.Visible = true;
+ setFileTypeToolStripMenuItem.Visible = true;
+ toolStripSeparator5.Visible = true;
+ toolStripSeparator6.Visible = true;
+
+ if (asset.Type == PckAssetType.SkinFile)
+ {
+ correctSkinDecimalsToolStripMenuItem.Visible = true;
+ exportToolStripMenuItem.Visible = true;
+ }
+ if (asset.Type == PckAssetType.TextureFile)
+ generateMipMapTextureToolStripMenuItem1.Visible = true;
+ if (asset.Type == PckAssetType.ModelsFile)
+ setModelContainerFormatToolStripMenuItem.Visible = true;
+ if (asset.Type == PckAssetType.SkinDataFile || asset.Type == PckAssetType.TexturePackInfoFile || asset.Type == PckAssetType.AudioFile)
+ setSubPCKEndiannessToolStripMenuItem.Visible = true;
+ }
+ else
+ {
+ replaceToolStripMenuItem.Visible = false;
+ cloneFileToolStripMenuItem.Visible = false;
+ setFileTypeToolStripMenuItem.Visible = false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Controls/PckEditor.resx b/PCK-Studio/Controls/PckEditor.resx
new file mode 100644
index 00000000..5e94f7c7
--- /dev/null
+++ b/PCK-Studio/Controls/PckEditor.resx
@@ -0,0 +1,2097 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+
+
+ 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
+ 8+BMiU9xSj9GDDCHwDUcMkHMV8I4YKwwEz0K5TTDbjg/NnbZmEsvwcYuuVQYpxwTXCyU8g2YMaMA9NIJ
+ QlbKc/bsWePhf9yV868cRwU+9urlV49ddc3mO2PQDmDbQrL1wvZLH2n1jwL0m3S/9BN9i3ENH0E3I+Ij
+ 165ePWaFyYNijmQzbk6y88LG0GHSNcktA2RXAwTAVlDG8CCv2hKBdbzbZhRPJilXFq4wuuJh8dIlYxYs
+ Xjhm/sL5Y+fMgz7wYKfjL5ulHyRZNmWXbKCcX4CWVvpbgeTVFkhq0j+BAmI8iTTZBwWAzyt9dNH16gP/
+ HXPlvCvGzJs7Tx9M/ohfjp/5M3zskkuJl5c2/SoAuyjtI8ULoND/ZfgWuhdK9G0bxdkYVm1j0OlYdErs
+ wq+Zk/kS3sJXSkjy8rMGok+SZSlXQL8z3hvLkn6JT+7OLKZwXrZ0KSvWFSNio/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3W
+ b/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb/3Wb1uy/Yf/8P8D4rKD
+ rca4/zIAAAAASUVORK5CYII=
+
+
+
+
+ NoControl
+
+
+ 413, 0
+
+
+ 190, 50
+
+
+ Zoom
+
+
+
+ 14
+
+
+ logoPictureBox
+
+
+ System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 10
+
+
+ 8, 27
+
+
+ 241, 23
+
+
+ 2
+
+
+ pckFileLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 4
+
+
+ Top, Right
+
+
+ True
+
+
+ 1369, 252
+
+
+ 30, 19
+
+
+ 19
+
+
+ aaa
+
+
+ labelImageSize
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 5
+
+
+ Top, Right
+
+
+ True
+
+
+ 1347, 53
+
+
+ 0, 0
+
+
+ 17
+
+
+ fileEntryCountLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 6
+
+
+ Bottom, Right
+
+
+ True
+
+
+ 204, 144
+
+
+ 0, 0
+
+
+ 15
+
+
+ metroLabel2
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 2
+
+
+ Bottom, Right
+
+
+
+
+
+ NoControl
+
+
+ 128, 2
+
+
+ 15, 15
+
+
+ 1
+
+
+ False
+
+
+ False
+
+
+ 215, 114
+
+
+ 146, 20
+
+
+ 21
+
+
+ entryTypeTextBox
+
+
+ MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 3
+
+
+ Bottom, Right
+
+
+
+
+
+ NoControl
+
+
+ 128, 2
+
+
+ 15, 15
+
+
+ 1
+
+
+ False
+
+
+ False
+
+
+ 215, 146
+
+
+ 146, 20
+
+
+ 16
+
+
+ entryDataTextBox
+
+
+ MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 4
+
+
+ Bottom, Right
+
+
+ 215, 172
+
+
+ 146, 33
+
+
+ 20
+
+
+ buttonEdit
+
+
+ False
+
+
+ buttonEdit
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 5
+
+
+ Bottom, Right
+
+
+ True
+
+
+ 266, 37
+
+
+ 0, 0
+
+
+ 13
+
+
+ metroLabel1
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ MetaTab
+
+
+ 6
+
+
+ 301, 19
+
+
+ 160, 22
+
+
+ Add Entry
+
+
+ 160, 22
+
+
+ Add BOX Entry
+
+
+ 160, 22
+
+
+ Add ANIM Entry
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x
+ DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5
+ jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC
+
+
+
+ 181, 22
+
+
+ Add Entry
+
+
+ 181, 22
+
+
+ Add Multiple Entries
+
+
+ 181, 22
+
+
+ Delete Entry
+
+
+ 181, 22
+
+
+ Edit All Entries
+
+
+ 182, 92
+
+
+ contextMenuMetaTree
+
+
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Left
+
+
+ 5, 5
+
+
+ 204, 229
+
+
+ 0
+
+
+ treeMeta
+
+
+ System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ MetaTab
+
+
+ 7
+
+
+ 4, 38
+
+
+ 5, 5, 5, 5
+
+
+ 724, 239
+
+
+ 0
+
+
+ Properties
+
+
+ MetaTab
+
+
+ MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ PropertiesTabControl
+
+
+ 0
+
+
+ Bottom
+
+
+ 279, 270
+
+
+ 732, 281
+
+
+ 11
+
+
+ PropertiesTabControl
+
+
+ MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 7
+
+
+ True
+
+
+ True
+
+
+ 433, 71
+
+
+ 0, 0
+
+
+ 3
+
+
+ label11
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 8
+
+
+ 22, 20
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABVSURBVDhPYxgc
+ 4P8Chv8YeKWUIFSaMPi/W+r//1MapOGTOixQ7UADsCkgAkO1jywDRIGxA8JQPlQ7PQyAaUTDUO30MACG
+ YZqhfKh24gGGzYMAMDAAAPvHncAZVkkSAAAAAElFTkSuQmCC
+
+
+
+ 172, 22
+
+
+ Folder
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAIkSURBVDhPpdLf
+ T1JxGMfxc1n8qtzcyglCWhFS1PLGHAgisDmktZZtabRSEYhDZ8xpiSWVpaSxLpoXyWquLvzV+oGZq+iy
+ /6Stm7qsm+DT830YMJw3rbO9Djs7z/P+wob03xcAyWbUwqLXotWgha1pDzPr1axl/y52uEHFrAY1z4l5
+ sVsK0IK1UVMbaKQAOXhgN2tuKLHQTKtBh6M0XwmIxe1OtexjXZa9pA6dlnomlgXx7WoCo/1eTF3pwfRQ
+ gM3HLmD+Wh8yIwE8CgcwFznLJs67cLPPgeMmXW1gKRXCZjqGfCbBvi6kWH6OnoXMKFsd68fa2CW0Haqr
+ BpYnh5G7F8PGtIyV2yG2NhXHeuo6nioD5CI+pRMsG+nFYqSHVQKrt0LYKAcmhyCeX6Vklk0MsI9phQIK
+ Bfy07OfPSkAs/v7xDcViEd6OZ/C2LyOXHMb75Agtlk72nF6hdy/FEgrFP3yI2OVA7r6MXz+/04siPB3P
+ aXgJ75JhbFIgP5PAZwr42lcp8IJnioUCBcLVQHbQizfjQTr1Kj7cTbBIpw1R54mK/GwMXwjqaYWkzrVV
+ A4uDPry+QYGJIN7eUVjMcQyyvWrrQRxbM/GdA4+Dbjy57MJC0AmnUQ2XUYPZXjse+qvKi9vRHZLisUJx
+ WyB3m0sBkwZuvYr56A8j7LQs0B2S7LMg2n0EUY8ZdpMaDgo4mlSsq1lXo7w4fuZk6Sf861U5mS9J+gsp
+ e+98+xbVEAAAAABJRU5ErkJggg==
+
+
+
+ 172, 22
+
+
+ Skin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAI/SURBVDhPjZHt
+ b9JQFMbvv6IRCiYmU+cGpQXH5oACMkZvgQILG2Su7e2mE3l1cTMricaXEQtscVN0UYIaB8MZmW/ZFxP/
+ KrzNpCHxi0+eL/ec53fuSQ7IHLqyXW+uwwj7lLBvQweu9N6Y/M65/h3iOmpNLL2hxaYj1bAEnxhXPkyB
+ TNe9/H76YS96rzOz0Z3lSQI1banX1uTLMfVkYetnMt/2LTRGMq1rwlv7SssJHnyLcbRp77csvLLdaF1l
+ HabVg+mElVg9cq//gOpJ+tmvVNRmiKsXUi8sPGUGPEWIshihiShlvN1meNoQoQ1R2jDfuBimCfHjJOsg
+ SrNXWIcRJwuQBFXJneXoOvL0NiGkzDtLrgJnKUIySp6L0MYYeVYWhUKYrAq+MG3WgGJolCfP1BGzI0zc
+ gfYcpNrlNHZ/SE9Ff4Ejn4vOjjIHDu7HI7RpjRsvsiOPN+7iRmVxqpkLakEANPf7ypyjnJzEQzEDegon
+ eS/t3grs3gw+Ki5iIAfJCgoMA7i4hWZU6TpmwCdlHr+7SvpoM1YR/VpO1wDQhRlQkzzZ0OVsmKwhby5k
+ 1cqnuX+tA1WZ4e3mUtiK/X/AcgBv9bUcx9YAXYOcrlPAm+fIIhyvIh/e6lhJYHiNHdX6AwAHPpcTPSWm
+ AVnWCh2mbeQpQEtN9tclpip78nBot37/i5KoIUY7rhIDOdaiIl+es5U4MkIZ8S15O4E/0YCB8HNbcuOh
+ mAGqxOQ5S4Q6f1yOF6CVp0w6gxfQ/ZdBnj/Cc21Sm8M0egAAAABJRU5ErkJggg==
+
+
+
+ 172, 22
+
+
+ Animated Texture
+
+
+ 172, 22
+
+
+ Audio.pck
+
+
+ 172, 22
+
+
+ Colours.col
+
+
+ 172, 22
+
+
+ Skins.pck
+
+
+ 172, 22
+
+
+ Behaviours.bin
+
+
+ 172, 22
+
+
+ EntityMaterials.bin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAA3SURBVDhPY/j/
+ /z9FGKsgGIsCKWSMTQ0QYxUE45FmALpiYvFwMgAbxqIYG8YqCMajBhCJ/zMAAPGwpV/Xje8RAAAAAElF
+ TkSuQmCC
+
+
+
+ 157, 22
+
+
+ Create
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAIkSURBVDhPpdLf
+ T1JxGMfxc1n8qtzcyglCWhFS1PLGHAgisDmktZZtabRSEYhDZ8xpiSWVpaSxLpoXyWquLvzV+oGZq+iy
+ /6Stm7qsm+DT830YMJw3rbO9Djs7z/P+wob03xcAyWbUwqLXotWgha1pDzPr1axl/y52uEHFrAY1z4l5
+ sVsK0IK1UVMbaKQAOXhgN2tuKLHQTKtBh6M0XwmIxe1OtexjXZa9pA6dlnomlgXx7WoCo/1eTF3pwfRQ
+ gM3HLmD+Wh8yIwE8CgcwFznLJs67cLPPgeMmXW1gKRXCZjqGfCbBvi6kWH6OnoXMKFsd68fa2CW0Haqr
+ BpYnh5G7F8PGtIyV2yG2NhXHeuo6nioD5CI+pRMsG+nFYqSHVQKrt0LYKAcmhyCeX6Vklk0MsI9phQIK
+ Bfy07OfPSkAs/v7xDcViEd6OZ/C2LyOXHMb75Agtlk72nF6hdy/FEgrFP3yI2OVA7r6MXz+/04siPB3P
+ aXgJ75JhbFIgP5PAZwr42lcp8IJnioUCBcLVQHbQizfjQTr1Kj7cTbBIpw1R54mK/GwMXwjqaYWkzrVV
+ A4uDPry+QYGJIN7eUVjMcQyyvWrrQRxbM/GdA4+Dbjy57MJC0AmnUQ2XUYPZXjse+qvKi9vRHZLisUJx
+ WyB3m0sBkwZuvYr56A8j7LQs0B2S7LMg2n0EUY8ZdpMaDgo4mlSsq1lXo7w4fuZk6Sf861U5mS9J+gsp
+ e+98+xbVEAAAAABJRU5ErkJggg==
+
+
+
+ 228, 22
+
+
+ Import Skin
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAEnSURBVDhPYxgc
+ 4P8Chv8YeKWUIFSaMPi/W+r//1MapOGTOixQ7UADkCS05Xjh2FhFEIydtIT+22uJAsX4wBimFqod04Bt
+ nTn/9/YV/T82rQGM93YXAfkl/1eVRYPl8RqwuTnn/5aW3P8r69L+r67P+7+mIf//rIKo/7s7i/7PyfT9
+ PzvTC78BW6AGrKpN+7+2IReM5xTF/N/VWQA0wAdogA8BA4Ca//7799/VauH/TdUZ/7dVp//fA7Td3XLV
+ //+iwNgBYXwGbCiP+7+5Oun/9qai/5n2+v+zHAzAeG9HDnEGTIl3/D8tzuG/owLP/w5f2/9dPrYIjWgY
+ qh3VgAJnrf+5Lhr/HRV5/jvLcoExNs0gDNWOagBeDNMM5UO1Ew8wbB4EgIEBABiEccKRdcoAAAAAAElF
+ TkSuQmCC
+
+
+
+ 228, 22
+
+
+ Import Extracted Skins Folder
+
+
+ 228, 22
+
+
+ Add Texture
+
+
+ 228, 22
+
+
+ Add File
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABzSURBVDhPpYzB
+ DQAhCARp4hr3Txu254WTjYRb9cEmk/BgRjBVHTv85Twmgt77PcJEYIFrhIkAgWOEiSAGthEmgtbaD9fW
+ mBgpB4xywCgFxiMf5YDdrq3l5wjEjKtzTARMNlydY2IGot2ureVnRjkQmZbICyCi7XU5cfqKAAAAAElF
+ TkSuQmCC
+
+
+
+ 157, 22
+
+
+ Import
+
+
+ 186, 22
+
+
+ Export as 3DS Texture
+
+
+ 157, 22
+
+
+ Export
+
+
+ 222, 22
+
+
+ Skin (.PNG)
+
+
+ 222, 22
+
+
+ Cape (.PNG)
+
+
+ 222, 22
+
+
+ Texture (.PNG)
+
+
+ 222, 22
+
+
+ Languages File (.LOC)
+
+
+ 222, 22
+
+
+ Game Rules File (.GRF)
+
+
+ 222, 22
+
+
+ Music Cues File (audio.PCK)
+
+
+ 222, 22
+
+
+ Colour Table File (.COL)
+
+
+ 222, 22
+
+
+ Game Rules Header (.GRH)
+
+
+ 222, 22
+
+
+ Skins PCK (.PCK)
+
+
+ 222, 22
+
+
+ Models File (.BIN)
+
+
+ 222, 22
+
+
+ Behaviours File (.BIN)
+
+
+ 222, 22
+
+
+ Entity Materials File (.BIN)
+
+
+ 157, 22
+
+
+ Set File Type
+
+
+ 154, 6
+
+
+ 223, 22
+
+
+ Generate MipMap Texture
+
+
+ 223, 22
+
+
+ View File Info
+
+
+ 223, 22
+
+
+ Correct Skin Decimals
+
+
+ 100, 22
+
+
+ Big
+
+
+ 100, 22
+
+
+ Little
+
+
+ 223, 22
+
+
+ Set Endianness
+
+
+ 80, 22
+
+
+ 1
+
+
+ 80, 22
+
+
+ 2
+
+
+ 80, 22
+
+
+ 3
+
+
+ 223, 22
+
+
+ Set Model Container version
+
+
+ 157, 22
+
+
+ Misc. Functions
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAACYSURBVDhPpZBZ
+ CsQwDEOd5QK5/2E9qCBGXtopzMcDxxKyY3P3izmnm9kt0OlVvsVVVgOAtvduQ4KJdYbaGKOEFFOHamut
+ ENKaMlk75zi2QX1rUqDpkbEF/cGktb47ygb5ODA8hVArgsK1cx+EAE7LaB8+hb3QzDx942eAXrqjBOgR
+ MRkBfHeUADbe8ncANw4NhLwF33R3+wA6sV5/E8GOLwAAAABJRU5ErkJggg==
+
+
+
+ 157, 22
+
+
+ Extract
+
+
+ 154, 6
+
+
+ 157, 22
+
+
+ Clone
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAACVJREFUOE9jwAL+E8AkAbI0IYNRA0YNAIFRA8g0AKYJF0YCDAwAzhor1TRE/JoA
+ AAAASUVORK5CYII=
+
+
+
+ 157, 22
+
+
+ Rename
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAC/SURBVDhPlVHB
+ DQMhDEOIfwfoOuzFoPxhAd5c6/SMAgq0tRQFmdgXfA5IKUkBMcbHPxyJCxVCkK7rm+EwaK1dQO9dClzO
+ WfpOTM7hy1oMGNvY4pucxNY2p6cAWzFw2oZuMmiJweGeHM634UdLg50YwD05vQ2fYoaoDTEMrJyIfw3R
+ 4qYQWUZgg6OwlDJyMH8LcwF2T8FZ5kYQb4Lde/9Et8S6Dy1z0LUGi7VpWGvl3Lw2V98ZrtwIUYktwwPn
+ 3AtE5NqX8pp0ZQAAAABJRU5ErkJggg==
+
+
+
+ 157, 22
+
+
+ Replace
+
+
+ 157, 22
+
+
+ Delete
+
+
+ 158, 236
+
+
+ contextMenuPCKEntries
+
+
+ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Left
+
+
+ 0
+
+
+ 204, 20
+
+
+ 32, 32
+
+
+ 5, 50
+
+
+ 0
+
+
+ 274, 501
+
+
+ 20
+
+
+ treeViewMain
+
+
+ System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ $this
+
+
+ 9
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+ vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x
+ DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5
+ jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC
+
+
+
+ 181, 22
+
+
+ Add Multiple Entries
+
+
+ Top, Right
+
+
+ True
+
+
+ 831, 0
+
+
+ 173, 15
+
+
+ 22
+
+
+ Save as Switch/Vita/PS4 PCK
+
+
+ LittleEndianCheckBox
+
+
+ MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 3
+
+
+ Top, Bottom, Left, Right
+
+
+ None
+
+
+ NoControl
+
+
+ 285, 50
+
+
+ 218, 218
+
+
+ Zoom
+
+
+ 18
+
+
+ previewPictureBox
+
+
+ PckStudio.ToolboxItems.InterpolationPictureBox, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null
+
+
+ $this
+
+
+ 2
+
+
+ True
+
+
+ None
+
+
+ 4, 38
+
+
+ 5, 50, 5, 7
+
+
+ 1016, 558
+
+
+ addEntryToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addBOXEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addANIMEntryToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addMultipleEntriesToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ deleteEntryToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ editAllEntriesToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ createToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ folderToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ createAnimatedTextureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ audiopckToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ colourscolToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ CreateSkinsPCKToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ behavioursbinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ entityMaterialsbinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importSkinsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importSkinToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ importExtractedSkinsFolderToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addTextureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ exportToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ as3DSTextureFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setFileTypeToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ capeToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ textureToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ languagesFileLOCToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ gameRulesFileGRFToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ audioPCKFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ coloursCOLFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ gameRulesHeaderGRHToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ skinsPCKToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ modelsFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ behavioursFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ entityMaterialsFileBINToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ toolStripSeparator5
+
+
+ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ miscFunctionsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ generateMipMapTextureToolStripMenuItem1
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ viewFileInfoToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ correctSkinDecimalsToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setSubPCKEndiannessToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ bigEndianXbox360PS3WiiUToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ littleEndianPS4PSVitaSwitchToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ setModelContainerFormatToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version1ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version2ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ version3114ToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ extractToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ toolStripSeparator6
+
+
+ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ cloneFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ renameFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ replaceToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ deleteFileToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ imageList
+
+
+ System.Windows.Forms.ImageList, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ addMultipleEntriesToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ PckEditor
+
+
+ PckStudio.Internal.EditorControl`1[[PckStudio.Internal.PackInfo, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null]], PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null
+
+
\ No newline at end of file
diff --git a/PCK-Studio/Extensions/AnimationExtensions.cs b/PCK-Studio/Extensions/AnimationExtensions.cs
deleted file mode 100644
index 81af938a..00000000
--- a/PCK-Studio/Extensions/AnimationExtensions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Drawing;
-using AnimatedGif;
-using PckStudio.Internal;
-
-namespace PckStudio.Extensions
-{
- internal static class AnimationExtensions
- {
- internal static Image CreateAnimationImage(this Animation animation)
- {
- if (animation.FrameCount == 0)
- {
- return null;
- }
- var ms = new System.IO.MemoryStream();
- var generateor = new AnimatedGifCreator(ms, GameConstants.GameTickInMilliseconds, 0);
- foreach (Animation.Frame frame in animation.GetInterpolatedFrames())
- {
- generateor.AddFrame(frame.Texture, frame.Ticks * GameConstants.GameTickInMilliseconds, GifQuality.Bit8);
- }
- ms.Position = 0;
- return Image.FromStream(ms);
- }
- }
-}
diff --git a/PCK-Studio/Extensions/ImageLayoutDirection.cs b/PCK-Studio/Extensions/ImageLayoutDirection.cs
deleted file mode 100644
index 7cfc23eb..00000000
--- a/PCK-Studio/Extensions/ImageLayoutDirection.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace PckStudio.Extensions
-{
- internal enum ImageLayoutDirection
- {
- Horizontal,
- Vertical
- }
-}
diff --git a/PCK-Studio/Extensions/PckAssetExtensions.cs b/PCK-Studio/Extensions/PckAssetExtensions.cs
deleted file mode 100644
index 08c3f96e..00000000
--- a/PCK-Studio/Extensions/PckAssetExtensions.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Drawing;
-using System.Collections.Generic;
-
-using OMI.Formats.Pck;
-using OMI.Workers;
-
-using PckStudio.Interfaces;
-using PckStudio.Internal.Deserializer;
-using PckStudio.Internal.Serializer;
-
-namespace PckStudio.Extensions
-{
- internal static class PckAssetExtensions
- {
- private const string MipMap = "MipMapLevel";
-
- internal static PckAsset CreateNewAssetIf(this PckFile pck, bool condition, string filename, PckAssetType filetype, IDataFormatWriter writer)
- {
- if (condition)
- {
- return pck.CreateNewAsset(filename, filetype, writer);
- }
- return default;
- }
-
- internal static PckAsset CreateNewAsset(this PckFile pck, string filename, PckAssetType filetype, IDataFormatWriter writer)
- {
- PckAsset asset = pck.CreateNewAsset(filename, filetype);
- asset.SetData(writer);
- return asset;
- }
-
- internal static Image GetTexture(this PckAsset asset)
- {
- if (asset.Type != PckAssetType.SkinFile &&
- asset.Type != PckAssetType.CapeFile &&
- asset.Type != PckAssetType.TextureFile)
- {
- throw new Exception("Asset is not suitable to contain image data.");
- }
- return asset.GetDeserializedData(ImageDeserializer.DefaultDeserializer);
- }
-
- internal static T GetDeserializedData(this PckAsset asset, IPckAssetDeserializer deserializer)
- {
- return deserializer.Deserialize(asset);
- }
-
- internal static T GetData(this PckAsset asset, IDataFormatReader formatReader) where T : class
- {
- using var ms = new MemoryStream(asset.Data);
- return formatReader.FromStream(ms);
- }
-
- internal static void SetSerializedData(this PckAsset asset, T obj, IPckAssetSerializer serializer)
- {
- serializer.Serialize(obj, ref asset);
- }
-
- internal static void SetData(this PckAsset asset, IDataFormatWriter formatWriter)
- {
- using (var stream = new MemoryStream())
- {
- formatWriter.WriteToStream(stream);
- asset.SetData(stream.ToArray());
- }
- }
-
- internal static void SetTexture(this PckAsset asset, Image image)
- {
- if (asset.Type != PckAssetType.SkinFile &&
- asset.Type != PckAssetType.CapeFile &&
- asset.Type != PckAssetType.TextureFile)
- {
- throw new Exception("Asset is not suitable to contain image data.");
- }
- asset.SetSerializedData(image, ImageSerializer.DefaultSerializer);
- }
-
- internal static bool IsMipmappedFile(this PckAsset asset)
- {
- // We only want to test the file name itself. ex: "terrainMipMapLevel2"
- string name = Path.GetFileNameWithoutExtension(asset.Filename);
-
- // check if last character is a digit (0-9). If not return false
- if (!char.IsDigit(name[name.Length - 1]))
- return false;
-
- // If string does not end with MipMapLevel, then it's not MipMapped
- if (!name.Remove(name.Length - 1, 1).EndsWith(MipMap))
- return false;
- return true;
- }
-
- internal static string GetNormalPath(this PckAsset asset)
- {
- if (!asset.IsMipmappedFile())
- return asset.Filename;
- string ext = Path.GetExtension(asset.Filename);
- return asset.Filename.Remove(asset.Filename.Length - (MipMap.Length + 1) - ext.Length) + ext;
- }
-
- internal static void DeserializeProperties(this PckAsset asset, IEnumerable serializedData)
- {
- IEnumerable> lines = serializedData
- .Select(line => line.Split([' '], 2))
- .Where (keyValue => keyValue.Length == 2)
- .Select(keyValue => new KeyValuePair(keyValue[0].Replace(":", ""), keyValue[1]));
- foreach (KeyValuePair kv in lines)
- {
- asset.AddProperty(kv);
- }
- }
-
- internal static IEnumerable SerializeProperties(this PckAsset asset, string seperater = ":")
- {
- IReadOnlyList> properties = asset.GetProperties();
- return properties.Select(property => property.Key + seperater + property.Value);
- }
- }
-}
diff --git a/PCK-Studio/External/API/Miles/Binka.cs b/PCK-Studio/External/API/Miles/Binka.cs
index 16e6ee96..47000ef8 100644
--- a/PCK-Studio/External/API/Miles/Binka.cs
+++ b/PCK-Studio/External/API/Miles/Binka.cs
@@ -2,7 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
-using PckStudio.Extensions;
+using PckStudio.Core.Extensions;
using PckStudio.Internal;
using PckStudio.Internal.App;
using SharpMSS;
diff --git a/PCK-Studio/FileFormats/CSMBFile.cs b/PCK-Studio/FileFormats/CSMBFile.cs
deleted file mode 100644
index b07d8f80..00000000
--- a/PCK-Studio/FileFormats/CSMBFile.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using System;
-using System.Drawing;
-using System.IO;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace PckStudio.FileFormats
-{
- #region File Structure
- /*
- Version - 4 bytes[int32]
- NumberOfParts - 4 bytes[int32]
- {
- Part name length - 2 bytes[int16]
- part name - x bytes
- part parent - 4 bytes[int32] (HEAD=1, BODY=2, LEG0=3, LEG1=4, ARM0=5, ARM1=6)
- Position-X - 4 bytes[float]
- Position-Y - 4 bytes[float]
- Position-Z - 4 bytes[float]
- Size-X - 4 bytes[float]
- Size-Y - 4 bytes[float]
- Size-Z - 4 bytes[float]
- UV-Y - 4 bytes[int32]
- UV-X - 4 bytes[int32]
- mirror texture - 1 byte[bool]
- Hide with armour - 1 byte[bool]
- inflation/scale value - 4 bytes[float]
- }
- NumberOfOffsets - 4 bytes[int32]
- {
- offset part - 4 bytes[int32]
- vertical offset - 4 bytes[float]
- }
- */
- #endregion
- class CSMBFile
- {
- public List Parts = new List();
- public List Offsets = new List();
- }
-
- public class CSMBPart
- {
- public string Name = "Partname";
- public CSMBParentPart Parent = 0;
- public float posX, posY, posZ = 0.0f;
- public float sizeX, sizeY, sizeZ = 0.0f;
- public int uvX, uvY = 0;
- public bool HideWArmour, MirrorTexture = false;
- public float Inflation = 0.0f;
- }
- public class CSMBOffset
- {
- public CSMBOffsetPart offsetPart = 0;
- public float VerticalOffset = 0.0f;
- }
-
- public enum CSMBOffsetPart
- {
- HEAD = 0,
- BODY = 1,
- ARM0 = 2,
- ARM1 = 3,
- LEG0 = 4,
- LEG1 = 5,
- HEADWEAR = 6,
- JACKET = 7,
- SLEEVE0 = 8,
- SLEEVE1 = 9,
- PANTS0 = 10,
- PANTS1 = 11,
- WAIST = 12,
- LEGGING0 = 13,
- LEGGING1 = 14,
- SOCK0 = 15,
- SOCK1 = 16,
- BOOT0 = 17,
- BOOT1 = 18,
- ARMARMOR1 = 19,
- ARMARMOR0 = 20,
- BODYARMOR = 21,
- BELT = 22,
- TOOL0 = 23,
- TOOL1 = 24,
- HELMET = 25,
- SHOULDER0 = 26,
- SHOULDER1 = 27,
- CHEST = 28
- }
-
- public enum CSMBParentPart
- {
- HEAD = 0,
- BODY = 1,
- ARM0 = 2,
- ARM1 = 3,
- LEG0 = 4,
- LEG1 = 5,
- }
-}
diff --git a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.Designer.cs b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.Designer.cs
index bd3df23c..52426b93 100644
--- a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.Designer.cs
+++ b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.Designer.cs
@@ -33,7 +33,6 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddSkinPrompt));
System.Windows.Forms.Label label2;
System.Windows.Forms.Label label1;
- this.textTheme = new System.Windows.Forms.TextBox();
this.contextMenuSkin = new System.Windows.Forms.ContextMenuStrip(this.components);
this.replaceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuCape = new System.Windows.Forms.ContextMenuStrip(this.components);
@@ -81,11 +80,6 @@
label1.ForeColor = System.Drawing.Color.White;
label1.Name = "label1";
//
- // textTheme
- //
- resources.ApplyResources(this.textTheme, "textTheme");
- this.textTheme.Name = "textTheme";
- //
// contextMenuSkin
//
this.contextMenuSkin.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -289,6 +283,7 @@
// capePictureBox
//
resources.ApplyResources(this.capePictureBox, "capePictureBox");
+ this.capePictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.capePictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.capePictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.capePictureBox.Name = "capePictureBox";
@@ -298,6 +293,7 @@
// skinPictureBox
//
resources.ApplyResources(this.skinPictureBox, "skinPictureBox");
+ this.skinPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.skinPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.skinPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.skinPictureBox.Name = "skinPictureBox";
@@ -343,7 +339,6 @@
}
#endregion
- private System.Windows.Forms.TextBox textTheme;
private System.Windows.Forms.ContextMenuStrip contextMenuSkin;
private System.Windows.Forms.ToolStripMenuItem replaceToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip contextMenuCape;
diff --git a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.cs b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.cs
index 0fa628c5..a2f83a5c 100644
--- a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.cs
+++ b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.cs
@@ -8,127 +8,90 @@ using OMI.Formats.Languages;
using OMI.Formats.Pck;
using PckStudio.Internal;
using PckStudio.Forms.Editor;
-using PckStudio.Internal.IO._3DST;
+using PckStudio.Core.IO._3DST;
using PckStudio.Properties;
using PckStudio.Forms;
-using PckStudio.Extensions;
+using PckStudio.Core.Extensions;
+using System.Linq;
+using System.Diagnostics;
+using PckStudio.Core.Skin;
+using PckStudio.Interfaces;
+using PckStudio.Core;
namespace PckStudio.Forms.Additional_Popups
{
public partial class AddSkinPrompt : MetroFramework.Forms.MetroForm
{
- public PckAsset SkinAsset => _skin;
- public PckAsset CapeAsset => _cape;
- public bool HasCape => _cape is not null;
+ public Skin NewSkin => newSkin;
- private LOCFile currentLoc;
- private PckAsset _skin = new PckAsset("dlcskinXYXYXYXY", PckAssetType.SkinFile);
- private PckAsset _cape;
- private SkinANIM _anim = SkinANIM.Empty;
+ private Skin newSkin;
private Random rng = new Random();
- private eSkinType skinType;
-
- private enum eSkinType
- {
- Invalid = -1,
- _64x64,
- _64x32,
- _64x64HD,
- _64x32HD,
- Custom,
- }
-
- public AddSkinPrompt(LOCFile loc)
+ public AddSkinPrompt()
{
InitializeComponent();
- currentLoc = loc;
+ newSkin = new Skin("", new SkinANIM(SkinAnimMask.RESOLUTION_64x64), Resources.classic_template, Enumerable.Empty(), Enumerable.Empty());
}
- private void CheckImage(Image img)
+ private void SetNewTexture(Image img)
{
- switch (img.Height)
+ Debug.Assert(img is not null, "Image is null.");
+
+ if (img.Width != img.Height && img.Height != img.Width / 2)
{
- case 64:
- _anim = _anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64, true);
- MessageBox.Show(this, "64x64 Skin Detected");
- skinType = eSkinType._64x64;
- break;
- case 32:
- _anim = _anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64 | SkinAnimFlag.SLIM_MODEL, false);
- MessageBox.Show(this, "64x32 Skin Detected");
- skinType = eSkinType._64x32;
- break;
- default:
- if (img.Width == img.Height)
- {
- _anim = _anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64, true);
- MessageBox.Show(this, "64x64 HD Skin Detected");
- skinType = eSkinType._64x64HD;
- break;
- }
-
- if (img.Height == img.Width / 2)
- {
- _anim = _anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64 | SkinAnimFlag.SLIM_MODEL, false);
- MessageBox.Show(this, "64x32 HD Skin Detected");
- skinType = eSkinType._64x32HD;
- break;
- }
-
- MessageBox.Show(this, "Not a Valid Skin File");
- skinType = eSkinType.Invalid;
- return;
+ MessageBox.Show("The selected image does not suit a skin texture.", "Invalid image dimensions.", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
}
+ newSkin.Anim.SetFlag(SkinAnimFlag.RESOLUTION_64x64, img.Width == img.Height);
- skinPictureBox.Image = img;
+ skinPictureBox.Image = newSkin.Texture = img;
+ labelSelectTexture.Visible = false;
capePictureBox.Visible = true;
buttonCape.Visible = true;
capeLabel.Visible = true;
buttonDone.Enabled = true;
buttonAnimGen.Enabled = true;
- labelSelectTexture.Visible = false;
}
private void DrawModel()
{
- bool isSlim = _anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
+ bool isSlim = newSkin.Anim.GetFlag(SkinAnimFlag.SLIM_MODEL);
Pen outlineColor = Pens.LightGray;
Brush fillColor = Brushes.Gray;
Image previewTexture = new Bitmap(displayBox.Width, displayBox.Height);
using (Graphics g = Graphics.FromImage(previewTexture))
{
- if(!_anim.GetFlag(SkinAnimFlag.HEAD_DISABLED))
+ if(!newSkin.Anim.GetFlag(SkinAnimFlag.HEAD_DISABLED))
{
//Head
g.DrawRectangle(outlineColor, 70, 15, 40, 40);
g.FillRectangle(fillColor, 71, 16, 39, 39);
}
- if (!_anim.GetFlag(SkinAnimFlag.BODY_DISABLED))
+ if (!newSkin.Anim.GetFlag(SkinAnimFlag.BODY_DISABLED))
{
//Body
g.DrawRectangle(outlineColor, 70, 55, 40, 60);
g.FillRectangle(fillColor, 71, 56, 39, 59);
}
- if (!_anim.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED))
+ if (!newSkin.Anim.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED))
{
//Arm0
g.DrawRectangle(outlineColor, isSlim ? 55 : 50, 55, isSlim ? 15 : 20, 60);
g.FillRectangle(fillColor , isSlim ? 56 : 51, 56, isSlim ? 14 : 19, 59);
}
- if (!_anim.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED))
+ if (!newSkin.Anim.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED))
{
//Arm1
g.DrawRectangle(outlineColor, 110, 55, isSlim ? 15 : 20, 60);
g.FillRectangle(fillColor, 111, 56, isSlim ? 14 : 19, 59);
}
- if (!_anim.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED))
+ if (!newSkin.Anim.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED))
{
//Leg0
g.DrawRectangle(outlineColor, 70, 115, 20, 60);
g.FillRectangle(fillColor, 71, 116, 19, 59);
}
- if (!_anim.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED))
+ if (!newSkin.Anim.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED))
{
//Leg1
g.DrawRectangle(outlineColor, 90, 115, 20, 60);
@@ -158,7 +121,7 @@ namespace PckStudio.Forms.Additional_Popups
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
- CheckImage(Image.FromFile(ofd.FileName));
+ SetNewTexture(Image.FromFile(ofd.FileName).ReleaseFromFile());
}
}
@@ -188,12 +151,14 @@ namespace PckStudio.Forms.Additional_Popups
using (FileStream fs = File.OpenRead(ofd.FileName))
{
var reader = new _3DSTextureReader();
- CheckImage(reader.FromStream(fs));
+ SetNewTexture(reader.FromStream(fs));
}
textSkinName.Text = Path.GetFileNameWithoutExtension(ofd.FileName);
return;
}
- CheckImage(Image.FromFile(ofd.FileName));
+
+ Image img = Image.FromFile(ofd.FileName).ReleaseFromFile();
+ SetNewTexture(img);
}
}
}
@@ -219,15 +184,13 @@ namespace PckStudio.Forms.Additional_Popups
ofd.Title = "Select a PNG File";
if (ofd.ShowDialog() == DialogResult.OK)
{
- var img = Image.FromFile(ofd.FileName);
+ Image img = Image.FromFile(ofd.FileName).ReleaseFromFile();
if (img.RawFormat != ImageFormat.Png && img.Width != img.Height * 2)
{
MessageBox.Show(this, "Not a Valid Cape File");
return;
}
- capePictureBox.Image = Image.FromFile(ofd.FileName);
- _cape ??= new PckAsset("dlccapeXYXYXYXY", PckAssetType.CapeFile);
- _cape.SetData(File.ReadAllBytes(ofd.FileName));
+ newSkin.CapeTexture = capePictureBox.Image = img;
contextMenuCape.Items[0].Text = "Replace";
capeLabel.Visible = false;
contextMenuCape.Visible = true;
@@ -237,43 +200,17 @@ namespace PckStudio.Forms.Additional_Popups
private void CreateButton_Click(object sender, EventArgs e)
{
- if (!int.TryParse(textSkinID.Text, out int skinId))
+ if (radioButtonManual.Checked)
{
- MessageBox.Show(this, "The Skin ID Must be a Unique 8 Digit Number Thats Not Already in Use", "Invalid Skin ID", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
- string skinIdStr = skinId.ToString("d08");
- _skin.Filename = $"dlcskin{skinIdStr}.png";
- _skin.AddProperty("DISPLAYNAME", textSkinName.Text);
-
- if (currentLoc is not null)
- {
- string skinDisplayNameLocKey = $"IDS_dlcskin{skinIdStr}_DISPLAYNAME";
- _skin.AddProperty("DISPLAYNAMEID", skinDisplayNameLocKey);
- currentLoc.AddLocKey(skinDisplayNameLocKey, textSkinName.Text);
- }
-
- if (!string.IsNullOrEmpty(textThemeName.Text))
- {
- _skin.AddProperty("THEMENAME", textThemeName.Text);
- if (currentLoc is not null)
+ if (!int.TryParse(textSkinID.Text, out int skinId))
{
- _skin.AddProperty("THEMENAMEID", $"IDS_dlcskin{skinIdStr}_THEMENAME");
- currentLoc.AddLocKey($"IDS_dlcskin{skinIdStr}_THEMENAME", textThemeName.Text);
+ MessageBox.Show("The Skin Id must be a unique 8 digit number that is not already in use", "Invalid Skin Id", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
}
+ newSkin.Identifier = new SkinIdentifier(skinId);
}
- _skin.AddProperty("ANIM", _anim);
- _skin.AddProperty("GAME_FLAGS", "0x18");
- _skin.AddProperty("FREE", "1");
-
- if (HasCape)
- {
- _cape.Filename = $"dlccape{skinIdStr}.png";
- _skin.AddProperty("CAPEPATH", _cape.Filename);
- }
- _skin.SetTexture(skinPictureBox.Image);
+ newSkin.MetaData = new SkinMetaData(textSkinName.Text, textThemeName.Text);
DialogResult = DialogResult.OK;
- Close();
}
private void textSkinID_TextChanged(object sender, EventArgs e)
@@ -284,24 +221,21 @@ namespace PckStudio.Forms.Additional_Popups
private void CreateCustomModel_Click(object sender, EventArgs e)
{
- //Prompt for skin model generator
- if (MessageBox.Show(this, "Create your own custom skin model?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) != DialogResult.Yes)
+ if (MessageBox.Show("Create your own custom skin model?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) != DialogResult.Yes)
return;
- _skin.SetTexture(Resources.classic_template);
+ newSkin.MetaData = new SkinMetaData(textSkinName.Text, textThemeName.Text);
- using generateModel generate = new generateModel(_skin);
+ ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (customSkin) => newSkin = customSkin);
- if (generate.ShowDialog() == DialogResult.OK)
+ using CustomSkinEditor customSkinEditor = new CustomSkinEditor(newSkin, saveContext);
+
+ if (customSkinEditor.ShowDialog() == DialogResult.OK)
{
- displayBox.Image = generate.PreviewImage;
+ skinPictureBox.Image = newSkin.Texture;
buttonDone.Enabled = true;
labelSelectTexture.Visible = false;
- if (skinType != eSkinType._64x64 && skinType != eSkinType._64x64HD)
- {
- buttonSkin.Location = new Point(buttonSkin.Location.X - skinPictureBox.Width, buttonSkin.Location.Y);
- skinType = eSkinType._64x64;
- }
+ DrawModel();
}
}
@@ -309,8 +243,8 @@ namespace PckStudio.Forms.Additional_Popups
{
if (radioButtonAuto.Checked)
{
- int num = rng.Next(100000, 99999999);
- textSkinID.Text = num.ToString();
+ newSkin.Identifier = new(rng.Next(100000, 99999999));
+ textSkinID.Text = newSkin.Identifier.ToString();
textSkinID.Enabled = false;
}
}
@@ -322,10 +256,10 @@ namespace PckStudio.Forms.Additional_Popups
private void buttonAnimGen_Click(object sender, EventArgs e)
{
- using ANIMEditor diag = new ANIMEditor(_anim);
+ using ANIMEditor diag = new ANIMEditor(newSkin.Anim);
if (diag.ShowDialog(this) == DialogResult.OK)
{
- _anim = diag.ResultAnim;
+ newSkin.Anim = diag.ResultAnim;
DrawModel();
}
}
diff --git a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.resx b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.resx
index 6e87bf23..4255bf1a 100644
--- a/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.resx
+++ b/PCK-Studio/Forms/Additional-Popups/AddSkinPrompt.resx
@@ -219,21 +219,6 @@
19
-
- 102, 78
-
-
- 239, 20
-
-
- 32
-
-
- textTheme
-
-
- System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
17, 17
@@ -654,9 +639,6 @@
4
-
- False
-
108, 259
diff --git a/PCK-Studio/Forms/Additional-Popups/Animation/ChangeTile.cs b/PCK-Studio/Forms/Additional-Popups/Animation/ChangeTile.cs
index 58fdc3aa..de2fa054 100644
--- a/PCK-Studio/Forms/Additional-Popups/Animation/ChangeTile.cs
+++ b/PCK-Studio/Forms/Additional-Popups/Animation/ChangeTile.cs
@@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Windows.Forms;
-using MetroFramework.Controls;
-using System.Xml.Linq;
-using MetroFramework.Forms;
-using PckStudio.Extensions;
-using PckStudio.Internal;
-using PckStudio.Internal.App;
-using PckStudio.Internal.Json;
+using PckStudio.Core;
+using PckStudio.Core.Json;
+using PckStudio.Json;
+using PckStudio.Core.Extensions;
namespace PckStudio.Forms.Additional_Popups.Animation
{
@@ -32,10 +28,8 @@ namespace PckStudio.Forms.Additional_Popups.Animation
private void InitializeTreeviews()
{
- Profiler.Start();
GetTileDataToView(ResourceCategory.BlockAnimation);
GetTileDataToView(ResourceCategory.ItemAnimation);
- Profiler.Stop();
}
public DialogResult ShowDialog(IWin32Window owner)
diff --git a/PCK-Studio/Forms/Additional-Popups/EntityForms/AddEntry.cs b/PCK-Studio/Forms/Additional-Popups/EntityForms/AddEntry.cs
index 1057ab70..9b76ad87 100644
--- a/PCK-Studio/Forms/Additional-Popups/EntityForms/AddEntry.cs
+++ b/PCK-Studio/Forms/Additional-Popups/EntityForms/AddEntry.cs
@@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.Windows.Forms;
using PckStudio.Forms.Additional_Popups.Animation;
-using PckStudio.Internal.Json;
+using PckStudio.Core.Json;
+using PckStudio.Json;
namespace PckStudio.Forms.Additional_Popups.EntityForms
diff --git a/PCK-Studio/Forms/Additional-Popups/ItemSelectionPopUp.cs b/PCK-Studio/Forms/Additional-Popups/ItemSelectionPopUp.cs
index f84b95a5..c872cfdd 100644
--- a/PCK-Studio/Forms/Additional-Popups/ItemSelectionPopUp.cs
+++ b/PCK-Studio/Forms/Additional-Popups/ItemSelectionPopUp.cs
@@ -27,8 +27,11 @@ namespace PckStudio.Forms.Additional_Popups
private void okBtn_Click(object sender, EventArgs e)
{
- if(ComboBox.SelectedIndex > -1)
+ if(ComboBox.SelectedIndex <= -1)
+ {
cancelButton_Click(sender, e);
+ return;
+ }
DialogResult = DialogResult.OK;
}
diff --git a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.Designer.cs b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.Designer.cs
index 7bead21f..7c104732 100644
--- a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.Designer.cs
+++ b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.Designer.cs
@@ -31,8 +31,8 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NumericPrompt));
this.TextLabel = new System.Windows.Forms.Label();
this.OKButton = new System.Windows.Forms.Button();
- this.ContextLabel = new MetroFramework.Controls.MetroLabel();
this.ValueUpDown = new System.Windows.Forms.NumericUpDown();
+ this.toolTipLabel = new MetroFramework.Controls.MetroLabel();
((System.ComponentModel.ISupportInitialize)(this.ValueUpDown)).BeginInit();
this.SuspendLayout();
//
@@ -50,26 +50,28 @@
this.OKButton.UseVisualStyleBackColor = true;
this.OKButton.Click += new System.EventHandler(this.OKBtn_Click);
//
- // ContextLabel
- //
- resources.ApplyResources(this.ContextLabel, "ContextLabel");
- this.ContextLabel.FontSize = MetroFramework.MetroLabelSize.Small;
- this.ContextLabel.Name = "ContextLabel";
- this.ContextLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
- this.ContextLabel.WrapToLine = true;
- //
// ValueUpDown
//
resources.ApplyResources(this.ValueUpDown, "ValueUpDown");
+ this.ValueUpDown.BackColor = System.Drawing.SystemColors.WindowText;
+ this.ValueUpDown.ForeColor = System.Drawing.SystemColors.Window;
this.ValueUpDown.Name = "ValueUpDown";
//
+ // toolTipLabel
+ //
+ resources.ApplyResources(this.toolTipLabel, "toolTipLabel");
+ this.toolTipLabel.FontSize = MetroFramework.MetroLabelSize.Small;
+ this.toolTipLabel.Name = "toolTipLabel";
+ this.toolTipLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.toolTipLabel.WrapToLine = true;
+ //
// NumericPrompt
//
this.AcceptButton = this.OKButton;
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.ValueUpDown);
- this.Controls.Add(this.ContextLabel);
+ this.Controls.Add(this.toolTipLabel);
this.Controls.Add(this.OKButton);
this.Controls.Add(this.TextLabel);
this.MaximizeBox = false;
@@ -89,7 +91,7 @@
#endregion
public System.Windows.Forms.Button OKButton;
public System.Windows.Forms.Label TextLabel;
- public MetroFramework.Controls.MetroLabel ContextLabel;
private System.Windows.Forms.NumericUpDown ValueUpDown;
+ private MetroFramework.Controls.MetroLabel toolTipLabel;
}
}
\ No newline at end of file
diff --git a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.cs b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.cs
index 5ebf4bbf..5fad9a9b 100644
--- a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.cs
+++ b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.cs
@@ -6,23 +6,66 @@ namespace PckStudio
{
public partial class NumericPrompt : MetroForm
{
- public int SelectedValue => (int)ValueUpDown.Value;
+ public decimal SelectedValue => ValueUpDown.Value;
+
+ public int SelectedValueAsInt => (int)SelectedValue;
- public int Minimum { set => ValueUpDown.Minimum = value; }
- public int Maximum { set => ValueUpDown.Maximum = value; }
+ public string ToolTipText
+ {
+ get => toolTipLabel.Text;
+ set => toolTipLabel.Text = value;
+ }
+
+ public decimal ValueStep
+ {
+ get => ValueUpDown.Increment;
+ set => ValueUpDown.Increment = value;
+ }
+
+ public int DecimalPlaces
+ {
+ get => ValueUpDown.DecimalPlaces;
+ set => ValueUpDown.DecimalPlaces = value;
+ }
+
+ public decimal Minimum
+ {
+ get => ValueUpDown.Minimum;
+ set => ValueUpDown.Minimum = value;
+ }
+
+ public decimal Maximum
+ {
+ get => ValueUpDown.Maximum;
+ set => ValueUpDown.Maximum = value;
+ }
+
+ private NumericPrompt()
+ {
+ InitializeComponent();
+ }
public NumericPrompt(int initialValue)
: this(initialValue, int.MinValue, int.MaxValue)
{
+ }
+ public NumericPrompt(decimal initialValue, decimal minimum, decimal maximum)
+ : this()
+ {
+ Minimum = minimum;
+ Maximum = maximum;
+ ValueUpDown.Value = initialValue;
}
public NumericPrompt(int initialValue, int minimum, int maximum)
+ : this((decimal)initialValue, minimum, maximum)
+ {
+ }
+
+ public NumericPrompt(float initialValue, float minimum, float maximum)
+ : this((decimal)initialValue, (decimal)minimum, (decimal)maximum)
{
- InitializeComponent();
- ValueUpDown.Value = initialValue;
- Minimum = minimum;
- Maximum = maximum;
}
private void OKBtn_Click(object sender, EventArgs e)
@@ -32,9 +75,9 @@ namespace PckStudio
private void RenamePrompt_Load(object sender, EventArgs e)
{
- if(string.IsNullOrEmpty(ContextLabel.Text))
+ if (string.IsNullOrEmpty(toolTipLabel.Text))
{
- ContextLabel.Visible = false;
+ toolTipLabel.Visible = false;
Size = new System.Drawing.Size(264, 85);
}
}
diff --git a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.resx b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.resx
index 97fc650e..fd242b82 100644
--- a/PCK-Studio/Forms/Additional-Popups/NumericPrompt.resx
+++ b/PCK-Studio/Forms/Additional-Popups/NumericPrompt.resx
@@ -119,15 +119,18 @@
- Bottom
+ Bottom, Left
True
+
+ NoControl
+
- 19, 90
+ 19, 38
34, 13
@@ -163,7 +166,7 @@
NoControl
- 95, 118
+ 83, 66
75, 23
@@ -186,38 +189,14 @@
2
-
- Top
-
-
- 28, 27
-
-
- 208, 58
-
-
- 6
-
-
- TopCenter
-
-
- ContextLabel
-
-
- MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
-
- $this
-
-
- 1
+
+ Bottom, Left, Right
- 71, 88
+ 71, 36
- 164, 20
+ 141, 20
7
@@ -234,14 +213,47 @@
0
+
+ False
+
+
+ 3, 11
+
+
+ 235, 22
+
+
+ 235, 22
+
+
+ 6
+
+
+ TopCenter
+
+
+ toolTipLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 1
+
True
6, 13
+
+ GrowAndShrink
+
- 264, 150
+ 241, 98
@@ -2749,6 +2761,12 @@
AP//AAA=
+
+ 4, 2, 4, 2
+
+
+ 0, 60, 0, 0
+
CenterParent
diff --git a/PCK-Studio/Forms/AppSettingsForm.Designer.cs b/PCK-Studio/Forms/AppSettingsForm.Designer.cs
index 00ed901a..4fc1d0f8 100644
--- a/PCK-Studio/Forms/AppSettingsForm.Designer.cs
+++ b/PCK-Studio/Forms/AppSettingsForm.Designer.cs
@@ -63,7 +63,6 @@
this.Resizable = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Style = MetroFramework.MetroColorStyle.Black;
- this.Text = "Application Settings";
this.Theme = MetroFramework.MetroThemeStyle.Dark;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AppBehaviorSettingsForm_FormClosing);
this.ResumeLayout(false);
diff --git a/PCK-Studio/Forms/AppSettingsForm.cs b/PCK-Studio/Forms/AppSettingsForm.cs
index f9aa41d5..3bbd5509 100644
--- a/PCK-Studio/Forms/AppSettingsForm.cs
+++ b/PCK-Studio/Forms/AppSettingsForm.cs
@@ -5,6 +5,8 @@ using System.Diagnostics;
using System.Windows.Forms;
using MetroFramework.Controls;
using MetroFramework.Forms;
+using PckStudio.Core.App;
+using PckStudio.Internal.App;
using PckStudio.Properties;
namespace PckStudio.Forms
@@ -12,57 +14,84 @@ namespace PckStudio.Forms
public partial class AppSettingsForm : MetroForm
{
private ApplicationSettingsBase _applicationSettings;
+ internal const string keyToStringContextKey = "keyToString";
public AppSettingsForm()
- : this(Settings.Default)
+ : this("Application Settings", Settings.Default, new Dictionary()
+ {
+ ["ShowRichPresence"] = "Show Rich Presence",
+ ["AutoSaveChanges"] = "Auto Save",
+ ["UseLittleEndianAsDefault"] = "Open as Little Endian",
+ ["AutoUpdate"] = "Auto Update",
+ ["LoadSubPcks"] = "Load Sub Pcks",
+ ["UsePrerelease"] = "Use Prerelease",
+ ["ValidateImageDimension"] = "Validate skin dimension",
+ })
{
}
- public AppSettingsForm(ApplicationSettingsBase applicationSettings)
+ public AppSettingsForm(string title, ApplicationSettingsBase applicationSettings, Dictionary keyToStringMap = null)
{
InitializeComponent();
+ Text = title;
_applicationSettings = applicationSettings;
+ if (keyToStringMap is not null && !_applicationSettings.Context.ContainsKey(SettingsManager.KeyToStringContextKeyConst))
+ _applicationSettings.Context.Add(SettingsManager.KeyToStringContextKeyConst, keyToStringMap);
LoadSettings();
}
- private static Dictionary CheckBoxText = new Dictionary()
+ static bool ContextTryGetKeyToString(SettingsContext context, string key, out string value)
{
- ["ShowRichPresence"] = "Show Rich Presence",
- ["AutoSaveChanges"] = "Auto Save",
- ["UseLittleEndianAsDefault"] = "Open as Little Endian",
- ["AutoUpdate"] = "Auto Update",
- ["LoadSubPcks"] = "Load Sub Pcks",
- ["UsePrerelease"] = "Use Prerelease",
- };
-
- private void CheckBox_CheckedChanged(object sender, EventArgs e)
- {
- if (sender is CheckBox checkBox && checkBox.Tag is string settingsKey && _applicationSettings[settingsKey] is bool)
- {
- _applicationSettings[settingsKey] = checkBox.Checked;
- }
+ value = default;
+ return
+ context.ContainsKey(SettingsManager.KeyToStringContextKeyConst) &&
+ context[SettingsManager.KeyToStringContextKeyConst] is Dictionary keyToString &&
+ keyToString.TryGetValue(key, out value);
}
+ static Control CreateCheckBox(SettingsPropertyValue propertyValue, SettingsBase settings)
+ {
+ var control = new MetroCheckBox
+ {
+ Name = propertyValue.Name,
+ Tag = propertyValue.Name,
+ Text = ContextTryGetKeyToString(settings.Context, propertyValue.Name, out string name) ? name : propertyValue.Name,
+ Checked = (bool)propertyValue.PropertyValue,
+
+ AutoSize = true,
+ Theme = MetroFramework.MetroThemeStyle.Dark,
+ Style = MetroFramework.MetroColorStyle.White,
+ };
+
+ void CheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ if (sender is CheckBox checkBox && checkBox.Tag is string settingsKey && settings[settingsKey] is bool)
+ {
+ settings[settingsKey] = checkBox.Checked;
+ }
+ }
+
+ control.CheckedChanged += CheckBox_CheckedChanged;
+ return control;
+ }
+
+ delegate Control ControlCreateDelegate(SettingsPropertyValue propertyValue, SettingsBase settings);
+
+ Dictionary _typeToControl = new Dictionary()
+ {
+ [typeof(bool)] = CreateCheckBox,
+ };
+
private void LoadSettings()
{
foreach (SettingsPropertyValue item in _applicationSettings.PropertyValues)
{
Debug.WriteLine($"{item.Property.Name}: {item.Property.PropertyType}");
- if (!item.Property.Attributes.ContainsKey(typeof(UserScopedSettingAttribute)) || item.Property.PropertyType != typeof(bool))
+ bool isUserScoped = item.Property.Attributes?.ContainsKey(typeof(UserScopedSettingAttribute)) ?? true;
+ if (!isUserScoped || !_typeToControl.ContainsKey(item.Property.PropertyType) || item.Property.IsReadOnly)
continue;
- var checkBox = new MetroCheckBox
- {
- Name = item.Name,
- Tag = item.Name,
- Text = CheckBoxText.ContainsKey(item.Name) ? CheckBoxText[item.Name] : item.Name,
- Checked = (bool)item.PropertyValue,
-
- AutoSize = true,
- Theme = MetroFramework.MetroThemeStyle.Dark,
- Style = MetroFramework.MetroColorStyle.White,
- };
- checkBox.CheckedChanged += CheckBox_CheckedChanged;
- flowLayoutPanel.Controls.Add(checkBox);
+ Control control = _typeToControl[item.Property.PropertyType](item, _applicationSettings);
+ flowLayoutPanel.Controls.Add(control);
}
}
diff --git a/PCK-Studio/Forms/Editor/ANIMEditor.cs b/PCK-Studio/Forms/Editor/ANIMEditor.cs
index c379d7d2..27ef70d7 100644
--- a/PCK-Studio/Forms/Editor/ANIMEditor.cs
+++ b/PCK-Studio/Forms/Editor/ANIMEditor.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using PckStudio.Internal;
using PckStudio.Forms.Additional_Popups;
using PckStudio.Properties;
+using PckStudio.Core.Skin;
namespace PckStudio.Forms.Editor
{
diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs b/PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs
index 4fed8d2a..7a891d6a 100644
--- a/PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs
+++ b/PCK-Studio/Forms/Editor/AnimationEditor.Designer.cs
@@ -319,7 +319,7 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.animationPictureBox.BlendColor = System.Drawing.Color.White;
- this.animationPictureBox.BlendMode = PckStudio.Extensions.BlendMode.Multiply;
+ this.animationPictureBox.BlendMode = PckStudio.Core.Extensions.BlendMode.Multiply;
this.animationPictureBox.Image = null;
this.animationPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.animationPictureBox.Location = new System.Drawing.Point(157, 88);
diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs
index e5ba5639..a0f6cd02 100644
--- a/PCK-Studio/Forms/Editor/AnimationEditor.cs
+++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs
@@ -29,39 +29,32 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PckStudio.Forms.Additional_Popups.Animation;
-using PckStudio.Extensions;
-using PckStudio.Properties;
-using PckStudio.Internal;
-using PckStudio.Internal.Deserializer;
-using PckStudio.Internal.Serializer;
+using PckStudio.Core.Extensions;
+using PckStudio.Core.Deserializer;
+using PckStudio.Core.Serializer;
+using PckStudio.Core;
+using PckStudio.Interfaces;
+using PckStudio.Controls;
namespace PckStudio.Forms.Editor
{
- public partial class AnimationEditor : MetroForm
+ public partial class AnimationEditor : EditorForm
{
- public Animation Result => _animation;
+ private bool _editable;
- private Animation _animation;
- private bool _isSpecialTile;
-
- private AnimationEditor()
+ internal AnimationEditor(Animation animation, ISaveContext saveContext, string displayName, bool editable = true)
+ : base(animation, saveContext)
{
InitializeComponent();
- toolStripSeparator1.Visible = saveToolStripMenuItem1.Visible = !Settings.Default.AutoSaveChanges;
- }
-
- internal AnimationEditor(Animation animation, string displayName, bool isSpecialTile = false)
- : this()
- {
- _ = animation ?? throw new ArgumentNullException(nameof(animation));
- _animation = animation;
+ saveToolStripMenuItem1.Available = !saveContext.AutoSave;
+ toolStripSeparator1.Available = !saveContext.AutoSave;
tileLabel.Text = displayName;
- _isSpecialTile = isSpecialTile;
+ _editable = editable;
animationPictureBox.Image = animation.CreateAnimationImage();
}
- internal AnimationEditor(Animation animation, string displayName, Color blendColor)
- : this(animation, displayName)
+ internal AnimationEditor(Animation animation, ISaveContext saveContext, string displayName, Color blendColor)
+ : this(animation, saveContext, displayName)
{
animationPictureBox.UseBlendColor = true;
animationPictureBox.BlendColor = blendColor;
@@ -69,10 +62,9 @@ namespace PckStudio.Forms.Editor
private void ValidateToolStrip()
{
- bulkAnimationSpeedToolStripMenuItem.Enabled =
- importToolStripMenuItem.Enabled =
- exportAsToolStripMenuItem.Enabled =
- InterpolationCheckbox.Visible = !_isSpecialTile;
+ editToolStripMenuItem.Visible =
+ importToolStripMenuItem.Visible =
+ InterpolationCheckbox.Visible = _editable;
}
private void AnimationEditor_Load(object sender, EventArgs e)
@@ -83,20 +75,20 @@ namespace PckStudio.Forms.Editor
private void LoadAnimationTreeView()
{
- if (_animation is null)
+ if (EditorValue is null)
{
- AnimationStartStopBtn.Enabled = false;
+ AnimationStartStopBtn.Visible = false;
return;
}
- AnimationStartStopBtn.Enabled = true;
- InterpolationCheckbox.Checked = _animation.Interpolate;
+ AnimationStartStopBtn.Visible = true;
+ InterpolationCheckbox.Checked = EditorValue.Interpolate;
TextureIcons.Images.Clear();
- TextureIcons.Images.AddRange(_animation.GetTextures().ToArray());
+ TextureIcons.Images.AddRange(EditorValue.GetTextures().ToArray());
UpdateTreeView();
- animationPictureBox.Image ??= _animation.CreateAnimationImage();
+ animationPictureBox.Image ??= EditorValue.CreateAnimationImage();
- if (_animation.FrameCount > 0)
+ if (EditorValue.FrameCount > 0)
{
animationPictureBox.Image.SelectActiveFrame(FrameDimension.Page, 0);
}
@@ -106,11 +98,11 @@ namespace PckStudio.Forms.Editor
{
frameTreeView.Nodes.Clear();
frameTreeView.Nodes.AddRange(
- _animation.GetFrames()
+ EditorValue.GetFrames()
.Select(frame =>
{
- var imageIndex = _animation.GetTextureIndex(frame.Texture);
- return new TreeNode($"for {frame.Ticks} ticks", imageIndex, imageIndex);
+ var imageIndex = EditorValue.GetTextureIndex(frame.Texture);
+ return new TreeNode($"for {frame.Ticks} tick(s)", imageIndex, imageIndex);
})
.ToArray()
);
@@ -122,7 +114,7 @@ namespace PckStudio.Forms.Editor
{
StopAnimation();
}
- animationPictureBox.Image = _animation.GetFrame(frameTreeView.SelectedNode.Index).Texture;
+ animationPictureBox.Image = EditorValue.GetFrame(frameTreeView.SelectedNode.Index).Texture;
}
private void StopAnimation()
@@ -139,9 +131,9 @@ namespace PckStudio.Forms.Editor
return;
}
- if (_animation.FrameCount > 1)
+ if (EditorValue.FrameCount > 1)
{
- animationPictureBox.Image = _animation.CreateAnimationImage();
+ animationPictureBox.Image = EditorValue.CreateAnimationImage();
animationPictureBox.Start();
AnimationStartStopBtn.Text = "Stop Animation";
}
@@ -166,8 +158,9 @@ namespace PckStudio.Forms.Editor
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
{
- if (!_isSpecialTile && _animation is not null && _animation.FrameCount > 0)
+ if (_editable && EditorValue is not null && EditorValue.FrameCount > 0)
{
+ Save();
DialogResult = DialogResult.OK;
return;
}
@@ -231,7 +224,7 @@ namespace PckStudio.Forms.Editor
{
int draggedIndex = draggedNode.Index;
int targetIndex = targetNode.Index;
- _animation.SwapFrames(draggedIndex, targetIndex);
+ EditorValue.SwapFrames(draggedIndex, targetIndex);
UpdateTreeView();
}
}
@@ -255,8 +248,8 @@ namespace PckStudio.Forms.Editor
private void treeView1_doubleClick(object sender, EventArgs e)
{
- Animation.Frame frame = _animation.GetFrame(frameTreeView.SelectedNode.Index);
- using FrameEditor diag = new FrameEditor(frame.Ticks, _animation.GetTextureIndex(frame.Texture), TextureIcons);
+ Animation.Frame frame = EditorValue.GetFrame(frameTreeView.SelectedNode.Index);
+ using FrameEditor diag = new FrameEditor(frame.Ticks, EditorValue.GetTextureIndex(frame.Texture), TextureIcons);
if (diag.ShowDialog(this) == DialogResult.OK)
{
/* Found a bug here. When passing the frame variable,
@@ -266,7 +259,7 @@ namespace PckStudio.Forms.Editor
* - Matt
*/
- _animation.SetFrame(frameTreeView.SelectedNode.Index, diag.FrameTextureIndex, diag.FrameTime);
+ EditorValue.SetFrame(frameTreeView.SelectedNode.Index, diag.FrameTextureIndex, diag.FrameTime);
UpdateTreeView();
}
}
@@ -277,14 +270,14 @@ namespace PckStudio.Forms.Editor
diag.SaveBtn.Text = "Add";
if (diag.ShowDialog(this) == DialogResult.OK)
{
- _animation.AddFrame(diag.FrameTextureIndex, _isSpecialTile ? Animation.MinimumFrameTime : diag.FrameTime);
+ EditorValue.AddFrame(diag.FrameTextureIndex, _editable ? diag.FrameTime : Animation.MinimumFrameTime);
UpdateTreeView();
}
}
private void removeFrameToolStripMenuItem_Click(object sender, EventArgs e)
{
- if (frameTreeView.SelectedNode is TreeNode t && _animation.RemoveFrame(t.Index))
+ if (frameTreeView.SelectedNode is TreeNode t && EditorValue.RemoveFrame(t.Index))
{
frameTreeView.SelectedNode.Remove();
}
@@ -297,7 +290,7 @@ namespace PckStudio.Forms.Editor
{
if (animationPictureBox.IsPlaying)
animationPictureBox.Stop();
- _animation.SetFrameTicks(diag.Ticks);
+ EditorValue.SetFrameTicks(diag.Ticks);
UpdateTreeView();
}
diag.Dispose();
@@ -334,10 +327,10 @@ namespace PckStudio.Forms.Editor
}
try
{
- var img = Image.FromFile(textureFile);
+ Image img = Image.FromFile(textureFile).ReleaseFromFile();
JObject mcmeta = JObject.Parse(File.ReadAllText(fileDialog.FileName));
Animation javaAnimation = AnimationDeserializer.DefaultDeserializer.DeserializeJavaAnimation(mcmeta, img);
- _animation = javaAnimation;
+ EditorValue = javaAnimation;
LoadAnimationTreeView();
}
catch (JsonException j_ex)
@@ -354,11 +347,11 @@ namespace PckStudio.Forms.Editor
fileDialog.Filter = "Animation Scripts (*.mcmeta)|*.png.mcmeta";
if (fileDialog.ShowDialog(this) == DialogResult.OK)
{
- JObject mcmeta = AnimationSerializer.SerializeJavaAnimation(_animation);
+ JObject mcmeta = AnimationSerializer.SerializeJavaAnimation(EditorValue);
string jsondata = JsonConvert.SerializeObject(mcmeta, Formatting.Indented);
string filename = fileDialog.FileName;
File.WriteAllText(filename, jsondata);
- Image finalTexture = AnimationSerializer.SerializeTexture(_animation);
+ Image finalTexture = AnimationSerializer.SerializeTexture(EditorValue);
// removes ".mcmeta" from filename
string texturePath = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename));
finalTexture.Save(texturePath);
@@ -390,8 +383,8 @@ namespace PckStudio.Forms.Editor
private void InterpolationCheckbox_CheckedChanged(object sender, EventArgs e)
{
- if (_animation is not null)
- _animation.Interpolate = InterpolationCheckbox.Checked;
+ if (EditorValue is not null)
+ EditorValue.Interpolate = InterpolationCheckbox.Checked;
}
private void AnimationEditor_FormClosing(object sender, FormClosingEventArgs e)
@@ -400,7 +393,7 @@ namespace PckStudio.Forms.Editor
{
animationPictureBox.Stop();
}
- if (Settings.Default.AutoSaveChanges)
+ if (!saveToolStripMenuItem1.Available)
{
saveToolStripMenuItem1_Click(sender, EventArgs.Empty);
}
@@ -415,14 +408,14 @@ namespace PckStudio.Forms.Editor
if (fileDialog.ShowDialog(this) != DialogResult.OK)
return;
- var gif = Image.FromFile(fileDialog.FileName);
+ Image gif = Image.FromFile(fileDialog.FileName).ReleaseFromFile();
if (!gif.RawFormat.Equals(ImageFormat.Gif))
{
MessageBox.Show(this, "Selected file is not a gif", "Invalid file", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
- var oldResolution = _animation.GetFrame(0).Texture.Width;
+ var oldResolution = EditorValue.GetFrame(0).Texture.Width;
FrameDimension dimension = new FrameDimension(gif.FrameDimensionsList[0]);
int frameCount = gif.GetFrameCount(dimension);
@@ -436,8 +429,8 @@ namespace PckStudio.Forms.Editor
textures.Add(new Bitmap(gif, oldResolution, oldResolution));
}
- _animation = new Animation(textures, initFramesFromTextures: true);
- _animation.Interpolate = InterpolationCheckbox.Checked;
+ EditorValue = new Animation(textures, initFramesFromTextures: true);
+ EditorValue.Interpolate = InterpolationCheckbox.Checked;
LoadAnimationTreeView();
}
@@ -452,7 +445,7 @@ namespace PckStudio.Forms.Editor
return;
using Image img = Image.FromFile(ofd.FileName);
IEnumerable textures = img.Split(ImageLayoutDirection.Vertical);
- _animation = new Animation(textures, initFramesFromTextures: true);
+ EditorValue = new Animation(textures, initFramesFromTextures: true);
LoadAnimationTreeView();
}
@@ -465,7 +458,7 @@ namespace PckStudio.Forms.Editor
};
if (fileDialog.ShowDialog(this) != DialogResult.OK)
return;
- _animation.CreateAnimationImage().Save(fileDialog.FileName);
+ EditorValue.CreateAnimationImage().Save(fileDialog.FileName);
}
private void frameTimeandTicksToolStripMenuItem_Click(object sender, EventArgs e)
diff --git a/PCK-Studio/Forms/Editor/AudioEditor.cs b/PCK-Studio/Forms/Editor/AudioEditor.cs
index cc37747c..05acd345 100644
--- a/PCK-Studio/Forms/Editor/AudioEditor.cs
+++ b/PCK-Studio/Forms/Editor/AudioEditor.cs
@@ -7,30 +7,23 @@ using System.Windows.Forms;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Diagnostics;
-
-using MetroFramework.Forms;
using NAudio.Wave;
-
-using OMI.Formats.Pck;
-
-using PckStudio.FileFormats;
-using PckStudio.Internal.IO.PckAudio;
using PckStudio.Forms.Additional_Popups;
using PckStudio.Properties;
using PckStudio.External.API.Miles;
-using PckStudio.Extensions;
+using PckStudio.Core.Extensions;
using PckStudio.Internal.App;
+using PckStudio.Controls;
+using PckStudio.Interfaces;
+using PckStudio.Core.FileFormats;
// Audio Editor by MattNL and Miku-666
namespace PckStudio.Forms.Editor
{
- public partial class AudioEditor : MetroForm
+ public partial class AudioEditor : EditorForm
{
public string defaultType = "yes";
- PckAudioFile _audioFile = null;
- PckAsset _audioAsset;
- bool _isLittleEndian = false;
MainForm parent = null;
private static readonly List Categories = new List
@@ -52,7 +45,15 @@ namespace PckStudio.Forms.Editor
*/
};
- private string GetCategoryFromId(PckAudioFile.AudioCategory.EAudioType categoryId)
+ public AudioEditor(PckAudioFile audioFile, ISaveContext saveContext)
+ : base(audioFile, saveContext)
+ {
+ InitializeComponent();
+ saveToolStripMenuItem1.Visible = !saveContext.AutoSave;
+ SetUpTree();
+ }
+
+ private string GetCategoryFromId(PckAudioFile.AudioCategory.EAudioType categoryId)
=> categoryId >= PckAudioFile.AudioCategory.EAudioType.Overworld &&
categoryId <= PckAudioFile.AudioCategory.EAudioType.BuildOff
? Categories[(int)categoryId]
@@ -63,26 +64,12 @@ namespace PckStudio.Forms.Editor
return (PckAudioFile.AudioCategory.EAudioType)Categories.IndexOf(category);
}
- public AudioEditor(PckAsset asset, bool isLittleEndian)
- {
- InitializeComponent();
-
- saveToolStripMenuItem1.Visible = !Settings.Default.AutoSaveChanges;
-
- _isLittleEndian = isLittleEndian;
-
- _audioAsset = asset;
- _audioFile = _audioAsset.GetData(new PckAudioFileReader(isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian));
-
- SetUpTree();
- }
-
public void SetUpTree()
{
treeView1.BeginUpdate();
treeView1.Nodes.Clear();
- foreach (PckAudioFile.AudioCategory category in _audioFile.Categories)
+ foreach (PckAudioFile.AudioCategory category in EditorValue.Categories)
{
// fix songs with directories using backslash instead of forward slash
// Songs with a backslash instead of a forward slash would not play in RPCS3
@@ -92,7 +79,7 @@ namespace PckStudio.Forms.Editor
if (category.AudioType == PckAudioFile.AudioCategory.EAudioType.Creative)
{
if (category.Name == "include_overworld" &&
- _audioFile.TryGetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld, out PckAudioFile.AudioCategory overworldCategory))
+ EditorValue.TryGetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld, out PckAudioFile.AudioCategory overworldCategory))
{
foreach (var name in category.SongNames.ToList())
{
@@ -108,7 +95,7 @@ namespace PckStudio.Forms.Editor
treeNode.Tag = category;
treeView1.Nodes.Add(treeNode);
}
- playOverworldInCreative.Enabled = _audioFile.HasCategory(PckAudioFile.AudioCategory.EAudioType.Creative);
+ playOverworldInCreative.Enabled = EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Creative);
treeView1.EndUpdate();
}
@@ -120,9 +107,9 @@ namespace PckStudio.Forms.Editor
if (!parent.CreateDataFolder())
return;
- string FileName = Path.Combine(parent.GetDataPath(), entry.Text + ".binka");
+ string fileName = Path.Combine(parent.GetDataPath(), entry.Text + ".binka");
- if (File.Exists(FileName))
+ if (File.Exists(fileName))
MessageBox.Show(this, $"\"{entry.Text}.binka\" exists in the \"Data\" folder", "File found");
else
MessageBox.Show(this, $"\"{entry.Text}.binka\" does not exist in the \"Data\" folder. The game will crash when attempting to load this track.", "File missing");
@@ -144,7 +131,7 @@ namespace PckStudio.Forms.Editor
private void addCategoryStripMenuItem_Click(object sender, EventArgs e)
{
- string[] available = Categories.FindAll(str => !_audioFile.HasCategory(GetCategoryId(str))).ToArray();
+ string[] available = Categories.FindAll(str => !EditorValue.HasCategory(GetCategoryId(str))).ToArray();
if (available.Length == 0)
{
MessageBox.Show(this, "There are no more categories that could be added", "All possible categories are used");
@@ -154,8 +141,8 @@ namespace PckStudio.Forms.Editor
if (add.ShowDialog(this) != DialogResult.OK)
return;
- _audioFile.AddCategory(GetCategoryId(add.SelectedItem));
- PckAudioFile.AudioCategory category = _audioFile.GetCategory(GetCategoryId(add.SelectedItem));
+ EditorValue.AddCategory(GetCategoryId(add.SelectedItem));
+ PckAudioFile.AudioCategory category = EditorValue.GetCategory(GetCategoryId(add.SelectedItem));
if (GetCategoryId(add.SelectedItem) == PckAudioFile.AudioCategory.EAudioType.Creative)
{
@@ -194,7 +181,7 @@ namespace PckStudio.Forms.Editor
private void removeCategoryStripMenuItem_Click(object sender, EventArgs e)
{
if (treeView1.SelectedNode is TreeNode main &&
- _audioFile.RemoveCategory(GetCategoryId(treeView1.SelectedNode.Text)))
+ EditorValue.RemoveCategory(GetCategoryId(treeView1.SelectedNode.Text)))
{
if(GetCategoryId(treeView1.SelectedNode.Text) == PckAudioFile.AudioCategory.EAudioType.Creative)
{
@@ -370,18 +357,18 @@ namespace PckStudio.Forms.Editor
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
{
- if (!_audioFile.HasCategory(PckAudioFile.AudioCategory.EAudioType.Overworld) ||
- !_audioFile.HasCategory(PckAudioFile.AudioCategory.EAudioType.Nether) ||
- !_audioFile.HasCategory(PckAudioFile.AudioCategory.EAudioType.End))
+ if (!EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Overworld) ||
+ !EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Nether) ||
+ !EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.End))
{
MessageBox.Show(this, "Your changes were not saved. The game will crash when loading your pack if the Overworld, Nether and End categories don't all exist with at least one valid song.", "Mandatory Categories Missing");
return;
}
- PckAudioFile.AudioCategory overworldCategory = _audioFile.GetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld);
+ PckAudioFile.AudioCategory overworldCategory = EditorValue.GetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld);
bool songs_missing = false;
- foreach (PckAudioFile.AudioCategory category in _audioFile.Categories)
+ foreach (PckAudioFile.AudioCategory category in EditorValue.Categories)
{
if (category.SongNames.Count < 1)
{
@@ -391,8 +378,8 @@ namespace PckStudio.Forms.Editor
foreach(var song in category.SongNames)
{
- string FileName = Path.Combine(parent.GetDataPath(), song + ".binka");
- if (!File.Exists(FileName))
+ string fileName = Path.Combine(parent.GetDataPath(), song + ".binka");
+ if (!File.Exists(fileName))
{
songs_missing = true;
MessageBox.Show(this, "\"" + song + ".binka\" does not exist in the \"Data\" folder. The game will crash when attempting to load this track.", "File missing");
@@ -420,7 +407,7 @@ namespace PckStudio.Forms.Editor
return;
}
- _audioAsset.SetData(new PckAudioFileWriter(_audioFile, _isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian));
+ Save();
DialogResult = DialogResult.OK;
}
@@ -444,7 +431,7 @@ namespace PckStudio.Forms.Editor
if (dr != DialogResult.Yes)
return;
var totalSongList = new List();
- foreach (string song in _audioFile.Categories.SelectMany(cat => cat.SongNames))
+ foreach (string song in EditorValue.Categories.SelectMany(cat => cat.SongNames))
{
Console.WriteLine(song);
totalSongList.Add(song);
@@ -544,7 +531,7 @@ namespace PckStudio.Forms.Editor
return;
var totalSongList = new List();
- foreach (string song in _audioFile.Categories.SelectMany(cat => cat.SongNames))
+ foreach (string song in EditorValue.Categories.SelectMany(cat => cat.SongNames))
{
totalSongList.Add(song);
}
@@ -596,7 +583,7 @@ namespace PckStudio.Forms.Editor
if (!(treeView1.SelectedNode is TreeNode t && t.Tag is PckAudioFile.AudioCategory category))
return;
- string[] available = Categories.FindAll(str => !_audioFile.HasCategory(GetCategoryId(str))).ToArray();
+ string[] available = Categories.FindAll(str => !EditorValue.HasCategory(GetCategoryId(str))).ToArray();
if (available.Length > 0)
{
using ItemSelectionPopUp add = new ItemSelectionPopUp(available);
@@ -604,11 +591,11 @@ namespace PckStudio.Forms.Editor
if (add.ShowDialog(this) != DialogResult.OK)
return;
- _audioFile.RemoveCategory(category.AudioType);
+ EditorValue.RemoveCategory(category.AudioType);
- _audioFile.AddCategory(category.parameterType, GetCategoryId(add.SelectedItem), category.AudioType == PckAudioFile.AudioCategory.EAudioType.Overworld && playOverworldInCreative.Checked ? "include_overworld" : "");
+ EditorValue.AddCategory(category.parameterType, GetCategoryId(add.SelectedItem), category.AudioType == PckAudioFile.AudioCategory.EAudioType.Overworld && playOverworldInCreative.Checked ? "include_overworld" : "");
- PckAudioFile.AudioCategory newCategory = _audioFile.GetCategory(GetCategoryId(add.SelectedItem));
+ PckAudioFile.AudioCategory newCategory = EditorValue.GetCategory(GetCategoryId(add.SelectedItem));
category.SongNames.ForEach(c => newCategory.SongNames.Add(c));
@@ -628,7 +615,7 @@ namespace PckStudio.Forms.Editor
return;
string musicdir = Path.Combine(parent.GetDataPath(), "Music");
Directory.CreateDirectory(musicdir);
- foreach (PckAudioFile.AudioCategory category in _audioFile.Categories)
+ foreach (PckAudioFile.AudioCategory category in EditorValue.Categories)
{
for (var i = 0; i < category.SongNames.Count; i++) // using standard for loop so the list can be modified
{
diff --git a/PCK-Studio/Forms/Editor/BehaviourEditor.Designer.cs b/PCK-Studio/Forms/Editor/BehaviourEditor.Designer.cs
index ed133825..48a4202d 100644
--- a/PCK-Studio/Forms/Editor/BehaviourEditor.Designer.cs
+++ b/PCK-Studio/Forms/Editor/BehaviourEditor.Designer.cs
@@ -299,7 +299,6 @@
this.Style = MetroFramework.MetroColorStyle.Silver;
this.Text = "Behaviour Editor";
this.Theme = MetroFramework.MetroThemeStyle.Dark;
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BehaviourEditor_FormClosing);
this.metroContextMenu1.ResumeLayout(false);
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
diff --git a/PCK-Studio/Forms/Editor/BehaviourEditor.cs b/PCK-Studio/Forms/Editor/BehaviourEditor.cs
index c47957ee..e4cd6a63 100644
--- a/PCK-Studio/Forms/Editor/BehaviourEditor.cs
+++ b/PCK-Studio/Forms/Editor/BehaviourEditor.cs
@@ -1,75 +1,64 @@
using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Diagnostics;
-using System.IO;
using System.Linq;
using System.Windows.Forms;
-using MetroFramework.Forms;
-using PckStudio.Forms.Additional_Popups.EntityForms;
-using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
using OMI.Formats.Behaviour;
-using OMI.Workers.Behaviour;
-using OMI.Formats.Pck;
-using PckStudio.Properties;
-using PckStudio.Internal;
-using PckStudio.Extensions;
-using PckStudio.Internal.Json;
+using PckStudio.Controls;
using PckStudio.Internal.App;
+using PckStudio.Interfaces;
+using PckStudio.Forms.Additional_Popups.EntityForms;
+using PckStudio.Json;
+using PckStudio.Core.Json;
namespace PckStudio.Forms.Editor
{
- public partial class BehaviourEditor : MetroForm
+ // Behaviours File Format research by Miku and MattNL
+ public partial class BehaviourEditor : EditorForm
{
- // Behaviours File Format research by Miku and MattNL
- private readonly PckAsset _asset;
- BehaviourFile _behaviourFile;
+ private const string BehaviourEntryDataType = "behaviours";
+ private readonly List BehaviourData = Entities.BehaviourInfos;
- private readonly List BehaviourData = Entities.BehaviourInfos;
+ public BehaviourEditor(BehaviourFile behaviourFile, ISaveContext saveContext)
+ : base(behaviourFile, saveContext)
+ {
+ InitializeComponent();
- void SetUpTree()
+ saveToolStripMenuItem1.Visible = !saveContext.AutoSave;
+
+ treeView1.ImageList = new ImageList();
+ treeView1.ImageList.Images.AddRange(ApplicationScope.EntityImages);
+ treeView1.ImageList.ColorDepth = ColorDepth.Depth32Bit;
+ SetUpTree();
+ }
+
+ void SetUpTree()
{
treeView1.BeginUpdate();
treeView1.Nodes.Clear();
- foreach (var entry in _behaviourFile.entries)
+ foreach (BehaviourFile.RiderPositionOverride entry in EditorValue.entries)
{
- TreeNode EntryNode = new TreeNode(entry.name);
+ TreeNode entryNode = new TreeNode(entry.name);
- var behaviour = BehaviourData.Find(b => b.InternalName == entry.name);
- EntryNode.Text = behaviour.DisplayName;
- EntryNode.ImageIndex = BehaviourData.IndexOf(behaviour);
- EntryNode.SelectedImageIndex = EntryNode.ImageIndex;
- EntryNode.Tag = entry;
+ EntityInfo behaviour = BehaviourData.Find(b => b.InternalName == entry.name);
+ entryNode.Text = behaviour.DisplayName;
+ entryNode.ImageIndex = BehaviourData.IndexOf(behaviour);
+ entryNode.SelectedImageIndex = entryNode.ImageIndex;
+ entryNode.Tag = entry;
- foreach (var posOverride in entry.overrides)
+ foreach (BehaviourFile.RiderPositionOverride.PositionOverride posOverride in entry.overrides)
{
- TreeNode OverrideNode = new TreeNode("Position Override");
- OverrideNode.Tag = posOverride;
- EntryNode.Nodes.Add(OverrideNode);
- OverrideNode.ImageIndex = 103;
- OverrideNode.SelectedImageIndex = OverrideNode.ImageIndex;
+ TreeNode overrideNode = new TreeNode("Position Override");
+ overrideNode.Tag = posOverride;
+ entryNode.Nodes.Add(overrideNode);
+ overrideNode.ImageIndex = 103;
+ overrideNode.SelectedImageIndex = overrideNode.ImageIndex;
}
- treeView1.Nodes.Add(EntryNode);
+ treeView1.Nodes.Add(entryNode);
}
treeView1.EndUpdate();
}
- public BehaviourEditor(PckAsset asset)
- {
- InitializeComponent();
-
- saveToolStripMenuItem1.Visible = !Settings.Default.AutoSaveChanges;
-
- _asset = asset;
- _behaviourFile = asset.GetData(new BehavioursReader());
-
- treeView1.ImageList = new ImageList();
- treeView1.ImageList.Images.AddRange(ApplicationScope.EntityImages);
- treeView1.ImageList.ColorDepth = ColorDepth.Depth32Bit;
- SetUpTree();
- }
-
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if (treeView1.SelectedNode is null)
@@ -149,13 +138,13 @@ namespace PckStudio.Forms.Editor
if (!(treeView1.SelectedNode.Tag is BehaviourFile.RiderPositionOverride entry))
return;
- var diag = new AddEntry("behaviours", ApplicationScope.EntityImages);
+ var diag = new AddEntry(BehaviourEntryDataType, ApplicationScope.EntityImages);
if (diag.ShowDialog(this) == DialogResult.OK)
{
if (string.IsNullOrEmpty(diag.SelectedEntity))
return;
- if (_behaviourFile.entries.FindAll(behaviour => behaviour.name == diag.SelectedEntity).Count() > 0)
+ if (EditorValue.entries.FindAll(behaviour => behaviour.name == diag.SelectedEntity).Count() > 0)
{
MessageBox.Show(this, "You cannot have two entries for one entity. Please use the \"Add New Position Override\" tool to add multiple overrides for entities", "Error", MessageBoxButtons.OK);
return;
@@ -186,41 +175,46 @@ namespace PckStudio.Forms.Editor
if (treeView1.SelectedNode.Tag is BehaviourFile.RiderPositionOverride.PositionOverride)
treeView1.SelectedNode = treeView1.SelectedNode.Parent;
- if (treeView1.SelectedNode.Tag is BehaviourFile.RiderPositionOverride)
+ if (treeView1.SelectedNode.Tag is BehaviourFile.RiderPositionOverride positionOverride)
{
- TreeNode OverrideNode = new TreeNode("Position Override");
- OverrideNode.Tag = new BehaviourFile.RiderPositionOverride.PositionOverride();
- OverrideNode.ImageIndex = 103;
- OverrideNode.SelectedImageIndex = 103;
- treeView1.SelectedNode.Nodes.Add(OverrideNode);
- }
+ BehaviourFile.RiderPositionOverride.PositionOverride newPositionOverride = new BehaviourFile.RiderPositionOverride.PositionOverride();
+ TreeNode overrideNode = new TreeNode("Position Override");
+ overrideNode.Tag = newPositionOverride;
+ overrideNode.ImageIndex = 103;
+ overrideNode.SelectedImageIndex = 103;
+ treeView1.SelectedNode.Nodes.Add(overrideNode);
+ positionOverride.overrides.Add(newPositionOverride);
+ }
}
private void addNewEntryToolStripMenuItem_Click(object sender, EventArgs e)
{
- var diag = new AddEntry("behaviours", ApplicationScope.EntityImages);
+ var diag = new AddEntry(BehaviourEntryDataType, ApplicationScope.EntityImages);
if(diag.ShowDialog(this) == DialogResult.OK)
{
if (string.IsNullOrEmpty(diag.SelectedEntity))
return;
- if (_behaviourFile.entries.FindAll(behaviour => behaviour.name == diag.SelectedEntity).Count() > 0)
+ if (EditorValue.entries.FindAll(behaviour => behaviour.name == diag.SelectedEntity).Count() > 0)
{
MessageBox.Show(this, "You cannot have two entries for one entity. Please use the \"Add New Position Override\" tool to add multiple overrides for entities", "Error", MessageBoxButtons.OK);
return;
}
- BehaviourFile.RiderPositionOverride NewOverride = new BehaviourFile.RiderPositionOverride(diag.SelectedEntity);
+ BehaviourFile.RiderPositionOverride newOverride = new BehaviourFile.RiderPositionOverride(diag.SelectedEntity);
+ EditorValue.entries.Add(newOverride);
- TreeNode NewOverrideNode = new TreeNode(NewOverride.name);
- NewOverrideNode.Tag = NewOverride;
+ TreeNode newOverrideNode = new TreeNode(newOverride.name);
+ newOverrideNode.Tag = newOverride;
- EntityInfo behaviour = BehaviourData.Find(b => b.InternalName == NewOverride.name);
- NewOverrideNode.Text = behaviour.DisplayName;
- NewOverrideNode.ImageIndex = BehaviourData.IndexOf(behaviour);
- NewOverrideNode.SelectedImageIndex = NewOverrideNode.ImageIndex;
+ // potentially null de-reference
+ EntityInfo behaviour = BehaviourData.Find(b => b.InternalName == newOverride.name);
- treeView1.Nodes.Add(NewOverrideNode);
- treeView1.SelectedNode = NewOverrideNode;
+ newOverrideNode.Text = behaviour.DisplayName;
+ newOverrideNode.ImageIndex = BehaviourData.IndexOf(behaviour);
+ newOverrideNode.SelectedImageIndex = newOverrideNode.ImageIndex;
+
+ treeView1.Nodes.Add(newOverrideNode);
+ treeView1.SelectedNode = newOverrideNode;
addNewPositionOverrideToolStripMenuItem_Click(sender, e); // adds a Position Override to the new Override
}
@@ -239,36 +233,8 @@ namespace PckStudio.Forms.Editor
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
{
- _behaviourFile = new BehaviourFile();
- foreach (TreeNode node in treeView1.Nodes)
- {
- if(node.Tag is BehaviourFile.RiderPositionOverride entry)
- {
- entry.overrides.Clear();
- Console.WriteLine();
- foreach (TreeNode overrideNode in node.Nodes)
- {
- if(overrideNode.Tag is BehaviourFile.RiderPositionOverride.PositionOverride overrideEntry)
- {
- entry.overrides.Add(overrideEntry);
- }
- }
-
- _behaviourFile.entries.Add(entry);
- }
- }
-
- _asset.SetData(new BehavioursWriter(_behaviourFile));
-
+ Save();
DialogResult = DialogResult.OK;
}
-
- private void BehaviourEditor_FormClosing(object sender, FormClosingEventArgs e)
- {
- if (Settings.Default.AutoSaveChanges)
- {
- saveToolStripMenuItem1_Click(sender, EventArgs.Empty);
- }
- }
}
}
diff --git a/PCK-Studio/Forms/Editor/BoxEditor.cs b/PCK-Studio/Forms/Editor/BoxEditor.cs
index 8af249bf..89443617 100644
--- a/PCK-Studio/Forms/Editor/BoxEditor.cs
+++ b/PCK-Studio/Forms/Editor/BoxEditor.cs
@@ -1,16 +1,17 @@
using System;
using System.Windows.Forms;
-using PckStudio.Internal;
+using PckStudio.Core.Skin;
using PckStudio.Properties;
namespace PckStudio.Forms.Editor
{
public partial class BoxEditor : MetroFramework.Forms.MetroForm
{
- public string Result;
+ private SkinBOX result;
+ public SkinBOX Result => result;
- public BoxEditor(string box, bool hasInflation)
- : this(SkinBOX.FromString(box), hasInflation)
+ public BoxEditor(string formattedBoxString, bool hasInflation)
+ : this(SkinBOX.FromString(formattedBoxString), hasInflation)
{
}
@@ -43,14 +44,14 @@ namespace PckStudio.Forms.Editor
private void saveButton_Click(object sender, EventArgs e)
{
- Result =
+ result = SkinBOX.FromString(
$"{parentComboBox.SelectedItem} " +
$"{PosXUpDown.Value} {PosYUpDown.Value} {PosZUpDown.Value} " +
$"{SizeXUpDown.Value} {SizeYUpDown.Value} {SizeZUpDown.Value} " +
$"{uvXUpDown.Value} {uvYUpDown.Value} " +
$"{Convert.ToInt32(armorCheckBox.Checked)} " +
$"{Convert.ToInt32(mirrorCheckBox.Checked)} " +
- $"{inflationUpDown.Value}";
+ $"{inflationUpDown.Value}");
DialogResult = DialogResult.OK;
}
diff --git a/PCK-Studio/Forms/Editor/COLEditor.Designer.cs b/PCK-Studio/Forms/Editor/COLEditor.Designer.cs
index 30338f00..ef808db5 100644
--- a/PCK-Studio/Forms/Editor/COLEditor.Designer.cs
+++ b/PCK-Studio/Forms/Editor/COLEditor.Designer.cs
@@ -547,7 +547,6 @@ namespace PckStudio.Forms.Editor
this.Name = "COLEditor";
this.Style = MetroFramework.MetroColorStyle.Silver;
this.Theme = MetroFramework.MetroThemeStyle.Dark;
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.COLEditor_FormClosing);
this.metroPanel1.ResumeLayout(false);
this.metroPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.blueUpDown)).EndInit();
diff --git a/PCK-Studio/Forms/Editor/COLEditor.cs b/PCK-Studio/Forms/Editor/COLEditor.cs
index 73966b8a..b36c01a7 100644
--- a/PCK-Studio/Forms/Editor/COLEditor.cs
+++ b/PCK-Studio/Forms/Editor/COLEditor.cs
@@ -8,32 +8,39 @@ using MetroFramework.Forms;
using OMI.Formats.Color;
using OMI.Formats.Pck;
using OMI.Workers.Color;
-using PckStudio.Extensions;
+using PckStudio.Core.Extensions;
using PckStudio.Properties;
+using PckStudio.Controls;
+using PckStudio.Interfaces;
+using System.Collections.ObjectModel;
namespace PckStudio.Forms.Editor
{
- public partial class COLEditor : MetroForm
+ public partial class COLEditor : EditorForm
{
ColorContainer _defaultColourfile;
- ColorContainer _colourfile;
string _clipboard_color = "#FFFFFF";
- private readonly PckAsset _asset;
-
List colorCache = new List();
List waterCache = new List();
List underwaterCache = new List();
List fogCache = new List();
- public COLEditor(PckAsset asset)
+ private static readonly ICollection PS4Biomes = new List
+ {
+ "bamboo_jungle",
+ "bamboo_jungle_hills",
+ "mesa_mutated",
+ "mega_spruce_taiga_mutated",
+ "mega_taiga_mutated"
+ };
+
+ public COLEditor(ColorContainer colorContainer, ISaveContext saveContext)
+ : base(colorContainer, saveContext)
{
InitializeComponent();
- saveToolStripMenuItem1.Visible = !Settings.Default.AutoSaveChanges;
-
- _asset = asset;
- _colourfile = asset.GetData(new COLFileReader());
+ saveToolStripMenuItem1.Visible = !saveContext.AutoSave;
TU12ToolStripMenuItem.Click += (sender, e) => SetUpDefaultFile(sender, e, 0);
TU13ToolStripMenuItem.Click += (sender, e) => SetUpDefaultFile(sender, e, 1);
@@ -111,9 +118,9 @@ namespace PckStudio.Forms.Editor
underwaterTreeView.Nodes.Clear();
fogTreeView.Nodes.Clear();
- ColorContainer temp = targetVersion ? _defaultColourfile : _colourfile;
+ ColorContainer temp = targetVersion ? _defaultColourfile : EditorValue;
- List CurrentEntries = new List();
+ List currentEntries = new List();
colorCache.Clear();
fogCache.Clear();
@@ -123,33 +130,33 @@ namespace PckStudio.Forms.Editor
// fixes the duplicate entry bug
if (targetVersion)
{
- foreach(ColorContainer.Color col in _colourfile.Colors)
+ foreach(ColorContainer.Color col in EditorValue.Colors)
{
if (_defaultColourfile.Colors.Find(c => c.Name == col.Name) == null)
continue;
- CurrentEntries.Add(col.Name);
+ currentEntries.Add(col.Name);
AddEntry(colorTreeView, colorCache, col.Name, col);
}
}
foreach (ColorContainer.Color col in temp.Colors)
{
- ColorContainer.Color entry = _colourfile.Colors.Find(color => color.Name == col.Name);
- if (CurrentEntries.Contains(col.Name))
+ ColorContainer.Color entry = EditorValue.Colors.Find(color => color.Name == col.Name);
+ if (currentEntries.Contains(col.Name))
continue;
ColorContainer.Color color = entry ?? col;
AddEntry(colorTreeView, colorCache, color.Name, color);
}
- CurrentEntries.Clear();
+ currentEntries.Clear();
// fixes the duplicate entry bug
if (targetVersion)
{
- foreach (ColorContainer.WaterColor col in _colourfile.WaterColors)
+ foreach (ColorContainer.WaterColor col in EditorValue.WaterColors)
{
if (_defaultColourfile.WaterColors.Find(c => c.Name == col.Name) == null)
continue;
- ColorContainer.WaterColor entry = _colourfile.WaterColors.Find(color => color.Name == col.Name);
+ ColorContainer.WaterColor entry = EditorValue.WaterColors.Find(color => color.Name == col.Name);
ColorContainer.WaterColor color = entry ?? col;
AddEntry(waterTreeView, waterCache, color.Name, color);
AddEntry(underwaterTreeView, underwaterCache, color.Name, color);
@@ -159,8 +166,8 @@ namespace PckStudio.Forms.Editor
foreach (ColorContainer.WaterColor col in temp.WaterColors)
{
- ColorContainer.WaterColor entry = _colourfile.WaterColors.Find(color => color.Name == col.Name);
- if (CurrentEntries.Contains(col.Name))
+ ColorContainer.WaterColor entry = EditorValue.WaterColors.Find(color => color.Name == col.Name);
+ if (currentEntries.Contains(col.Name))
continue;
ColorContainer.WaterColor color = entry ?? col;
AddEntry(waterTreeView, waterCache, color.Name, color);
@@ -201,14 +208,14 @@ namespace PckStudio.Forms.Editor
fogTreeView.SelectedNode = null;
var colorEntry = (ColorContainer.Color)colorTreeView.SelectedNode.Tag;
- var color = colorEntry.ColorPallette.ToArgb();
+ Color color = colorEntry.ColorPallette;
SetUpValueChanged(false);
alphaUpDown.Visible = false;
alphaLabel.Visible = false;
- redUpDown.Value = color >> 16 & 0xff;
- greenUpDown.Value = color >> 8 & 0xff;
- blueUpDown.Value = color & 0xff;
- pictureBox1.BackColor = Color.FromArgb(0xff << 24 | color);
+ redUpDown.Value = color.R;
+ greenUpDown.Value = color.G;
+ blueUpDown.Value = color.B;
+ pictureBox1.BackColor = Color.FromArgb(0xff, color);
colorTextbox.Text = ColorTranslator.ToHtml(colorEntry.ColorPallette).TrimStart('#');
SetUpValueChanged(true);
}
@@ -226,15 +233,17 @@ namespace PckStudio.Forms.Editor
fogTreeView.SelectedNode = null;
var colorEntry = (ColorContainer.WaterColor)waterTreeView.SelectedNode.Tag;
- int color = colorEntry.SurfaceColor.ToArgb();
+ Color color = colorEntry.SurfaceColor;
SetUpValueChanged(false);
+
+ alphaUpDown.Value = color.A;
+ redUpDown.Value = color.R;
+ greenUpDown.Value = color.G;
+ blueUpDown.Value = color.B;
+
alphaUpDown.Enabled = true;
alphaUpDown.Visible = true;
alphaLabel.Visible = true;
- alphaUpDown.Value = color >> 24 & 0xff;
- redUpDown.Value = color >> 16 & 0xff;
- greenUpDown.Value = color >> 8 & 0xff;
- blueUpDown.Value = color & 0xff;
pictureBox1.BackColor = colorEntry.SurfaceColor;
colorTextbox.Text = ColorTranslator.ToHtml(colorEntry.SurfaceColor).TrimStart('#');
SetUpValueChanged(true);
@@ -253,14 +262,14 @@ namespace PckStudio.Forms.Editor
fogTreeView.SelectedNode = null;
var colorEntry = (ColorContainer.WaterColor)underwaterTreeView.SelectedNode.Tag;
- int color = colorEntry.UnderwaterColor.ToArgb();
+ Color color = colorEntry.UnderwaterColor;
SetUpValueChanged(false);
alphaUpDown.Visible = false;
alphaLabel.Visible = false;
- redUpDown.Value = color >> 16 & 0xff;
- greenUpDown.Value = color >> 8 & 0xff;
- blueUpDown.Value = color & 0xff;
- pictureBox1.BackColor = Color.FromArgb(255, Color.FromArgb(0xff << 24 | color));
+ redUpDown.Value = color.R;
+ greenUpDown.Value = color.G;
+ blueUpDown.Value = color.B;
+ pictureBox1.BackColor = Color.FromArgb(0xff, color);
colorTextbox.Text = ColorTranslator.ToHtml(colorEntry.UnderwaterColor).TrimStart('#');
SetUpValueChanged(true);
}
@@ -278,22 +287,21 @@ namespace PckStudio.Forms.Editor
underwaterTreeView.SelectedNode = null;
var colorEntry = (ColorContainer.WaterColor)fogTreeView.SelectedNode.Tag;
- int color = colorEntry.FogColor.ToArgb();
+ Color color = colorEntry.FogColor;
SetUpValueChanged(false);
alphaUpDown.Visible = false;
alphaLabel.Visible = false;
- redUpDown.Value = color >> 16 & 0xff;
- greenUpDown.Value = color >> 8 & 0xff;
- blueUpDown.Value = color & 0xff;
- pictureBox1.BackColor = Color.FromArgb(255, Color.FromArgb(0xff << 24 | color));
+ redUpDown.Value = color.R;
+ greenUpDown.Value = color.G;
+ blueUpDown.Value = color.B;
+ pictureBox1.BackColor = Color.FromArgb(0xff, color);
colorTextbox.Text = ColorTranslator.ToHtml(colorEntry.FogColor).TrimStart('#');
SetUpValueChanged(true);
}
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
{
- _asset.SetData(new COLFileWriter(_colourfile));
-
+ Save();
DialogResult = DialogResult.OK;
}
@@ -485,14 +493,14 @@ namespace PckStudio.Forms.Editor
}
else
{
- ColorContainer.WaterColor WaterEntry = _defaultColourfile.WaterColors.Find(color => color.Name == node.Text);
+ ColorContainer.WaterColor waterEntry = _defaultColourfile.WaterColors.Find(color => color.Name == node.Text);
- if (WaterEntry == null)
+ if (waterEntry == null)
return;
color =
- tab == waterTab ? WaterEntry.SurfaceColor :
- tab == underwaterTab ? WaterEntry.UnderwaterColor : WaterEntry.FogColor;
+ tab == waterTab ? waterEntry.SurfaceColor :
+ tab == underwaterTab ? waterEntry.UnderwaterColor : waterEntry.FogColor;
if (tab == waterTab)
{
@@ -523,52 +531,52 @@ namespace PckStudio.Forms.Editor
fogTreeView.Nodes.Clear();
if (!string.IsNullOrEmpty(metroTextBox1.Text))
{
- foreach (TreeNode _node in colorCache)
+ foreach (TreeNode node in colorCache)
{
- if (_node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
+ if (node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
{
- colorTreeView.Nodes.Add((TreeNode)_node.Clone());
+ colorTreeView.Nodes.Add((TreeNode)node.Clone());
}
}
- foreach (TreeNode _node in waterCache)
+ foreach (TreeNode node in waterCache)
{
- if (_node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
+ if (node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
{
- waterTreeView.Nodes.Add((TreeNode)_node.Clone());
+ waterTreeView.Nodes.Add((TreeNode)node.Clone());
}
}
- foreach (TreeNode _node in underwaterCache)
+ foreach (TreeNode node in underwaterCache)
{
- if (_node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
+ if (node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
{
- underwaterTreeView.Nodes.Add((TreeNode)_node.Clone());
+ underwaterTreeView.Nodes.Add((TreeNode)node.Clone());
}
}
- foreach (TreeNode _node in fogCache)
+ foreach (TreeNode node in fogCache)
{
- if (_node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
+ if (node.Text.ToLower().Contains(metroTextBox1.Text.ToLower()))
{
- fogTreeView.Nodes.Add((TreeNode)_node.Clone());
+ fogTreeView.Nodes.Add((TreeNode)node.Clone());
}
}
}
else
{
- foreach (TreeNode _node in colorCache)
+ foreach (TreeNode node in colorCache)
{
- colorTreeView.Nodes.Add((TreeNode)_node.Clone());
+ colorTreeView.Nodes.Add((TreeNode)node.Clone());
}
- foreach (TreeNode _node in waterCache)
+ foreach (TreeNode node in waterCache)
{
- waterTreeView.Nodes.Add((TreeNode)_node.Clone());
+ waterTreeView.Nodes.Add((TreeNode)node.Clone());
}
- foreach (TreeNode _node in underwaterCache)
+ foreach (TreeNode node in underwaterCache)
{
- underwaterTreeView.Nodes.Add((TreeNode)_node.Clone());
+ underwaterTreeView.Nodes.Add((TreeNode)node.Clone());
}
- foreach (TreeNode _node in fogCache)
+ foreach (TreeNode node in fogCache)
{
- fogTreeView.Nodes.Add((TreeNode)_node.Clone());
+ fogTreeView.Nodes.Add((TreeNode)node.Clone());
}
}
//enables redrawing tree after all objects have been added
@@ -588,14 +596,6 @@ namespace PckStudio.Forms.Editor
colorTextbox.Text = _clipboard_color;
}
- private void COLEditor_FormClosing(object sender, FormClosingEventArgs e)
- {
- if (Settings.Default.AutoSaveChanges)
- {
- saveToolStripMenuItem1_Click(sender, EventArgs.Empty);
- }
- }
-
private void colorTextbox_KeyPress(object sender, KeyPressEventArgs e)
{
string hexCheck = "0123456789abcdefABCDEF\b";
@@ -605,21 +605,12 @@ namespace PckStudio.Forms.Editor
private void stripPS4BiomesToolStripMenuItem_Click(object sender, EventArgs e)
{
- if(_colourfile.WaterColors.Count > 0)
+ if(EditorValue.WaterColors.Count > 0)
{
- List PS4Biomes = new List
- {
- "bamboo_jungle",
- "bamboo_jungle_hills",
- "mesa_mutated",
- "mega_spruce_taiga_mutated",
- "mega_taiga_mutated"
- };
-
- foreach (ColorContainer.WaterColor col in _colourfile.WaterColors.ToList())
+ foreach (ColorContainer.WaterColor col in EditorValue.WaterColors.ToList())
{
if (PS4Biomes.Contains(col.Name))
- _colourfile.WaterColors.Remove(col);
+ EditorValue.WaterColors.Remove(col);
}
SetUpTable(false);
@@ -640,12 +631,12 @@ namespace PckStudio.Forms.Editor
entry.Name = prompt.NewText;
entry.ColorPallette = Color.FromArgb(0xFFFFFF);
- if(_colourfile.Colors.Find(c => c.Name == entry.Name) != null)
+ if(EditorValue.Colors.Find(c => c.Name == entry.Name) != null)
{
MessageBox.Show(this, $"\"{entry.Name}\" already exists in this color table", "Color not added");
}
- _colourfile.Colors.Add(entry);
+ EditorValue.Colors.Add(entry);
AddEntry(colorTreeView, colorCache, entry.Name, entry);
}
}
@@ -659,7 +650,7 @@ namespace PckStudio.Forms.Editor
&& entry != null
&& entry.Tag is ColorContainer.Color color)
{
- _colourfile.Colors.Remove(color);
+ EditorValue.Colors.Remove(color);
RemoveEntry(entry, colorCache);
}
}
diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs
new file mode 100644
index 00000000..6f4df1c4
--- /dev/null
+++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs
@@ -0,0 +1,446 @@
+namespace PckStudio.Forms.Editor
+{
+ partial class CustomSkinEditor
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.GroupBox groupBox1;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomSkinEditor));
+ this.sizeLabel = new System.Windows.Forms.Label();
+ this.positionLabel = new System.Windows.Forms.Label();
+ this.uvLabel = new System.Windows.Forms.Label();
+ this.importTextureButton = new MetroFramework.Controls.MetroButton();
+ this.exportTextureButton = new MetroFramework.Controls.MetroButton();
+ this.skinPartTabContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.createToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.cloneToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.generateUvTextureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.buttonDone = new MetroFramework.Controls.MetroButton();
+ this.importSkinButton = new MetroFramework.Controls.MetroButton();
+ this.exportSkinButton = new MetroFramework.Controls.MetroButton();
+ this.outlineColorButton = new MetroFramework.Controls.MetroButton();
+ this.generateTextureCheckBox = new MetroFramework.Controls.MetroCheckBox();
+ this.showArmorCheckbox = new MetroFramework.Controls.MetroCheckBox();
+ this.skinPartListBox = new System.Windows.Forms.ListBox();
+ this.captureScreenshotButton = new MetroFramework.Controls.MetroButton();
+ this.showToolsCheckBox = new MetroFramework.Controls.MetroCheckBox();
+ this.skinNameLabel = new MetroFramework.Controls.MetroLabel();
+ this.metroTabControl1 = new MetroFramework.Controls.MetroTabControl();
+ this.skinPartsTabPage = new System.Windows.Forms.TabPage();
+ this.skinOffsetsTabPage = new System.Windows.Forms.TabPage();
+ this.offsetListBox = new System.Windows.Forms.ListBox();
+ this.offsetTabContextMenu = new MetroFramework.Controls.MetroContextMenu(this.components);
+ this.addOffsetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.removeOffsetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.renderer3D1 = new PckStudio.Rendering.SkinRenderer();
+ this.uvPictureBox = new PckStudio.ToolboxItems.InterpolationPictureBox();
+ this.centerSelectionCheckbox = new MetroFramework.Controls.MetroCheckBox();
+ this.textureSizeLabel = new System.Windows.Forms.Label();
+ this.renderSettingsButton = new MetroFramework.Controls.MetroButton();
+ this.exportTemplateButton = new MetroFramework.Controls.MetroButton();
+ this.animEditorButton = new MetroFramework.Controls.MetroButton();
+ groupBox1 = new System.Windows.Forms.GroupBox();
+ groupBox1.SuspendLayout();
+ this.skinPartTabContextMenu.SuspendLayout();
+ this.metroTabControl1.SuspendLayout();
+ this.skinPartsTabPage.SuspendLayout();
+ this.skinOffsetsTabPage.SuspendLayout();
+ this.offsetTabContextMenu.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.uvPictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // groupBox1
+ //
+ resources.ApplyResources(groupBox1, "groupBox1");
+ groupBox1.Controls.Add(this.sizeLabel);
+ groupBox1.Controls.Add(this.positionLabel);
+ groupBox1.Controls.Add(this.uvLabel);
+ groupBox1.ForeColor = System.Drawing.SystemColors.Control;
+ groupBox1.Name = "groupBox1";
+ groupBox1.TabStop = false;
+ //
+ // sizeLabel
+ //
+ resources.ApplyResources(this.sizeLabel, "sizeLabel");
+ this.sizeLabel.ForeColor = System.Drawing.Color.White;
+ this.sizeLabel.Name = "sizeLabel";
+ //
+ // positionLabel
+ //
+ resources.ApplyResources(this.positionLabel, "positionLabel");
+ this.positionLabel.ForeColor = System.Drawing.Color.White;
+ this.positionLabel.Name = "positionLabel";
+ //
+ // uvLabel
+ //
+ resources.ApplyResources(this.uvLabel, "uvLabel");
+ this.uvLabel.ForeColor = System.Drawing.Color.White;
+ this.uvLabel.Name = "uvLabel";
+ //
+ // importTextureButton
+ //
+ resources.ApplyResources(this.importTextureButton, "importTextureButton");
+ this.importTextureButton.ForeColor = System.Drawing.Color.White;
+ this.importTextureButton.Name = "importTextureButton";
+ this.importTextureButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.importTextureButton.UseSelectable = true;
+ this.importTextureButton.Click += new System.EventHandler(this.importTextureButton_Click);
+ //
+ // exportTextureButton
+ //
+ resources.ApplyResources(this.exportTextureButton, "exportTextureButton");
+ this.exportTextureButton.ForeColor = System.Drawing.Color.White;
+ this.exportTextureButton.Name = "exportTextureButton";
+ this.exportTextureButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.exportTextureButton.UseSelectable = true;
+ this.exportTextureButton.Click += new System.EventHandler(this.exportTextureButton_Click);
+ //
+ // skinPartTabContextMenu
+ //
+ this.skinPartTabContextMenu.ImageScalingSize = new System.Drawing.Size(20, 20);
+ this.skinPartTabContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.createToolStripMenuItem,
+ this.cloneToolStripMenuItem,
+ this.deleteToolStripMenuItem,
+ this.generateUvTextureToolStripMenuItem});
+ this.skinPartTabContextMenu.Name = "contextMenuStrip1";
+ resources.ApplyResources(this.skinPartTabContextMenu, "skinPartTabContextMenu");
+ //
+ // createToolStripMenuItem
+ //
+ resources.ApplyResources(this.createToolStripMenuItem, "createToolStripMenuItem");
+ this.createToolStripMenuItem.Name = "createToolStripMenuItem";
+ this.createToolStripMenuItem.Click += new System.EventHandler(this.createToolStripMenuItem_Click);
+ //
+ // cloneToolStripMenuItem
+ //
+ resources.ApplyResources(this.cloneToolStripMenuItem, "cloneToolStripMenuItem");
+ this.cloneToolStripMenuItem.Name = "cloneToolStripMenuItem";
+ this.cloneToolStripMenuItem.Click += new System.EventHandler(this.cloneToolStripMenuItem_Click);
+ //
+ // deleteToolStripMenuItem
+ //
+ resources.ApplyResources(this.deleteToolStripMenuItem, "deleteToolStripMenuItem");
+ this.deleteToolStripMenuItem.Name = "deleteToolStripMenuItem";
+ this.deleteToolStripMenuItem.Click += new System.EventHandler(this.deleteToolStripMenuItem_Click);
+ //
+ // generateUvTextureToolStripMenuItem
+ //
+ resources.ApplyResources(this.generateUvTextureToolStripMenuItem, "generateUvTextureToolStripMenuItem");
+ this.generateUvTextureToolStripMenuItem.Name = "generateUvTextureToolStripMenuItem";
+ this.generateUvTextureToolStripMenuItem.Click += new System.EventHandler(this.generateUvTextureToolStripMenuItem_Click);
+ //
+ // buttonDone
+ //
+ resources.ApplyResources(this.buttonDone, "buttonDone");
+ this.buttonDone.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.buttonDone.ForeColor = System.Drawing.Color.White;
+ this.buttonDone.Name = "buttonDone";
+ this.buttonDone.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.buttonDone.UseSelectable = true;
+ this.buttonDone.Click += new System.EventHandler(this.buttonDone_Click);
+ //
+ // importSkinButton
+ //
+ resources.ApplyResources(this.importSkinButton, "importSkinButton");
+ this.importSkinButton.ForeColor = System.Drawing.Color.White;
+ this.importSkinButton.Name = "importSkinButton";
+ this.importSkinButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.importSkinButton.UseSelectable = true;
+ this.importSkinButton.Click += new System.EventHandler(this.importSkinButton_Click);
+ //
+ // exportSkinButton
+ //
+ resources.ApplyResources(this.exportSkinButton, "exportSkinButton");
+ this.exportSkinButton.ForeColor = System.Drawing.Color.White;
+ this.exportSkinButton.Name = "exportSkinButton";
+ this.exportSkinButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.exportSkinButton.UseSelectable = true;
+ this.exportSkinButton.Click += new System.EventHandler(this.exportSkinButton_Click);
+ //
+ // outlineColorButton
+ //
+ resources.ApplyResources(this.outlineColorButton, "outlineColorButton");
+ this.outlineColorButton.ForeColor = System.Drawing.Color.White;
+ this.outlineColorButton.Name = "outlineColorButton";
+ this.outlineColorButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.outlineColorButton.UseSelectable = true;
+ this.outlineColorButton.Click += new System.EventHandler(this.outlineColorButton_Click);
+ //
+ // generateTextureCheckBox
+ //
+ resources.ApplyResources(this.generateTextureCheckBox, "generateTextureCheckBox");
+ this.generateTextureCheckBox.Name = "generateTextureCheckBox";
+ this.generateTextureCheckBox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.generateTextureCheckBox.UseSelectable = true;
+ //
+ // showArmorCheckbox
+ //
+ resources.ApplyResources(this.showArmorCheckbox, "showArmorCheckbox");
+ this.showArmorCheckbox.Name = "showArmorCheckbox";
+ this.showArmorCheckbox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.showArmorCheckbox.UseSelectable = true;
+ this.showArmorCheckbox.CheckedChanged += new System.EventHandler(this.showArmorCheckbox_CheckedChanged);
+ //
+ // skinPartListBox
+ //
+ this.skinPartListBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.skinPartListBox.ContextMenuStrip = this.skinPartTabContextMenu;
+ resources.ApplyResources(this.skinPartListBox, "skinPartListBox");
+ this.skinPartListBox.FormattingEnabled = true;
+ this.skinPartListBox.Name = "skinPartListBox";
+ this.skinPartListBox.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
+ this.skinPartListBox.Tag = "";
+ this.skinPartListBox.MouseClick += new System.Windows.Forms.MouseEventHandler(this.skinPartListBox_MouseClick);
+ this.skinPartListBox.SelectedIndexChanged += new System.EventHandler(this.skinPartListBox_SelectedIndexChanged);
+ this.skinPartListBox.DoubleClick += new System.EventHandler(this.skinPartListBox_DoubleClick);
+ this.skinPartListBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.skinPartListBox_KeyUp);
+ //
+ // 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;
+ //
+ // skinNameLabel
+ //
+ resources.ApplyResources(this.skinNameLabel, "skinNameLabel");
+ this.skinNameLabel.Name = "skinNameLabel";
+ this.skinNameLabel.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // metroTabControl1
+ //
+ resources.ApplyResources(this.metroTabControl1, "metroTabControl1");
+ this.metroTabControl1.Controls.Add(this.skinPartsTabPage);
+ this.metroTabControl1.Controls.Add(this.skinOffsetsTabPage);
+ this.metroTabControl1.Multiline = true;
+ this.metroTabControl1.Name = "metroTabControl1";
+ this.metroTabControl1.SelectedIndex = 0;
+ this.metroTabControl1.Style = MetroFramework.MetroColorStyle.Pink;
+ this.metroTabControl1.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.metroTabControl1.UseSelectable = true;
+ //
+ // skinPartsTabPage
+ //
+ this.skinPartsTabPage.Controls.Add(this.skinPartListBox);
+ resources.ApplyResources(this.skinPartsTabPage, "skinPartsTabPage");
+ this.skinPartsTabPage.Name = "skinPartsTabPage";
+ //
+ // skinOffsetsTabPage
+ //
+ this.skinOffsetsTabPage.Controls.Add(this.offsetListBox);
+ resources.ApplyResources(this.skinOffsetsTabPage, "skinOffsetsTabPage");
+ this.skinOffsetsTabPage.Name = "skinOffsetsTabPage";
+ //
+ // offsetListBox
+ //
+ this.offsetListBox.ContextMenuStrip = this.offsetTabContextMenu;
+ resources.ApplyResources(this.offsetListBox, "offsetListBox");
+ this.offsetListBox.FormattingEnabled = true;
+ this.offsetListBox.Name = "offsetListBox";
+ this.offsetListBox.DoubleClick += new System.EventHandler(this.offsetListBox_DoubleClick);
+ //
+ // offsetTabContextMenu
+ //
+ this.offsetTabContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.addOffsetToolStripMenuItem,
+ this.removeOffsetToolStripMenuItem});
+ this.offsetTabContextMenu.Name = "offsetTabContextMenu";
+ resources.ApplyResources(this.offsetTabContextMenu, "offsetTabContextMenu");
+ this.offsetTabContextMenu.Theme = MetroFramework.MetroThemeStyle.Dark;
+ //
+ // addOffsetToolStripMenuItem
+ //
+ this.addOffsetToolStripMenuItem.Name = "addOffsetToolStripMenuItem";
+ resources.ApplyResources(this.addOffsetToolStripMenuItem, "addOffsetToolStripMenuItem");
+ this.addOffsetToolStripMenuItem.Click += new System.EventHandler(this.addOffsetToolStripMenuItem_Click);
+ //
+ // removeOffsetToolStripMenuItem
+ //
+ this.removeOffsetToolStripMenuItem.Name = "removeOffsetToolStripMenuItem";
+ resources.ApplyResources(this.removeOffsetToolStripMenuItem, "removeOffsetToolStripMenuItem");
+ this.removeOffsetToolStripMenuItem.Click += new System.EventHandler(this.removeOffsetToolStripMenuItem_Click);
+ //
+ // renderer3D1
+ //
+ resources.ApplyResources(this.renderer3D1, "renderer3D1");
+ this.renderer3D1.Animate = true;
+ this.renderer3D1.BackColor = System.Drawing.Color.DimGray;
+ this.renderer3D1.CapeTexture = null;
+ this.renderer3D1.CenterOnSelect = false;
+ this.renderer3D1.GuideLineColor = System.Drawing.Color.Empty;
+ this.renderer3D1.HighlightlingColor = System.Drawing.Color.Aqua;
+ this.renderer3D1.MouseSensetivity = 0.01F;
+ this.renderer3D1.Name = "renderer3D1";
+ this.renderer3D1.RefreshRate = 60;
+ this.renderer3D1.SelectedIndex = -1;
+ this.renderer3D1.SelectedIndices = new int[] {
+ -1};
+ this.renderer3D1.ShowArmor = false;
+ this.renderer3D1.ShowBoundingBox = false;
+ this.renderer3D1.ShowGuideLines = false;
+ this.renderer3D1.Texture = null;
+ this.renderer3D1.VSync = true;
+ this.renderer3D1.TextureChanging += new System.EventHandler(this.renderer3D1_TextureChanging);
+ //
+ // uvPictureBox
+ //
+ resources.ApplyResources(this.uvPictureBox, "uvPictureBox");
+ this.uvPictureBox.BackgroundInterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
+ this.uvPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
+ this.uvPictureBox.Name = "uvPictureBox";
+ this.uvPictureBox.TabStop = false;
+ //
+ // centerSelectionCheckbox
+ //
+ resources.ApplyResources(this.centerSelectionCheckbox, "centerSelectionCheckbox");
+ this.centerSelectionCheckbox.Name = "centerSelectionCheckbox";
+ this.centerSelectionCheckbox.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.centerSelectionCheckbox.UseSelectable = true;
+ this.centerSelectionCheckbox.CheckedChanged += new System.EventHandler(this.centerSelectionCheckbox_CheckedChanged);
+ //
+ // textureSizeLabel
+ //
+ resources.ApplyResources(this.textureSizeLabel, "textureSizeLabel");
+ this.textureSizeLabel.ForeColor = System.Drawing.Color.White;
+ this.textureSizeLabel.Name = "textureSizeLabel";
+ //
+ // renderSettingsButton
+ //
+ resources.ApplyResources(this.renderSettingsButton, "renderSettingsButton");
+ this.renderSettingsButton.Name = "renderSettingsButton";
+ this.renderSettingsButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.renderSettingsButton.UseSelectable = true;
+ this.renderSettingsButton.Click += new System.EventHandler(this.renderSettingsButton_Click);
+ //
+ // exportTemplateButton
+ //
+ resources.ApplyResources(this.exportTemplateButton, "exportTemplateButton");
+ this.exportTemplateButton.ForeColor = System.Drawing.Color.White;
+ this.exportTemplateButton.Name = "exportTemplateButton";
+ this.exportTemplateButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.exportTemplateButton.UseSelectable = true;
+ this.exportTemplateButton.Click += new System.EventHandler(this.exportTemplateButton_Click);
+ //
+ // animEditorButton
+ //
+ resources.ApplyResources(this.animEditorButton, "animEditorButton");
+ this.animEditorButton.Name = "animEditorButton";
+ this.animEditorButton.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.animEditorButton.UseSelectable = true;
+ this.animEditorButton.Click += new System.EventHandler(this.animEditorButton_Click);
+ //
+ // CustomSkinEditor
+ //
+ resources.ApplyResources(this, "$this");
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.exportTextureButton);
+ this.Controls.Add(this.importTextureButton);
+ this.Controls.Add(this.textureSizeLabel);
+ this.Controls.Add(groupBox1);
+ this.Controls.Add(this.showToolsCheckBox);
+ this.Controls.Add(this.centerSelectionCheckbox);
+ this.Controls.Add(this.showArmorCheckbox);
+ this.Controls.Add(this.generateTextureCheckBox);
+ this.Controls.Add(this.outlineColorButton);
+ this.Controls.Add(this.uvPictureBox);
+ this.Controls.Add(this.animEditorButton);
+ this.Controls.Add(this.exportTemplateButton);
+ this.Controls.Add(this.renderSettingsButton);
+ this.Controls.Add(this.metroTabControl1);
+ this.Controls.Add(this.skinNameLabel);
+ this.Controls.Add(this.captureScreenshotButton);
+ this.Controls.Add(this.renderer3D1);
+ this.Controls.Add(this.exportSkinButton);
+ this.Controls.Add(this.importSkinButton);
+ this.Controls.Add(this.buttonDone);
+ this.Name = "CustomSkinEditor";
+ this.Style = MetroFramework.MetroColorStyle.Silver;
+ this.Theme = MetroFramework.MetroThemeStyle.Dark;
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CustomSkinEditor_FormClosing);
+ groupBox1.ResumeLayout(false);
+ groupBox1.PerformLayout();
+ this.skinPartTabContextMenu.ResumeLayout(false);
+ this.metroTabControl1.ResumeLayout(false);
+ this.skinPartsTabPage.ResumeLayout(false);
+ this.skinOffsetsTabPage.ResumeLayout(false);
+ this.offsetTabContextMenu.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.uvPictureBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.ContextMenuStrip skinPartTabContextMenu;
+ private System.Windows.Forms.ToolStripMenuItem createToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem cloneToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem deleteToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem generateUvTextureToolStripMenuItem;
+ private MetroFramework.Controls.MetroButton buttonDone;
+ private MetroFramework.Controls.MetroButton outlineColorButton;
+ private MetroFramework.Controls.MetroButton exportSkinButton;
+ private MetroFramework.Controls.MetroButton importSkinButton;
+ private PckStudio.ToolboxItems.InterpolationPictureBox uvPictureBox;
+ private MetroFramework.Controls.MetroButton importTextureButton;
+ private MetroFramework.Controls.MetroButton exportTextureButton;
+ private MetroFramework.Controls.MetroCheckBox generateTextureCheckBox;
+ private MetroFramework.Controls.MetroCheckBox showArmorCheckbox;
+ private Rendering.SkinRenderer renderer3D1;
+ private System.Windows.Forms.ListBox skinPartListBox;
+ private MetroFramework.Controls.MetroButton captureScreenshotButton;
+ private MetroFramework.Controls.MetroCheckBox showToolsCheckBox;
+ private MetroFramework.Controls.MetroLabel skinNameLabel;
+ private MetroFramework.Controls.MetroTabControl metroTabControl1;
+ private System.Windows.Forms.TabPage skinPartsTabPage;
+ private System.Windows.Forms.TabPage skinOffsetsTabPage;
+ private System.Windows.Forms.ListBox offsetListBox;
+ private MetroFramework.Controls.MetroContextMenu offsetTabContextMenu;
+ private System.Windows.Forms.ToolStripMenuItem addOffsetToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem removeOffsetToolStripMenuItem;
+ private MetroFramework.Controls.MetroCheckBox centerSelectionCheckbox;
+ private System.Windows.Forms.Label positionLabel;
+ private System.Windows.Forms.Label sizeLabel;
+ private System.Windows.Forms.Label uvLabel;
+ private System.Windows.Forms.Label textureSizeLabel;
+ private MetroFramework.Controls.MetroButton renderSettingsButton;
+ private MetroFramework.Controls.MetroButton exportTemplateButton;
+ private MetroFramework.Controls.MetroButton animEditorButton;
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs
new file mode 100644
index 00000000..8b39c40d
--- /dev/null
+++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs
@@ -0,0 +1,481 @@
+using System;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Collections.Generic;
+
+using PckStudio.Controls;
+using PckStudio.Properties;
+using PckStudio.Forms.Additional_Popups;
+
+using PckStudio.Core.Skin;
+using PckStudio.Core.Extensions;
+using PckStudio.Interfaces;
+using PckStudio.ModelSupport;
+using PckStuido.ModelSupport.Extension;
+
+namespace PckStudio.Forms.Editor
+{
+ public partial class CustomSkinEditor : EditorForm
+ {
+ private const float cOffsetMaximum = 100_000f;
+ private Random _rng;
+ private bool _inflateOverlayParts;
+ private bool _allowInflate;
+
+ private BindingSource _skinPartListBindingSource;
+ private BindingSource _skinOffsetListBindingSource;
+
+ private Core.App.SettingsManager _settingsManager;
+
+ private static GraphicsConfig _graphicsConfig = new GraphicsConfig()
+ {
+ InterpolationMode = InterpolationMode.NearestNeighbor,
+ PixelOffsetMode = PixelOffsetMode.HighQuality,
+ };
+
+ private CustomSkinEditor() : this(null, null)
+ { }
+
+ public CustomSkinEditor(Skin skin, ISaveContext saveContext, bool inflateOverlayParts = false, bool allowInflate = false)
+ : base(skin, saveContext)
+ {
+ InitializeComponent();
+ InitializeRenderSettings();
+ _rng = new Random();
+ _skinPartListBindingSource = new BindingSource(renderer3D1.ModelData, null);
+ skinPartListBox.DataSource = _skinPartListBindingSource;
+ skinPartListBox.DisplayMember = "Type";
+ _allowInflate = allowInflate;
+ _inflateOverlayParts = inflateOverlayParts;
+ }
+
+ private void InitializeRenderSettings()
+ {
+ _settingsManager = Core.App.SettingsManager.CreateSettings();
+ _settingsManager.AddSetting("shouldAnimate" , true , "Animate skin" , state => renderer3D1.Animate = state);
+ _settingsManager.AddSetting("lockMouse" , true , "Lock mouse when paning/rotating", state => renderer3D1.LockMousePosition = state);
+ _settingsManager.AddSetting("showGuidelines" , false, "Show guidelines" , state => renderer3D1.ShowGuideLines = state);
+ _settingsManager.AddSetting("showBoundingBox", false, "Show Bounding Box" , state => renderer3D1.ShowBoundingBox = state);
+ }
+
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+ renderer3D1.Initialize(_inflateOverlayParts);
+ renderer3D1.GuideLineColor = Color.LightCoral;
+ skinNameLabel.Text = EditorValue.MetaData.Name;
+ if (EditorValue.HasCape)
+ renderer3D1.CapeTexture = EditorValue.CapeTexture;
+ LoadModelData();
+ }
+
+ protected override bool ProcessDialogKey(Keys keyData)
+ {
+ if (keyData == Keys.A)
+ {
+ using var animeditor = new ANIMEditor(EditorValue.Anim);
+ if (animeditor.ShowDialog() == DialogResult.OK)
+ {
+ renderer3D1.ANIM = EditorValue.Anim = animeditor.ResultAnim;
+ skinPartListBox_SelectedIndexChanged(this, EventArgs.Empty);
+ }
+ return true;
+ }
+ return base.ProcessDialogKey(keyData);
+ }
+
+ private void LoadModelData()
+ {
+ SkinModel modelInfo = EditorValue.Model;
+
+ List boxProperties = modelInfo.AdditionalBoxes;
+ List offsetProperties = modelInfo.PartOffsets;
+
+ renderer3D1.ANIM = EditorValue.Anim;
+
+ renderer3D1.ModelData.Clear();
+ foreach (SkinBOX box in boxProperties)
+ {
+ renderer3D1.ModelData.Add(box);
+ }
+ renderer3D1.ResetOffsets();
+ foreach (SkinPartOffset offset in offsetProperties)
+ {
+ renderer3D1.SetPartOffset(offset);
+ }
+
+ if (EditorValue.Texture is not null)
+ {
+ renderer3D1.Texture = EditorValue.Texture;
+ }
+
+ if (EditorValue.Texture is null && renderer3D1.Texture is not null)
+ {
+ EditorValue.Texture = renderer3D1.Texture;
+ }
+
+ _skinOffsetListBindingSource = new BindingSource(renderer3D1.GetOffsets().ToArray(), null);
+ offsetListBox.DataSource = _skinOffsetListBindingSource;
+ offsetListBox.DisplayMember = "Type";
+ offsetListBox.ValueMember = "Value";
+
+ _skinPartListBindingSource.ResetBindings(false);
+ _skinOffsetListBindingSource.ResetBindings(false);
+ }
+
+ private void GenerateUVTextureMap(SkinBOX skinBox)
+ {
+ if (EditorValue?.Texture is null)
+ {
+ Trace.TraceWarning($"[{nameof(CustomSkinEditor)}@{nameof(GenerateUVTextureMap)}] Failed to generate uv for {skinBox}. Reason: Model.Texture was null");
+ return;
+ }
+ using (Graphics graphics = Graphics.FromImage(EditorValue.Texture))
+ {
+ graphics.ApplyConfig(_graphicsConfig);
+ int argb = _rng.Next(unchecked((int)0xFF000000), -1);
+ var color = Color.FromArgb(argb);
+ Brush brush = new SolidBrush(color);
+ graphics.FillPath(brush, skinBox.GetUVGraphicsPath());
+ }
+ renderer3D1.Texture = EditorValue.Texture;
+ }
+
+ private void createToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var boxEditor = new BoxEditor(SkinBOX.DefaultHead, _allowInflate);
+ if (boxEditor.ShowDialog() == DialogResult.OK)
+ {
+ SkinBOX newBox = boxEditor.Result;
+ renderer3D1.ModelData.Add(newBox);
+ EditorValue.Model.AdditionalBoxes.Add(newBox);
+ _skinPartListBindingSource.ResetBindings(false);
+ if (generateTextureCheckBox.Checked)
+ GenerateUVTextureMap(newBox);
+ }
+ }
+
+ private void exportTextureButton_Click(object sender, EventArgs e)
+ {
+ if (EditorValue?.Texture is null)
+ {
+ Trace.TraceWarning($"[{nameof(CustomSkinEditor)}@{nameof(exportTextureButton_Click)}] Failed to export texture. Reason: skin.Model.Texture was null");
+ return;
+ }
+ using SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Filter = "PNG Image Files | *.png";
+ if (saveFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ EditorValue.Texture.Save(saveFileDialog.FileName, ImageFormat.Png);
+ }
+ }
+
+ private void importTextureButton_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog openFileDialog = new OpenFileDialog();
+ openFileDialog.Filter = "PNG Image Files | *.png";
+ openFileDialog.Title = "Select Skin Texture";
+
+ if (openFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ generateTextureCheckBox.Checked = false;
+ renderer3D1.Texture = Image.FromFile(openFileDialog.FileName).ReleaseFromFile();
+ }
+ }
+
+ private void buttonDone_Click(object sender, EventArgs e)
+ {
+ EditorValue.Model.AdditionalBoxes.Clear();
+ EditorValue.Model.AdditionalBoxes.AddRange(renderer3D1.ModelData);
+ EditorValue.Model.PartOffsets.Clear();
+ EditorValue.Model.PartOffsets.AddRange(renderer3D1.GetOffsets());
+ // just in case they're not the same instance
+ EditorValue.Anim = renderer3D1.ANIM;
+ DialogResult = DialogResult.OK;
+ }
+
+ private void exportSkinButton_Click(object sender, EventArgs e)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Title = "Save Model File";
+ saveFileDialog.Filter = SkinModelImporter.Default.SupportedModelFileFormatsFilter;
+ saveFileDialog.FileName = EditorValue.MetaData.Name.TrimEnd(new char[] { '\n', '\r' }).Replace(' ', '_');
+ if (saveFileDialog.ShowDialog() == DialogResult.OK)
+ SkinModelImporter.Default.Export(saveFileDialog.FileName, EditorValue.GetModelInfo());
+ }
+
+ private void importSkinButton_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog openFileDialog = new OpenFileDialog();
+ openFileDialog.Title = "Select Model File";
+ openFileDialog.Filter = SkinModelImporter.Default.SupportedModelFileFormatsFilter;
+ if (MessageBox.Show("Import custom model project file? Your current work will be lost!", "", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes && openFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ SkinModelInfo modelInfo = SkinModelImporter.Default.Import(openFileDialog.FileName);
+ if (modelInfo is not null)
+ {
+ EditorValue.SetModelInfo(modelInfo);
+ LoadModelData();
+ }
+ }
+ }
+
+ private void cloneToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (skinPartListBox.SelectedItem is SkinBOX box)
+ {
+ SkinBOX clone = box;
+ renderer3D1.ModelData.Add(clone);
+ EditorValue.Model.AdditionalBoxes.Add(clone);
+ _skinPartListBindingSource.ResetBindings(false);
+ }
+ }
+
+ private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (skinPartListBox.SelectedItem is SkinBOX box)
+ {
+ renderer3D1.ModelData.Remove(box);
+ EditorValue.Model.AdditionalBoxes.Remove(box);
+ _skinPartListBindingSource.ResetBindings(false);
+ }
+ }
+
+ private void CustomSkinEditor_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ renderer3D1.Dispose();
+ }
+
+ private void outlineColorButton_Click(object sender, EventArgs e)
+ {
+ ColorDialog colorDialog = new ColorDialog();
+ colorDialog.SolidColorOnly = true;
+ if (colorDialog.ShowDialog() == DialogResult.OK)
+ {
+ renderer3D1.GuideLineColor = colorDialog.Color;
+ skinPartListBox_SelectedIndexChanged(sender, e);
+ }
+ }
+
+ private void renderer3D1_TextureChanging(object sender, Rendering.TextureChangingEventArgs e)
+ {
+ Image texture = e.NewTexture;
+ // Skins can only be a 1:1 ratio (base 64x64) or a 2:1 ratio (base 64x32)
+ if (Settings.Default.ValidateImageDimension && texture.Width != texture.Height && texture.Height != texture.Width / 2)
+ {
+ e.Cancel = true;
+ MessageBox.Show("The selected image does not suit a skin texture.", "Invalid image dimensions.", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ uvPictureBox.Image = EditorValue.Texture = texture;
+ textureSizeLabel.Text = $"{texture.Width}x{texture.Height}";
+ }
+
+ private void skinPartListBox_DoubleClick(object sender, EventArgs e)
+ {
+ if (skinPartListBox.SelectedItem is SkinBOX box)
+ {
+ var boxEditor = new BoxEditor(box, _allowInflate);
+ if (boxEditor.ShowDialog() == DialogResult.OK)
+ {
+ renderer3D1.ModelData[skinPartListBox.SelectedIndex] = boxEditor.Result;
+ _skinPartListBindingSource.ResetItem(skinPartListBox.SelectedIndex);
+ }
+ }
+ }
+
+ // TODO: fixed outline rendering
+ private void skinPartListBox_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ int scale = 1;
+ renderer3D1.SelectedIndices = skinPartListBox.SelectedIndices.Cast().ToArray();
+ StringBuilder uv_sb = new StringBuilder();
+ StringBuilder size_sb = new StringBuilder();
+ StringBuilder pos_sb = new StringBuilder();
+ foreach (SkinBOX b in skinPartListBox.SelectedItems.Cast())
+ {
+ uv_sb.Append(b.UV);
+ uv_sb.Append(", ");
+ size_sb.Append(b.Size);
+ size_sb.Append(", ");
+ pos_sb.Append(b.Pos);
+ pos_sb.Append(", ");
+ }
+
+ uvLabel.Text = $"UV: {uv_sb}";
+ sizeLabel.Text = $"Size: {size_sb}";
+ positionLabel.Text = $"Position: {pos_sb}";
+
+ // TODO: highlight all selected boxes
+ if (skinPartListBox.SelectedItem is SkinBOX box)
+ {
+
+ Image uvArea = EditorValue.Texture.GetArea(Rectangle.Truncate(new RectangleF(box.UV.X, box.UV.Y, box.Size.X * 2 + box.Size.Z * 2, box.Size.Z + box.Size.Y)));
+
+ Bitmap refImg = new Bitmap(1, 1);
+
+ using (var g = Graphics.FromImage(refImg))
+ {
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.DrawImage(uvArea, new Rectangle(0, 0, 1, 1));
+ }
+
+ Color avgColor = refImg.GetPixel(0, 0);
+ renderer3D1.HighlightlingColor = avgColor.Inversed();
+
+ Size scaleSize = new Size(EditorValue.Texture.Width * scale, EditorValue.Texture.Height * scale);
+ uvPictureBox.Image = new Bitmap(scaleSize.Width, scaleSize.Height);
+ using (Graphics g = Graphics.FromImage(uvPictureBox.Image))
+ {
+ GraphicsPath graphicsPath = box.GetUVGraphicsPath(new System.Numerics.Vector2(scaleSize.Width * renderer3D1.TillingFactor.X, scaleSize.Height * renderer3D1.TillingFactor.Y));
+ var brush = new SolidBrush(Color.FromArgb(127, avgColor.GreyScaled()));
+ g.ApplyConfig(_graphicsConfig);
+ g.DrawImage(EditorValue.Texture, new Rectangle(Point.Empty, scaleSize), new Rectangle(Point.Empty, EditorValue.Texture.Size), GraphicsUnit.Pixel);
+ g.FillPath(brush, graphicsPath);
+ }
+ uvPictureBox.Invalidate();
+ }
+ }
+
+ 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);
+ }
+ }
+
+ private void showArmorCheckbox_CheckedChanged(object sender, EventArgs e)
+ {
+ renderer3D1.ShowArmor = showArmorCheckbox.Checked;
+ }
+
+ private void skinPartListBox_KeyUp(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Delete:
+ deleteToolStripMenuItem_Click(sender, e);
+ break;
+ case Keys.Escape:
+ ClearSelection();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void ReloadOffsetList()
+ {
+ _skinOffsetListBindingSource = new BindingSource(renderer3D1.GetOffsets().ToArray(), null);
+ offsetListBox.DataSource = _skinOffsetListBindingSource;
+ _skinOffsetListBindingSource.ResetBindings(false);
+ }
+
+ private void addOffsetToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var offsets = renderer3D1.GetOffsets().Select(offset => offset.Type).ToList();
+ string[] available = SkinPartOffset.ValidModelOffsetTypes.Where(s => !offsets.Contains(s)).ToArray();
+ using ItemSelectionPopUp typeSelection = new ItemSelectionPopUp(available);
+ using NumericPrompt valuePrompt = new NumericPrompt(0f, -cOffsetMaximum, cOffsetMaximum);
+ valuePrompt.DecimalPlaces = 1;
+ valuePrompt.ValueStep = (decimal)0.1f;
+ if (typeSelection.ShowDialog() == DialogResult.OK && valuePrompt.ShowDialog() == DialogResult.OK)
+ {
+ renderer3D1.SetPartOffset(typeSelection.SelectedItem, (float)valuePrompt.SelectedValue);
+ ReloadOffsetList();
+ }
+ }
+
+ private void removeOffsetToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (offsetListBox.SelectedItem is not SkinPartOffset offset)
+ return;
+ renderer3D1.SetPartOffset(offset.Type, 0f);
+ ReloadOffsetList();
+ }
+
+ private void offsetListBox_DoubleClick(object sender, EventArgs e)
+ {
+ if (offsetListBox.SelectedItem is not SkinPartOffset offset)
+ return;
+
+ using NumericPrompt valuePrompt = new NumericPrompt(offset.Value, -cOffsetMaximum, cOffsetMaximum);
+ valuePrompt.ToolTipText = "Set new Value for " + offset.Type;
+ valuePrompt.DecimalPlaces = 1;
+ valuePrompt.ValueStep = (decimal)0.1f;
+ if (valuePrompt.ShowDialog() == DialogResult.OK)
+ {
+ renderer3D1.SetPartOffset(offset.Type, (float)valuePrompt.SelectedValue);
+ ReloadOffsetList();
+ }
+ }
+
+ private void skinPartListBox_MouseClick(object sender, MouseEventArgs e)
+ {
+ if (skinPartListBox.IndexFromPoint(e.X, e.Y) == -1)
+ ClearSelection();
+ }
+
+ private void ClearSelection()
+ {
+ skinPartListBox.ClearSelected();
+ uvPictureBox.Image = EditorValue.Texture;
+ }
+
+
+ private void centerSelectionCheckbox_CheckedChanged(object sender, EventArgs e)
+ {
+ renderer3D1.CenterOnSelect = centerSelectionCheckbox.Checked;
+ }
+
+ private void generateUvTextureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (skinPartListBox.SelectedItem is SkinBOX skinBox)
+ {
+ GenerateUVTextureMap(skinBox);
+ }
+ }
+
+ private void renderSettingsButton_Click(object sender, EventArgs e)
+ {
+ using AppSettingsForm settingsForm = new AppSettingsForm("Render Settings", _settingsManager.GetSettings());
+ settingsForm.ShowDialog();
+ }
+
+ private string SanitizeModelFilename(in string modelFilename)
+ {
+ return string.IsNullOrWhiteSpace(modelFilename) ? "template" : modelFilename.TrimEnd(new char[] { '\n', '\r' }).Replace(' ', '_');
+ }
+
+ private void exportTemplateButton_Click(object sender, EventArgs e)
+ {
+ Image templateTexture = Resources.classic_template;
+ SkinAnimMask templateAnimMask = SkinAnimMask.RESOLUTION_64x64;
+
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Title = "Save Template Model";
+ saveFileDialog.Filter = SkinModelImporter.Default.SupportedModelFileFormatsFilter;
+ saveFileDialog.FileName = SanitizeModelFilename(EditorValue.MetaData.Name);
+ if (saveFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ SkinModelInfo modelInfo = new SkinModelInfo(templateTexture, templateAnimMask, new SkinModel());
+ SkinModelImporter.Default.Export(saveFileDialog.FileName, modelInfo);
+ }
+ }
+
+ private void animEditorButton_Click(object sender, EventArgs e)
+ {
+ ProcessDialogKey(Keys.A);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.ja.resx b/PCK-Studio/Forms/Editor/CustomSkinEditor.ja.resx
similarity index 100%
rename from PCK-Studio/Forms/Skins-And-Textures/generateModel.ja.resx
rename to PCK-Studio/Forms/Editor/CustomSkinEditor.ja.resx
diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx b/PCK-Studio/Forms/Editor/CustomSkinEditor.resx
similarity index 85%
rename from PCK-Studio/Forms/Skins-And-Textures/generateModel.resx
rename to PCK-Studio/Forms/Editor/CustomSkinEditor.resx
index da2157ab..e76b2020 100644
--- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx
+++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.resx
@@ -117,175 +117,205 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
False
+
+
+ Left
+
+
+ Top, Right
+
-
+
True
-
-
+
NoControl
-
- 23, 459
+
+ 6, 47
-
- 38, 13
+
+ 3, 3, 3, 3
-
- 137
+
+ 33, 19
-
- Parent
-
-
- label6
-
-
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 19
-
-
- False
-
-
- True
-
-
- NoControl
-
-
- 691, 357
-
-
- 44, 13
-
-
- 127
-
-
- Position
-
-
- label5
-
-
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 28
-
-
- False
-
-
- True
-
-
- NoControl
-
-
- 691, 259
-
-
- 27, 13
-
-
+
142
-
+
Size
-
- label3
+
+ sizeLabel
-
+
System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- $this
+
+ groupBox1
-
- 27
+
+ 0
-
- False
-
-
+
+ Top, Right
+
+
True
-
+
NoControl
-
- 654, 236
+
+ 6, 76
-
- 22, 13
+
+ 3, 3, 3, 3
-
+
+ 50, 19
+
+
+ 127
+
+
+ Position
+
+
+ positionLabel
+
+
+ System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ groupBox1
+
+
+ 1
+
+
+ Top, Right
+
+
+ True
+
+
+ NoControl
+
+
+ 6, 21
+
+
+ 3, 3, 3, 3
+
+
+ 28, 19
+
+
131
-
+
UV
-
- label7
+
+ uvLabel
-
+
System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+ groupBox1
+
+
+ 2
+
+
+ 19, 276
+
+
+ 3, 3, 3, 0
+
+
+ 161, 117
+
+
+ 170
+
+
+ Porperties
+
+
+ groupBox1
+
+
+ System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
$this
-
- 22
+
+ 5
-
- False
-
-
- True
+
+ Left
-
- NoControl
+
+ 23, 249
-
- 655, 56
+
+ 61, 21
-
- 128, 13
+
+ 128
-
- 113
+
+ Import
-
- Texture Mapping Preview
+
+ importTextureButton
-
- labelTextureMappingPreview
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
+
$this
-
- 16
+
+ 3
-
+
+ Left
+
+
+ 90, 249
+
+
+ 61, 21
+
+
+ 114
+
+
+ Export
+
+
+ exportTextureButton
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 2
+
+
17, 17
@@ -297,10 +327,10 @@
- 151, 26
+ 201, 26
- Create
+ Add Cube
@@ -318,7 +348,7 @@
- 151, 26
+ 201, 26
Clone
@@ -333,12 +363,12 @@
- 151, 26
+ 201, 26
Delete
-
+
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAFhSURBVFhH7ZY/
@@ -351,32 +381,29 @@
rkJggg==
-
- 151, 26
+
+ 201, 26
-
- Change Color
+
+ Re-generate UV Texture
-
- 152, 108
+
+ 202, 108
-
- contextMenuStrip1
+
+ skinPartTabContextMenu
-
+
System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- Flat
-
-
- NoControl
+
+ Bottom, Right
- 654, 676
+ 627, 553
- 130, 22
+ 250, 21
111
@@ -388,661 +415,106 @@
buttonDone
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
$this
- 26
-
-
- True
-
-
- NoControl
-
-
- 289, 647
-
-
- 33, 13
-
-
- 102
-
-
- View:
-
-
- labelView
-
-
- System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 25
-
-
- Flat
-
-
- NoControl
-
-
- 554, 642
-
-
- 89, 23
-
-
- 100
-
-
- Rotate Right
-
-
- rotateRightBtn
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 24
-
-
- Flat
-
-
- NoControl
-
-
- 194, 643
-
-
- 89, 23
-
-
- 101
-
-
- Rotate Left
-
-
- rotateLeftBtn
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 23
-
-
- 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
-
- HEAD
+
+ Bottom, Left
-
- BODY
+
+ 27, 553
-
- ARM0
+
+ 75, 21
-
- ARM1
+
+ 96
-
- LEG0
+
+ Import Skin
-
- LEG1
+
+ importSkinButton
-
- 23, 484
-
-
- 114, 21
-
-
- 134
-
-
- comboParent
-
-
- System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 18
-
-
- Flat
-
-
- NoControl
-
-
- 722, 206
-
-
- 61, 21
-
-
- 114
-
-
- EXPORT
-
-
- buttonEXPORT
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 15
-
-
- Flat
-
-
- NoControl
-
-
- 655, 206
-
-
- 61, 21
-
-
- 128
-
-
- IMPORT
-
-
- buttonIMPORT
-
-
- System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 20
-
-
- NoControl
-
-
- 655, 72
-
-
- 128, 128
-
-
- Zoom
-
-
- 112
-
-
- uvPictureBox
-
-
- PckStudio.ToolboxItems.InterpolationPictureBox, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null
-
-
- $this
-
-
- 17
-
-
- NoControl
-
-
- 194, 56
-
-
- 449, 580
-
-
- StretchImage
-
-
- 98
-
-
- displayBox
-
-
- System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- $this
-
-
- 13
-
-
- 23, 511
-
-
- 114, 21
-
-
- 146
-
-
- Load Template
-
-
- buttonTemplate
-
-
+
MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
+
$this
-
- 12
+
+ 20
+
+
+ Bottom, Left
+
+
+ 105, 553
+
+
+ 75, 21
+
+
+ 97
+
+
+ Export skin
+
+
+ exportSkinButton
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 19
+
+
+ Left
+
+
+ 19, 429
+
+
+ 161, 21
+
+
+ 145
+
+
+ Set Outline Color
+
+
+ False
+
+
+ outlineColorButton
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
+ $this
+
+
+ 10
+
+
+ Left
True
- 23, 556
+ 22, 399
140, 15
@@ -1063,338 +535,470 @@
$this
- 11
-
-
- True
-
-
- 23, 577
-
-
- 84, 15
-
-
- 148
-
-
- Guide Lines
-
-
- checkGuide
-
-
- MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
-
- $this
-
-
- 10
-
-
- True
-
-
- 23, 598
-
-
- 129, 15
-
-
- 149
-
-
- Show Armor Offsets
-
-
- checkBoxArmor
-
-
- MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
-
-
- $this
-
-
9
-
- 658, 275
+
+ Left
-
- 119, 20
+
+ True
-
- 150
+
+ 23, 532
-
- Center
+
+ 89, 15
-
- SizeXUpDown
+
+ 149
-
- System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Show Armor
-
+
+ showArmorCheckbox
+
+
+ MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
$this
-
+
8
-
- 658, 301
+
+ Fill
-
- 119, 20
+
+ 0, 0
-
- 151
+
+ 242, 446
-
- Center
+
+ 0
-
- SizeYUpDown
+
+ skinPartListBox
-
- System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+ skinPartsTabPage
+
+
+ 0
+
+
+ Bottom, Right
+
+
+ 510, 553
+
+
+ 111, 21
+
+
+ 163
+
+
+ Capture Screenshot
+
+
+ captureScreenshotButton
+
+
+ MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
$this
-
- 7
+
+ 17
-
- 658, 327
+
+ Left
-
- 119, 20
+
+ True
-
- 152
+
+ 23, 511
-
- Center
+
+ 82, 15
-
- SizeZUpDown
+
+ 164
-
- System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Show Tools
-
+
+ showToolsCheckBox
+
+
+ MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
$this
-
+
6
-
- 682, 233
+
+ Top, Left, Right
-
- 43, 20
+
+ True
-
- 156
+
+ 364, 36
-
- TextureXUpDown
+
+ 73, 19
-
- System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 165
-
+
+ nameLabel
+
+
+ skinNameLabel
+
+
+ MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a
+
+
$this
-
- 5
+
+ 16
-
- 731, 234
+
+ Top, Right
-
- 43, 20
+
+ 4, 38
-
- 157
+
+ 242, 446
-
- TextureYUpDown
+
+ 0
-
- System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Parts
-
- $this
+
+ skinPartsTabPage
-
- 4
+
+ System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- 657, 425
+
+ metroTabControl1
-
- 120, 20
+
+ 0
-
- 160
+
+ 204, 17
+
+
+ 152, 22
-
- Center
+
+ Add Offset
-
- PosZUpDown
+
+