private static void ParseSlots(SpineArmatureEditor armatureEditor, Bones2D.JSONClass armtureObj)
 {
     if (armtureObj.ContainKey("slots"))
     {
         Bones2D.JSONArray    slots     = armtureObj["slots"].AsArray;
         SpineData.SlotData[] slotDatas = new SpineData.SlotData[slots.Count];
         for (int i = 0; i < slots.Count; ++i)
         {
             Bones2D.JSONClass  slotObj  = slots[i].AsObject;
             SpineData.SlotData slotData = new SpineData.SlotData();
             slotData.displayIndex = i;
             if (slotObj.ContainKey("name"))
             {
                 slotData.name = slotObj["name"].ToString();
             }
             if (slotObj.ContainKey("bone"))
             {
                 slotData.bone = slotObj["bone"].ToString();
             }
             if (slotObj.ContainKey("color"))
             {
                 slotData.color = SpineArmatureEditor.HexToColor(slotObj["color"].ToString());
             }
             if (slotObj.ContainKey("attachment"))
             {
                 slotData.attachment = slotObj["attachment"].ToString();
             }
             if (slotObj.ContainKey("blend"))
             {
                 slotData.blend = slotObj["blend"].ToString();
             }
             slotData.index = i;
             slotDatas[i]   = slotData;
             armatureEditor.slotsDataKV[slotData.name] = slotData;
         }
         armatureEditor.armatureData.slots = slotDatas;
     }
 }
        static void CreateAnimSlot(SpineArmatureEditor armatureEditor, AnimationClip clip, SpineData.AnimationSlotData[] animSlotDatas)
        {
            for (int i = 0; i < animSlotDatas.Length; ++i)
            {
                SpineData.AnimationSlotData animSlotData = animSlotDatas[i];
                string             slotName        = animSlotData.name;
                Transform          slot            = armatureEditor.slotsKV[slotName];
                SpineData.SlotData defaultSlotData = armatureEditor.slotsDataKV[slotName];
                Color defaultColorData             = defaultSlotData.color;

                AnimationCurve color_rcurve = new AnimationCurve();
                AnimationCurve color_gcurve = new AnimationCurve();
                AnimationCurve color_bcurve = new AnimationCurve();
                AnimationCurve color_acurve = new AnimationCurve();

                AnimationCurve display_curve = new AnimationCurve();

                bool isHaveCurve = false;
                for (int j = 0; j < animSlotData.timelines.Length; ++j)
                {
                    SpineData.SlotTimeline timeline = animSlotData.timelines[j];
                    string  prevTweeneasing         = "linear";           //前一帧的tweenEasing
                    float[] prevCurves = null;
                    if (j > 0)
                    {
                        prevTweeneasing = animSlotData.timelines[j - 1].tweenEasing;
                        prevCurves      = animSlotData.timelines[j - 1].curve;
                    }
                    TangentMode tanModeL = GetPrevFrameTangentMode(prevTweeneasing, prevCurves);
                    TangentMode tanModeR = TangentMode.Linear;

                    if (timeline.curve != null && timeline.curve.Length > 0)
                    {
                        tanModeR    = TangentMode.Editable;
                        isHaveCurve = true;
                    }
                    else
                    {
                        if (timeline.tweenEasing == "stepped")
                        {
                            tanModeR = TangentMode.Stepped;
                        }
                        else
                        {
                            tanModeR = TangentMode.Linear;
                        }
                    }

                    if (timeline.type == "color")
                    {
                        if (!string.IsNullOrEmpty(timeline.color))
                        {
                            Color c = SpineArmatureEditor.HexToColor(timeline.color);
                            color_rcurve.AddKey(KeyframeUtil.GetNew(timeline.time, c.r, tanModeL, tanModeR));
                            color_gcurve.AddKey(KeyframeUtil.GetNew(timeline.time, c.g, tanModeL, tanModeR));
                            color_bcurve.AddKey(KeyframeUtil.GetNew(timeline.time, c.b, tanModeL, tanModeR));
                            color_acurve.AddKey(KeyframeUtil.GetNew(timeline.time, c.a, tanModeL, tanModeR));                         //*defaultColorData.a
                        }
                        else if (color_acurve.length > 0)
                        {
                            color_rcurve.AddKey(KeyframeUtil.GetNew(timeline.time, defaultColorData.r, tanModeL, tanModeR));
                            color_gcurve.AddKey(KeyframeUtil.GetNew(timeline.time, defaultColorData.g, tanModeL, tanModeR));
                            color_bcurve.AddKey(KeyframeUtil.GetNew(timeline.time, defaultColorData.b, tanModeL, tanModeR));
                            color_acurve.AddKey(KeyframeUtil.GetNew(timeline.time, defaultColorData.a, tanModeL, tanModeR));
                        }
                    }
                    else if (timeline.type == "attachment")
                    {
                        if (string.IsNullOrEmpty(timeline.attachmentName))
                        {
                            display_curve.AddKey(new Keyframe(timeline.time, -1f, float.PositiveInfinity, float.PositiveInfinity));
                        }
                        else
                        {
                            for (int r = 0; r < slot.childCount; ++r)
                            {
                                if (slot.GetChild(r).name.Equals(timeline.attachmentName))
                                {
                                    display_curve.AddKey(new Keyframe(timeline.time, r, float.PositiveInfinity, float.PositiveInfinity));
                                    break;
                                }
                            }
                        }
                    }
                }
                CurveExtension.OptimizesCurve(color_rcurve);
                CurveExtension.OptimizesCurve(color_gcurve);
                CurveExtension.OptimizesCurve(color_bcurve);
                CurveExtension.OptimizesCurve(color_acurve);
                CurveExtension.OptimizesCurve(display_curve);

                string path = "";
                if (slotPathKV.ContainsKey(slot.name))
                {
                    path = slotPathKV[slot.name];
                }
                else
                {
                    path = GetNodeRelativePath(armatureEditor, slot);
                    slotPathKV[slot.name] = path;
                }

                SetColorCurve <Slot>(path, clip, color_rcurve, "color.r", isHaveCurve, defaultColorData.r, animSlotData.timelines);
                SetColorCurve <Slot>(path, clip, color_gcurve, "color.g", isHaveCurve, defaultColorData.g, animSlotData.timelines);
                SetColorCurve <Slot>(path, clip, color_bcurve, "color.b", isHaveCurve, defaultColorData.b, animSlotData.timelines);
                SetColorCurve <Slot>(path, clip, color_acurve, "color.a", isHaveCurve, defaultColorData.a, animSlotData.timelines);

                //add pose
                AnimationCurve pose_color_rcurve = new AnimationCurve();
                AnimationCurve pose_color_gcurve = new AnimationCurve();
                AnimationCurve pose_color_bcurve = new AnimationCurve();
                AnimationCurve pose_color_acurve = new AnimationCurve();
                pose_color_rcurve.AddKey(new Keyframe(0f, defaultColorData.r));
                pose_color_gcurve.AddKey(new Keyframe(0f, defaultColorData.g));
                pose_color_bcurve.AddKey(new Keyframe(0f, defaultColorData.b));
                pose_color_acurve.AddKey(new Keyframe(0f, defaultColorData.a));
                AnimationUtility.SetEditorCurve(poseClip, EditorCurveBinding.FloatCurve(path, typeof(Slot), "color.r"), pose_color_rcurve);
                AnimationUtility.SetEditorCurve(poseClip, EditorCurveBinding.FloatCurve(path, typeof(Slot), "color.g"), pose_color_gcurve);
                AnimationUtility.SetEditorCurve(poseClip, EditorCurveBinding.FloatCurve(path, typeof(Slot), "color.b"), pose_color_bcurve);
                AnimationUtility.SetEditorCurve(poseClip, EditorCurveBinding.FloatCurve(path, typeof(Slot), "color.a"), pose_color_acurve);

                if (display_curve.keys != null && display_curve.keys.Length > 0 &&
                    CheckCurveValid(display_curve, slot.GetComponent <Slot>().displayIndex))
                {
                    clip.SetCurve(path, typeof(Slot), "m_DisplayIndex", display_curve);
                    //add pose
                    AnimationCurve pose_display_curve = new AnimationCurve();
                    pose_display_curve.AddKey(new Keyframe(0f, slot.GetComponent <Slot>().displayIndex));
                    AnimationUtility.SetEditorCurve(poseClip, EditorCurveBinding.FloatCurve(path, typeof(Slot), "m_DisplayIndex"), pose_display_curve);
                }
            }
        }
 private static void ParseSkins(SpineArmatureEditor armatureEditor, Bones2D.JSONClass armtureObj)
 {
     if (armtureObj.ContainKey("skins"))
     {
         Bones2D.JSONClass    skins     = armtureObj["skins"].AsObject;
         SpineData.SkinData[] skinDatas = new SpineData.SkinData[skins.Count];
         armatureEditor.armatureData.skins = skinDatas;
         int      skinDataCount = 0;
         string[] skinNames     = new string[skins.Count];
         foreach (string skinName in skins.GetKeys())
         {
             Bones2D.JSONClass  skinSlots = skins[skinName].AsObject;
             SpineData.SkinData skinData  = new SpineData.SkinData();
             skinDatas[skinDataCount] = skinData;
             skinData.skinName        = skinName;
             skinNames[skinDataCount] = skinName;
             skinData.slots           = new Dictionary <string, List <SpineData.SkinAttachment> >();
             foreach (string slotName in skinSlots.GetKeys())
             {
                 Bones2D.JSONClass skinAttments = skinSlots[slotName].AsObject;
                 skinData.slots[slotName] = new List <SpineData.SkinAttachment>();
                 foreach (string attachmentName in skinAttments.GetKeys())
                 {
                     Bones2D.JSONClass        attachmentObj = skinAttments[attachmentName].AsObject;
                     SpineData.SkinAttachment attachment    = new SpineData.SkinAttachment();
                     attachment.name = attachmentName;
                     if (attachmentObj.ContainKey("name"))
                     {
                         attachment.realName = attachmentObj["name"].ToString();
                     }
                     else
                     {
                         attachment.realName = attachmentName;
                     }
                     if (attachmentObj.ContainKey("path"))
                     {
                         attachment.textureName = attachmentObj["path"].ToString();
                     }
                     else
                     {
                         attachment.textureName = attachment.realName;
                     }
                     if (attachmentObj.ContainKey("type"))
                     {
                         attachment.type = attachmentObj["type"].ToString();                                                             //region,mesh,linkedmesh,boundingbox,path
                     }
                     if (attachment.type == "path" || attachment.type == "linkedmesh")
                     {
                         continue;
                     }
                     skinData.slots[slotName].Add(attachment);
                     if (attachmentObj.ContainKey("x"))
                     {
                         attachment.x = attachmentObj["x"].AsFloat * armatureEditor.unit;
                     }
                     if (attachmentObj.ContainKey("y"))
                     {
                         attachment.y = attachmentObj["y"].AsFloat * armatureEditor.unit;
                     }
                     if (attachmentObj.ContainKey("scaleX"))
                     {
                         attachment.scaleX = attachmentObj["scaleX"].AsFloat;
                     }
                     if (attachmentObj.ContainKey("scaleY"))
                     {
                         attachment.scaleY = attachmentObj["scaleY"].AsFloat;
                     }
                     if (attachmentObj.ContainKey("width"))
                     {
                         attachment.width = attachmentObj["width"].AsFloat;
                     }
                     if (attachmentObj.ContainKey("height"))
                     {
                         attachment.height = attachmentObj["height"].AsFloat;
                     }
                     if (attachmentObj.ContainKey("rotation"))
                     {
                         attachment.rotation = attachmentObj["rotation"].AsFloat;
                     }
                     if (attachmentObj.ContainKey("color"))
                     {
                         attachment.color = SpineArmatureEditor.HexToColor(attachmentObj["color"].ToString());
                     }
                     if (attachmentObj.ContainKey("hull"))
                     {
                         attachment.hull = attachmentObj["hull"].AsInt;
                     }
                     if (attachmentObj.ContainKey("uvs"))
                     {
                         Bones2D.JSONArray uvsObj = attachmentObj["uvs"].AsArray;
                         attachment.uvs = new Vector2[uvsObj.Count / 2];
                         for (int z = 0; z < uvsObj.Count; z += 2)
                         {
                             Vector2 uv = new Vector2(uvsObj[z].AsFloat, 1 - uvsObj[z + 1].AsFloat);
                             attachment.uvs[z / 2] = uv;
                         }
                     }
                     //triangles
                     if (attachmentObj.ContainKey("triangles"))
                     {
                         Bones2D.JSONArray trianglesObj = attachmentObj["triangles"].AsArray;
                         attachment.triangles = new int[trianglesObj.Count];
                         for (int z = 0; z < trianglesObj.Count; z++)
                         {
                             attachment.triangles[z] = trianglesObj[z].AsInt;
                         }
                     }
                     //vertex
                     if (attachmentObj.ContainKey("vertices"))
                     {
                         Bones2D.JSONArray verticesObj = attachmentObj["vertices"].AsArray;
                         if (attachment.uvs != null && verticesObj.Count > attachment.uvs.Length * 2)
                         {
                             //have weighted
                             List <float> weights = new List <float>();
                             for (int i = 0; i < verticesObj.Count; ++i)
                             {
                                 int boneCount = verticesObj[i].AsInt;
                                 weights.Add(boneCount);
                                 for (int j = 0; j < boneCount * 4; j += 4)
                                 {
                                     weights.Add(verticesObj[i + j + 1].AsInt);                                        //bone index
                                     weights.Add(verticesObj[i + j + 2].AsFloat * armatureEditor.unit);                //relativeBoneX
                                     weights.Add(verticesObj[i + j + 3].AsFloat * armatureEditor.unit);                //relativeBoneY
                                     weights.Add(verticesObj[i + j + 4].AsFloat);                                      //weight
                                 }
                                 i += boneCount * 4;
                             }
                             attachment.weights = weights;
                         }
                         else
                         {
                             //only vertices
                             attachment.vertices = new Vector3[verticesObj.Count / 2];
                             for (int i = 0; i < verticesObj.Count; i += 2)
                             {
                                 Vector3 vertex = new Vector3(verticesObj[i].AsFloat, verticesObj[i + 1].AsFloat, 0f);
                                 vertex.x *= armatureEditor.unit;
                                 vertex.y *= armatureEditor.unit;
                                 attachment.vertices[i / 2] = vertex;
                             }
                         }
                     }
                     //edges
                     if (armatureEditor.genMeshCollider && attachmentObj.ContainKey("edges"))
                     {
                         Bones2D.JSONArray edgesObj = attachmentObj["edges"].AsArray;
                         int        len             = edgesObj.Count;
                         List <int> edges           = new List <int>();
                         for (int z = 0; z < len; ++z)
                         {
                             int value = edgesObj[z].AsInt / 2;
                             if (edges.Count > 0)
                             {
                                 if (edges[edges.Count - 1] != value)
                                 {
                                     edges.Add(value);
                                 }
                             }
                             else
                             {
                                 edges.Add(value);
                             }
                         }
                         if (edges.Count > 2 && edges[0] == edges[edges.Count - 1])
                         {
                             edges.RemoveAt(edges.Count - 1);
                         }
                         if (edges.Count > 2)
                         {
                             attachment.edges = edges.ToArray();
                         }
                     }
                 }
             }
             ++skinDataCount;
         }
         armatureEditor.armature.GetComponent <Armature>().skins = skinNames;
     }
 }