diff --git a/SpineViewer/MainForm.Designer.cs b/SpineViewer/MainForm.Designer.cs index 9083a3e..9cffae1 100644 --- a/SpineViewer/MainForm.Designer.cs +++ b/SpineViewer/MainForm.Designer.cs @@ -40,6 +40,8 @@ toolStripMenuItem_Exit = new ToolStripMenuItem(); toolStripMenuItem_Function = new ToolStripMenuItem(); toolStripMenuItem_ResetAnimation = new ToolStripMenuItem(); + toolStripMenuItem_Tool = new ToolStripMenuItem(); + toolStripMenuItem_ConvertFileFormat = new ToolStripMenuItem(); toolStripMenuItem_Download = new ToolStripMenuItem(); toolStripMenuItem_ManageResource = new ToolStripMenuItem(); toolStripMenuItem_Help = new ToolStripMenuItem(); @@ -61,8 +63,6 @@ spinePreviewer = new SpineViewer.Controls.SpinePreviewer(); panel_MainForm = new Panel(); toolTip = new ToolTip(components); - toolStripMenuItem_Tool = new ToolStripMenuItem(); - toolStripMenuItem_ConvertFileFormat = new ToolStripMenuItem(); menuStrip.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer_MainForm).BeginInit(); splitContainer_MainForm.Panel1.SuspendLayout(); @@ -156,10 +156,24 @@ // toolStripMenuItem_ResetAnimation // toolStripMenuItem_ResetAnimation.Name = "toolStripMenuItem_ResetAnimation"; - toolStripMenuItem_ResetAnimation.Size = new Size(270, 34); + toolStripMenuItem_ResetAnimation.Size = new Size(242, 34); toolStripMenuItem_ResetAnimation.Text = "重置动画时间(&R)"; toolStripMenuItem_ResetAnimation.Click += toolStripMenuItem_ResetAnimation_Click; // + // toolStripMenuItem_Tool + // + toolStripMenuItem_Tool.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ConvertFileFormat }); + toolStripMenuItem_Tool.Name = "toolStripMenuItem_Tool"; + toolStripMenuItem_Tool.Size = new Size(84, 28); + toolStripMenuItem_Tool.Text = "工具(&T)"; + // + // toolStripMenuItem_ConvertFileFormat + // + toolStripMenuItem_ConvertFileFormat.Name = "toolStripMenuItem_ConvertFileFormat"; + toolStripMenuItem_ConvertFileFormat.Size = new Size(270, 34); + toolStripMenuItem_ConvertFileFormat.Text = "转换文件格式(&C)..."; + toolStripMenuItem_ConvertFileFormat.Click += toolStripMenuItem_ConvertFileFormat_Click; + // // toolStripMenuItem_Download // toolStripMenuItem_Download.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ManageResource }); @@ -183,19 +197,19 @@ // toolStripMenuItem_Diagnostics // toolStripMenuItem_Diagnostics.Name = "toolStripMenuItem_Diagnostics"; - toolStripMenuItem_Diagnostics.Size = new Size(270, 34); + toolStripMenuItem_Diagnostics.Size = new Size(208, 34); toolStripMenuItem_Diagnostics.Text = "诊断信息(&D)"; toolStripMenuItem_Diagnostics.Click += toolStripMenuItem_Diagnostics_Click; // // toolStripSeparator3 // toolStripSeparator3.Name = "toolStripSeparator3"; - toolStripSeparator3.Size = new Size(267, 6); + toolStripSeparator3.Size = new Size(205, 6); // // toolStripMenuItem_About // toolStripMenuItem_About.Name = "toolStripMenuItem_About"; - toolStripMenuItem_About.Size = new Size(270, 34); + toolStripMenuItem_About.Size = new Size(208, 34); toolStripMenuItem_About.Text = "关于(&A)"; toolStripMenuItem_About.Click += toolStripMenuItem_About_Click; // @@ -409,19 +423,6 @@ // toolTip.ShowAlways = true; // - // toolStripMenuItem_Tool - // - toolStripMenuItem_Tool.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ConvertFileFormat }); - toolStripMenuItem_Tool.Name = "toolStripMenuItem_Tool"; - toolStripMenuItem_Tool.Size = new Size(84, 28); - toolStripMenuItem_Tool.Text = "工具(&T)"; - // - // toolStripMenuItem_ConvertFileFormat - // - toolStripMenuItem_ConvertFileFormat.Name = "toolStripMenuItem_ConvertFileFormat"; - toolStripMenuItem_ConvertFileFormat.Size = new Size(270, 34); - toolStripMenuItem_ConvertFileFormat.Text = "转换文件格式(&C)..."; - // // MainForm // AutoScaleDimensions = new SizeF(11F, 24F); diff --git a/SpineViewer/Spine/Implementations/SkeletonConverter/SkeletonConverter38.cs b/SpineViewer/Spine/Implementations/SkeletonConverter/SkeletonConverter38.cs new file mode 100644 index 0000000..f5b970f --- /dev/null +++ b/SpineViewer/Spine/Implementations/SkeletonConverter/SkeletonConverter38.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SpineRuntime38; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace SpineViewer.Spine.Implementations.SkeletonConverter +{ + [SkeletonConverterImplementation(Version.V38)] + class SkeletonConverter38 : SpineViewer.Spine.SkeletonConverter + { + private SkeletonReader reader = null; + private bool nonessential = false; + private JsonObject root = null; + + public override void BinaryToJson(string binPath, string jsonPath) + { + using var input = new FileStream(binPath, FileMode.Open, FileAccess.Read, FileShare.Read); + reader = new(input); + + root = []; + root["skeleton"] = ReadSkeleton(); + ReadStrings(); + root["bones"] = ReadBones(); + root["slots"] = ReadSlots(); + root["ik"] = ReadIK(); + root["transform"] = ReadTransform(); + root["path"] = ReadPath(); + root["skins"] = ReadSkins(); + root["events"] = ReadEvents(); + root["aimations"] = ReadAnimations(); + + using var output = new FileStream(jsonPath, FileMode.Create, FileAccess.Write, FileShare.None); + using var writer = new Utf8JsonWriter(output, jsonWriterOptions); + root.WriteTo(writer); + } + + private JsonObject ReadSkeleton() + { + JsonObject skeleton = []; + skeleton["hash"] = reader.ReadString(); + skeleton["spine"] = reader.ReadString(); + skeleton["x"] = reader.ReadFloat(); + skeleton["y"] = reader.ReadFloat(); + skeleton["width"] = reader.ReadFloat(); + skeleton["height"] = reader.ReadFloat(); + nonessential = reader.ReadBoolean(); + if (nonessential) + { + skeleton["fps"] = reader.ReadFloat(); + skeleton["images"] = reader.ReadString(); + skeleton["audio"] = reader.ReadString(); + } + return skeleton; + } + + private void ReadStrings() + { + int count = reader.ReadVarInt(); + for (int i = 0; i < count; i++) + reader.StringTable.Add(reader.ReadString()); + } + + private JsonArray ReadBones() + { + JsonArray bones = []; + int count = reader.ReadVarInt(); + for (int i = 0; i < count; i++) + { + JsonObject data = []; + data["name"] = reader.ReadString(); + if (i != 0) data["parent"] = bones[reader.ReadVarInt()]["name"].GetValue(); + data["rotation"] = reader.ReadFloat(); + data["x"] = reader.ReadFloat(); + data["y"] = reader.ReadFloat(); + data["scaleX"] = reader.ReadFloat(); + data["scaleY"] = reader.ReadFloat(); + data["shearX"] = reader.ReadFloat(); + data["shearY"] = reader.ReadFloat(); + data["length"] = reader.ReadFloat(); + data["transform"] = SkeletonBinary.TransformModeValues[reader.ReadVarInt()].ToString(); + data["skin"] = reader.ReadBoolean(); + if (nonessential) reader.ReadInt(); + bones.Add(data); + } + return bones; + } + + private JsonArray ReadSlots() + { + JsonArray bones = root["bones"].AsArray(); + JsonArray slots = []; + int count = reader.ReadVarInt(); + for (int i = 0; i < count; i++) + { + JsonObject data = []; + data["name"] = reader.ReadString(); + data["bone"] = bones[reader.ReadVarInt()]["name"].GetValue(); + data["color"] = reader.ReadInt().ToString("x8"); // 0xrrggbbaa -> rrggbbaa + int dark = reader.ReadInt(); + if (dark != -1) data["dark"] = dark.ToString("x6"); // 0x00rrggbb -> rrggbb + data["attachment"] = reader.ReadStringRef(); + data["blend"] = ((BlendMode)reader.ReadVarInt()).ToString(); + slots.Add(data); + } + return slots; + } + + private JsonArray ReadIK() + { + JsonArray bones = root["bones"].AsArray(); + JsonArray ik = []; + int count = reader.ReadVarInt(); + for (int i = 0, bonesCount; i < count; i++) + { + JsonObject data = []; + data["name"] = reader.ReadString(); + data["order"] = reader.ReadVarInt(); + data["skin"] = reader.ReadBoolean(); + JsonArray bonesArray = []; bonesCount = reader.ReadVarInt(); + for (int j = 0; j < bonesCount; j++) bonesArray.Add(bones[reader.ReadVarInt()]["name"].GetValue()); + data["bones"] = bonesArray; + data["target"] = bones[reader.ReadVarInt()]["name"].GetValue(); + data["mix"] = reader.ReadFloat(); + data["softness"] = reader.ReadFloat(); + data["bendPositive"] = reader.ReadSByte() > 0; + data["compress"] = reader.ReadBoolean(); + data["stretch"] = reader.ReadBoolean(); + data["uniform"] = reader.ReadBoolean(); + ik.Add(data); + } + return ik; + } + + private JsonArray ReadTransform() + { + JsonArray bones = root["bones"].AsArray(); + JsonArray transform = []; + int count = reader.ReadVarInt(); + for (int i = 0, bonesCount; i < count; i++) + { + JsonObject data = []; + data["name"] = reader.ReadString(); + data["order"] = reader.ReadVarInt(); + data["skin"] = reader.ReadBoolean(); + JsonArray bonesArray = []; bonesCount = reader.ReadVarInt(); + for (int j = 0; j < bonesCount; j++) bonesArray.Add(bones[reader.ReadVarInt()]["name"].GetValue()); + data["bones"] = bonesArray; + data["target"] = bones[reader.ReadVarInt()]["name"].GetValue(); + data["local"] = reader.ReadBoolean(); + data["relative"] = reader.ReadBoolean(); + data["rotation"] = reader.ReadFloat(); + data["x"] = reader.ReadFloat(); + data["y"] = reader.ReadFloat(); + data["scaleX"] = reader.ReadFloat(); + data["scaleY"] = reader.ReadFloat(); + data["shearY"] = reader.ReadFloat(); + data["rotateMix"] = reader.ReadFloat(); + data["translateMix"] = reader.ReadFloat(); + data["scaleMix"] = reader.ReadFloat(); + data["shearMix"] = reader.ReadFloat(); + transform.Add(data); + } + return transform; + } + + private JsonArray ReadPath() + { + JsonArray bones = root["bones"].AsArray(); + JsonArray path = []; + int count = reader.ReadVarInt(); + for (int i = 0, bonesCount; i < count; i++) + { + JsonObject data = []; + data["name"] = reader.ReadString(); + data["order"] = reader.ReadVarInt(); + data["skin"] = reader.ReadBoolean(); + JsonArray bonesArray = []; bonesCount = reader.ReadVarInt(); + for (int j = 0; j < bonesCount; j++) bonesArray.Add(bones[reader.ReadVarInt()]["name"].GetValue()); + data["bones"] = bonesArray; + data["target"] = bones[reader.ReadVarInt()]["name"].GetValue(); + data["positionMode"] = ((PositionMode)reader.ReadVarInt()).ToString(); + data["spacingMode"] = ((SpacingMode)reader.ReadVarInt()).ToString(); + data["rotateMode"] = ((RotateMode)reader.ReadVarInt()).ToString(); + data["rotation"] = reader.ReadFloat(); + data["position"] = reader.ReadFloat(); + data["spacing"] = reader.ReadFloat(); + data["rotateMix"] = reader.ReadFloat(); + data["translateMix"] = reader.ReadFloat(); + path.Add(data); + } + return path; + } + + private JsonArray ReadSkins() + { + JsonArray skins = []; + int count = reader.ReadVarInt(); + for (int i = 0; i < count; i++) + { + throw new NotImplementedException(); + } + + return skins; + } + + private JsonObject ReadEvents() + { + JsonObject events = []; + int count = reader.ReadVarInt(); + for (int i = 0; i < count; i++) + { + JsonObject data = []; + events[reader.ReadStringRef()] = data; + data["int"] = reader.ReadVarInt(false); + data["float"] = reader.ReadFloat(); + data["string"] = reader.ReadString(); + string audio = reader.ReadString(); + if (audio is not null) + { + data["audio"] = audio; + data["volume"] = reader.ReadFloat(); + data["balance"] = reader.ReadFloat(); + } + } + return events; + } + + private JsonObject ReadAnimations() + { + JsonObject animations = []; + + return animations; + } + + public override void JsonToBinary(string jsonPath, string binPath) + { + // 按顺序把 json 的内容写入到骨骼 binary 缓冲区 + // 然后在文件中依次写入文件头和骨骼数据 + throw new NotImplementedException(); + } + } +}