public static void addAnimation(GameObject rootGO, string rootDirectory, SpineData spineData, Dictionary <string, GameObject> boneGOByName, AttachmentGOByNameBySlot attachmentGOByNameBySlot, int pixelsPerUnit, ModelImporterAnimationType modelImporterAnimationType, bool updateResources) { float ratio = 1.0f / (float)pixelsPerUnit; foreach (KeyValuePair <string, SpineAnimation> kvp in spineData.animations) { string animationName = kvp.Key; string animationFolder = rootDirectory + "/" + ANIMATION_FOLDER; string assetPath = animationFolder + "/" + animationName + ".anim"; SpineAnimation spineAnimation = kvp.Value; AnimationClip animationClip = new AnimationClip(); bool updateCurve = false; if (File.Exists(assetPath)) { AnimationClip oldClip = AssetDatabase.LoadAssetAtPath(assetPath, typeof(AnimationClip)) as AnimationClip; if (oldClip != null) { animationClip = oldClip; animationClip.ClearCurves(); updateCurve = true; } } AnimationUtility.SetAnimationType(animationClip, modelImporterAnimationType); if (spineAnimation.bones != null) { addBoneAnimationToClip(animationClip, spineAnimation.bones, spineData, boneGOByName, ratio); } if (spineAnimation.slots != null) { addSlotAnimationToClip(animationClip, spineAnimation.slots, spineData, attachmentGOByNameBySlot); } if (spineAnimation.draworder != null) { Debug.LogWarning("draworder animation implemented yet"); } if (updateCurve) { EditorUtility.SetDirty(animationClip); AssetDatabase.SaveAssets(); } else { animationClip.frameRate = 30; createFolderIfNoExists(rootDirectory, ANIMATION_FOLDER); AssetDatabase.CreateAsset(animationClip, assetPath); AssetDatabase.SaveAssets(); if (modelImporterAnimationType == ModelImporterAnimationType.Generic) { AddClipToAnimatorComponent(rootGO, animationClip); } else { AddClipToLegacyAnimationComponent(rootGO, animationClip); } } } }
public static void addSlotAnimationToClip(AnimationClip clip, Dictionary <string, SpineSlotAnimation> slotsAnimation, SpineData spineData, AttachmentGOByNameBySlot attachmentGOByNameBySlot) { foreach (KeyValuePair <string, SpineSlotAnimation> kvp in slotsAnimation) { string slotName = kvp.Key; string defaultAttachment = spineData.slotDefaultAttachments[slotName]; if (string.IsNullOrEmpty(defaultAttachment)) { continue; } SpineSlotAnimation slotAnimation = kvp.Value; if (slotAnimation.attachment != null && slotAnimation.attachment.Count > 0) { Dictionary <string, AnimationCurve> curveByName = new Dictionary <string, AnimationCurve>(); for (int i = 0; i < slotAnimation.attachment.Count; i++) { bool nullAttachment = false; SpineSlotAttachmentAnimation anim = slotAnimation.attachment[i]; if (string.IsNullOrEmpty(anim.name)) { anim.name = getFirstAttachmentName(slotAnimation); nullAttachment = true; } if (anim.name.Equals("")) { continue; } AnimationCurve enableCurve; if (curveByName.ContainsKey(anim.name)) { enableCurve = curveByName[anim.name]; } else { enableCurve = new AnimationCurve(); if (anim.time > 0.0f) { enableCurve.AddKey(KeyframeUtil.GetNew(0, 0.0f, TangentMode.Stepped)); } curveByName.Add(anim.name, enableCurve); if (i == 0 && !anim.name.Equals(defaultAttachment)) { AnimationCurve defSlotCurve = new AnimationCurve(); curveByName.Add(defaultAttachment, defSlotCurve); if (anim.time != 0.0f) { defSlotCurve.AddKey(KeyframeUtil.GetNew(0, nullAttachment ? 0 : 1, TangentMode.Stepped)); defSlotCurve.AddKey(KeyframeUtil.GetNew((float)anim.time, 0, TangentMode.Stepped)); } else { defSlotCurve.AddKey(KeyframeUtil.GetNew(0, 0, TangentMode.Stepped)); } } } enableCurve.AddKey(KeyframeUtil.GetNew((float)anim.time, nullAttachment ? 0 : 1, TangentMode.Stepped)); if (i < (slotAnimation.attachment.Count - 1)) { SpineSlotAttachmentAnimation nextAnim = slotAnimation.attachment[i + 1]; bool nullNextAttachment = false; if (string.IsNullOrEmpty(nextAnim.name)) { nextAnim.name = getFirstAttachmentName(slotAnimation); nullNextAttachment = true; } if (!nextAnim.name.Equals(anim.name) || nullNextAttachment) { enableCurve.AddKey(KeyframeUtil.GetNew((float)nextAnim.time, 0, TangentMode.Stepped)); } } } foreach (KeyValuePair <string, AnimationCurve> kvp2 in curveByName) { string attachmentName = kvp2.Key; AnimationCurve animationCurve = kvp2.Value; string attachmentPath = spineData.slotPathByName[slotName] + "/" + attachmentName.Replace("/", SLASH_REPLACEMENT); clip.SetCurve(attachmentPath, typeof(GameObject), "m_IsActive", animationCurve); } } if (slotAnimation.color != null && slotAnimation.color.Count > 0) { Debug.LogWarning("slot color animation is not supported yet"); } } }
public static void addAllAttahcmentsSlots(SpineData spineData, SpritesByName spriteByName, Dictionary <string, Slot> slotByName, float zStep, int pixelsPerUnit, out List <Skin> skins, out AttachmentGOByNameBySlot attachmentGOByNameBySlot) { float ratio = 1.0f / (float)pixelsPerUnit; skins = new List <Skin>(); attachmentGOByNameBySlot = new AttachmentGOByNameBySlot(); foreach (KeyValuePair <string, SpineSkinSlots> kvp in spineData.skins) { string skinName = kvp.Key; Skin skin = new Skin(); skin.name = skinName; List <SkinSlot> slotList = new List <SkinSlot>(); bool isDefault = skinName.Equals("default"); foreach (KeyValuePair <string, SpineSkinSlotAttachments> kvp2 in spineData.skins[skinName]) { string slotName = kvp2.Key; GameObject slotGO = slotByName[slotName].gameObject; Slot slot = slotByName[slotName]; SkinSlot skinSlot = new SkinSlot(); skinSlot.name = slotName; skinSlot.gameObject = slotGO; List <SkinSlotAttachment> attachmentList = new List <SkinSlotAttachment>(); foreach (KeyValuePair <string, SpineSkinAttachment> kvp3 in spineData.skins[skinName][slotName]) { string attachmenName = kvp3.Key; SkinSlotAttachment attachment = new SkinSlotAttachment(); attachment.name = attachmenName; SpineSkinAttachment spineAttachment = kvp3.Value; // - create skined object or direct GO for default skin Sprite sprite; spriteByName.TryGetValue(spineAttachment.name, out sprite); int drawOrder = spineData.slotOrder[slotName]; GameObject parentGO; GameObject spriteGO; string fixedName = attachmenName.Replace("/", SLASH_REPLACEMENT); if (isDefault) { parentGO = slotGO; spriteGO = new GameObject(fixedName); Attachment a = new Attachment(attachmenName, AttachmentType.SINGLE_SPRITE, spriteGO); slot.addAttachment(a); } else { spriteGO = new GameObject(skinName); Attachment a; slot.attachmentByName.TryGetValue(attachmenName, out a); if (a == null) { GameObject attachmentGO = new GameObject(fixedName); attachmentGO.transform.parent = slotGO.transform; resetLocalTRS(attachmentGO); a = new Attachment(attachmenName, AttachmentType.SKINED_SPRITE, attachmentGO); slot.addAttachment(a); } parentGO = a.gameObject; } attachment.gameObject = spriteGO; spriteGO.transform.parent = parentGO.gameObject.transform; // - if (spineAttachment.type.Equals("region")) { SpriteRenderer sr = spriteGO.AddComponent <SpriteRenderer>(); sr.sprite = sprite; spriteGO.transform.localPosition = getAttachmentPosition(spineAttachment, ratio, -(drawOrder * zStep)); spriteGO.transform.localRotation = getAttachmentRotation(spineAttachment, spriteByName.rotatedSprites.Contains(sprite)); spriteGO.transform.localScale = getAttachmentScale(spineAttachment); } else if (spineAttachment.type.Equals("boundingbox")) { PolygonCollider2D collider = spriteGO.AddComponent <PolygonCollider2D>(); resetLocalTRS(spriteGO); Vector2[] vertices = new Vector2[spineAttachment.vertices.Length / 2]; for (int i = 0; i < spineAttachment.vertices.Length; i += 2) { float x = (float)spineAttachment.vertices[i] * ratio; float y = (float)spineAttachment.vertices[i + 1] * ratio; vertices[i / 2] = new Vector2(x, y); } collider.points = vertices; collider.SetPath(0, vertices); } else { Debug.LogWarning("Attachment type " + spineAttachment.type + " is not supported yiet FIX MEEE"); } attachmentList.Add(attachment); } skinSlot.attachments = attachmentList.ToArray(); slotList.Add(skinSlot); } skin.slots = slotList.ToArray(); skins.Add(skin); } }