public static SkinController addSkinController(GameObject gameObject, SpineData spineData, List <Skin> allSkins, Dictionary <string, Slot> slotByName) { SkinController sk = gameObject.AddComponent <SkinController>(); List <Skin> skins = new List <Skin>(); Skin defaultSkin = null; foreach (Skin skin in allSkins) { if (skin.name.Equals("default")) { defaultSkin = skin; } else { skins.Add(skin); } } sk.defaultSkin = defaultSkin; sk.skins = skins.ToArray(); Slot[] slots = new Slot[slotByName.Count]; slotByName.Values.CopyTo(slots, 0); sk.slots = slots; return(sk); }
public static string[] getTransformPaths(GameObject go, SpineData spineData) { List <String> result = new List <string>(); result.Add(""); foreach (Transform t in go.GetComponentsInChildren <Transform>(true)) { string path = AnimationUtility.CalculateTransformPath(t, go.transform); if (t.name.StartsWith(SLOT_PREFIX + " [") && t.name.EndsWith("]")) { string slotName = t.name.Remove(t.name.Length - 1); slotName = slotName.Remove(0, (SLOT_PREFIX + " [").Length); if (spineData.slotPathByName.ContainsKey(slotName) && spineData.slotPathByName[slotName] == path) { result.Add(path); } } else { if (spineData.bonePathByName.ContainsKey(t.name) && spineData.bonePathByName[t.name] == path) { result.Add(path); } } } return(result.ToArray()); }
static void setCachedData(SpineData data) { data.slotByName = new Dictionary <string, SpineSlot>(); data.boneByName = new Dictionary <string, SpineBone>(); for (int i = 0; i < data.bones.Count; i++) { data.boneByName.Add(data.bones[i].name, data.bones[i]); } data.bonePathByName = new Dictionary <string, string>(); foreach (SpineBone bone in data.bones) { string path = ""; SpineBone b = bone; do { path = b.name + "/" + path; if (!string.IsNullOrEmpty(b.parent)) { b = data.boneByName[b.parent]; } else { b = null; } } while (b != null); if (path.Length > 0) { path = path.Remove(path.Length - 1); } data.bonePathByName.Add(bone.name, path); } data.slotOrder = new Dictionary <string, int>(); data.slotPathByName = new Dictionary <string, string>(); data.slotDefaultAttachments = new Dictionary <string, string>(); for (int i = 0; i < data.slots.Count; i++) { string slotName = data.slots[i].name; string defaultAttachment = data.slots[i].attachment; data.slotOrder.Add(slotName, i); string boneName = data.slots[i].bone; string bonePath = data.bonePathByName[boneName]; string slotPath = bonePath + "/" + SpineUtil.getSlotGOName(slotName); data.slotPathByName.Add(slotName, slotPath); data.slotDefaultAttachments.Add(slotName, defaultAttachment); } }
public static void builAvatarMask(GameObject gameObject, SpineData spineData, Animator animator, string directory, string name){ Avatar avatar = AvatarBuilder.BuildGenericAvatar(gameObject,""); animator.avatar = avatar; AvatarMask avatarMask = new AvatarMask(); string[] transofrmPaths = getTransformPaths(gameObject, spineData); avatarMask.transformCount = transofrmPaths.Length; for (int i=0; i< transofrmPaths.Length; i++){ avatarMask.SetTransformPath(i, transofrmPaths[i]); avatarMask.SetTransformActive(i, true); } createFolderIfNoExists(directory, ANIMATION_FOLDER); AssetDatabase.CreateAsset(avatar , directory + "/" + ANIMATION_FOLDER + "/" + name + ".anim.asset"); AssetDatabase.CreateAsset(avatarMask, directory + "/" + ANIMATION_FOLDER + "/" + name + ".mask.asset"); }
void OnWizardCreate() { string atlasPath = getAtlasFilePath(path); string directory = Path.GetDirectoryName(atlasPath); string name = Path.GetFileNameWithoutExtension(path); SpritesByName spriteByName; Dictionary <string, GameObject> boneGOByName; Dictionary <string, Slot> slotByName; List <Skin> skins; AttachmentGOByNameBySlot attachmentGOByNameBySlot; if (File.Exists(path)) { try{ SpineMultiatlas spineMultiAtlas = SpineMultiatlas.deserializeFromFile(atlasPath); SpineData spineData = SpineData.deserializeFromFile(path); SpineUtil.updateImporters(spineMultiAtlas, directory, pixelsPerUnit, out spriteByName); GameObject rootGO = SpineUtil.buildSceleton(name, spineData, pixelsPerUnit, out boneGOByName, out slotByName); rootGO.name = name; SpineUtil.addAllAttahcmentsSlots(spineData, spriteByName, slotByName, zStep, pixelsPerUnit, out skins, out attachmentGOByNameBySlot); SkinController sk = SpineUtil.addSkinController(rootGO, spineData, skins, slotByName); if (animationImportType == AnimationImportType.MECANIM) { Animator animator = SpineUtil.addAnimator(rootGO); if (buildAvatarMask) { SpineUtil.builAvatarMask(rootGO, spineData, animator, directory, name); } } ModelImporterAnimationType modelImporterAnimationType = getModelImporterAnimationType(); if (spineData.animations != null && spineData.animations.Count > 0) { SpineUtil.addAnimation(rootGO, directory, spineData, boneGOByName, attachmentGOByNameBySlot, pixelsPerUnit, modelImporterAnimationType, updateResources); } sk.showDefaulSlots(); SpineUtil.buildPrefab(rootGO, directory, name); GameObject.DestroyImmediate(rootGO); } catch (SpineMultiatlasCreationException e) { Debug.LogException(e); } catch (SpineDatatCreationException e) { Debug.LogException(e); } catch (AtlasImageDuplicateSpriteName e) { Debug.LogException(e); } } }
public static GameObject buildSceleton(string name, SpineData data, int pixelsPerUnit, out Dictionary <string, GameObject> boneGOByName, out Dictionary <string, Slot> slotByName) { float ratio = 1.0f / (float)pixelsPerUnit; boneGOByName = new Dictionary <string, GameObject>(); slotByName = new Dictionary <string, Slot>(); GameObject rootGO = new GameObject(name); foreach (SpineBone bone in data.bones) { GameObject go = new GameObject(bone.name); boneGOByName.Add(bone.name, go); } foreach (SpineBone bone in data.bones) { GameObject go = boneGOByName[bone.name]; if (bone.parent == null) { go.transform.parent = rootGO.transform; } else { go.transform.parent = boneGOByName[bone.parent].transform; } Vector3 position = new Vector3((float)bone.x * ratio, (float)bone.y * ratio, 0.0f); Vector3 scale = new Vector3((float)bone.scaleX, (float)bone.scaleY, 1.0f); Quaternion rotation = Quaternion.Euler(0, 0, (float)bone.rotation); go.transform.localPosition = position; go.transform.localScale = scale; go.transform.localRotation = rotation; } foreach (SpineSlot spineSlot in data.slots) { GameObject go = new GameObject(getSlotGOName(spineSlot.name)); go.transform.parent = boneGOByName[spineSlot.bone].transform; resetLocalTRS(go); Slot slot = new Slot(); slot.bone = spineSlot.bone; slot.name = spineSlot.name; slot.color = hexStringToColor32(spineSlot.color); slot.gameObject = go; slot.defaultAttachmentName = spineSlot.attachment; slotByName.Add(slot.name, slot); } return(rootGO); }
static void fixeAttachmentNamesIfOmited (SpineData data) { foreach(KeyValuePair<string, SpineSkinSlots>kvp in data.skins){ string skinName = kvp.Key; foreach(KeyValuePair<string, SpineSkinSlotAttachments>kvp2 in data.skins[skinName]){ string slotName = kvp2.Key; foreach(KeyValuePair<string, SpineSkinAttachment> kvp3 in data.skins[skinName][slotName]){ string attachmentName = kvp3.Key; SpineSkinAttachment attachment = kvp3.Value; if (string.IsNullOrEmpty(attachment.name)) attachment.name = attachmentName; // we set actualAttachment(sprite name) here in case if it empty it equal to attachment name } } } }
public static SpineData deserializeFromFile(string spineDataFilePath) { SpineData data = null; if (!File.Exists(spineDataFilePath)) { throw new SpineDatatCreationException("provided file does not exists"); } try{ data = LitJson.JsonMapper.ToObject <SpineData>(File.ReadAllText(spineDataFilePath)); } catch (LitJson.JsonException e) { throw new SpineDatatCreationException("problem with parse json data \n" + e.Message); } setCachedData(data); fixeAttachmentNamesIfOmited(data); return(data); }
static void setCachedData (SpineData data) { data.slotByName = new Dictionary<string, SpineSlot>(); data.boneByName = new Dictionary<string, SpineBone>(); for (int i = 0; i < data.bones.Count; i++) { data.boneByName.Add(data.bones[i].name, data.bones[i]); } data.bonePathByName = new Dictionary<string, string>(); foreach (SpineBone bone in data.bones){ string path = ""; SpineBone b = bone; do { path=b.name+"/"+path; if (!string.IsNullOrEmpty( b.parent)) b = data.boneByName[b.parent]; else b = null; } while (b!=null); if (path.Length >0) path = path.Remove(path.Length - 1); data.bonePathByName.Add(bone.name, path); } data.slotOrder = new Dictionary<string, int>(); data.slotPathByName = new Dictionary<string, string>(); data.slotDefaultAttachments = new Dictionary<string, string>(); for (int i = 0; i < data.slots.Count; i++) { string slotName = data.slots[i].name; string defaultAttachment = data.slots[i].attachment; data.slotOrder.Add(slotName, i); string boneName = data.slots[i].bone; string bonePath = data.bonePathByName[boneName]; string slotPath = bonePath+"/" + SpineUtil.getSlotGOName(slotName); data.slotPathByName.Add(slotName, slotPath); data.slotDefaultAttachments.Add(slotName, defaultAttachment); } }
public static string[] getTransformPaths(GameObject go, SpineData spineData){ List<String> result = new List<string>(); result.Add(""); foreach(Transform t in go.GetComponentsInChildren<Transform>(true)){ string path = AnimationUtility.CalculateTransformPath(t,go.transform); if (t.name.StartsWith(SLOT_PREFIX+" [") && t.name.EndsWith("]")){ string slotName = t.name.Remove(t.name.Length -1); slotName = slotName.Remove(0,(SLOT_PREFIX+" [").Length ); if (spineData.slotPathByName.ContainsKey(slotName) && spineData.slotPathByName[slotName]==path) result.Add(path); }else { if (spineData.bonePathByName.ContainsKey(t.name) && spineData.bonePathByName[t.name]==path) result.Add(path); } } return result.ToArray(); }
public static void builAvatarMask(GameObject gameObject, SpineData spineData, Animator animator, string directory, string name) { Avatar avatar = AvatarBuilder.BuildGenericAvatar(gameObject, ""); animator.avatar = avatar; AvatarMask avatarMask = new AvatarMask(); string[] transofrmPaths = getTransformPaths(gameObject, spineData); avatarMask.transformCount = transofrmPaths.Length; for (int i = 0; i < transofrmPaths.Length; i++) { avatarMask.SetTransformPath(i, transofrmPaths[i]); avatarMask.SetTransformActive(i, true); } createFolderIfNoExists(directory, ANIMATION_FOLDER); AssetDatabase.CreateAsset(avatar, directory + "/" + ANIMATION_FOLDER + "/" + name + ".anim.asset"); AssetDatabase.CreateAsset(avatarMask, directory + "/" + ANIMATION_FOLDER + "/" + name + ".mask.asset"); }
static void fixeAttachmentNamesIfOmited(SpineData data) { foreach (KeyValuePair <string, SpineSkinSlots> kvp in data.skins) { string skinName = kvp.Key; foreach (KeyValuePair <string, SpineSkinSlotAttachments> kvp2 in data.skins[skinName]) { string slotName = kvp2.Key; foreach (KeyValuePair <string, SpineSkinAttachment> kvp3 in data.skins[skinName][slotName]) { string attachmentName = kvp3.Key; SpineSkinAttachment attachment = kvp3.Value; if (string.IsNullOrEmpty(attachment.name)) { attachment.name = attachmentName; // we set actualAttachment(sprite name) here in case if it empty it equal to attachment name } } } } }
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, 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]; string spritePath = spineData.slotPathByName[ 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); GameObject parentGO; GameObject spriteGO; string fixedName = attachmenName.Replace("/",SLASH_REPLACEMENT); if (isDefault){ parentGO = slotGO; spriteGO = new GameObject(fixedName); spritePath += 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); } spritePath += fixedName + "/" + skinName; parentGO = a.gameObject; } attachment.gameObject = spriteGO; attachment.ObPath = spritePath; 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, 0); spriteGO.transform.localRotation = getAttachmentRotation(spineAttachment, spriteByName.rotatedSprites.Contains(sprite)); spriteGO.transform.localScale = getAttachmentScale(spineAttachment); attachment.sprite = sr; } 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); } }
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 addBoneAnimationToClip(AnimationClip clip, Dictionary<string, SpineBoneAnimation> bonesAnimation, SpineData spineData, Dictionary<string, GameObject> boneGOByName, float ratio) { foreach(KeyValuePair<string,SpineBoneAnimation> kvp in bonesAnimation){ string boneName = kvp.Key; GameObject boneGO = boneGOByName[boneName]; SpineBoneAnimation boneAnimation = kvp.Value; string bonePath = spineData.bonePathByName[boneName]; if (boneAnimation.translate != null && boneAnimation.translate.Count > 0){ AnimationCurve curveX = new AnimationCurve(); AnimationCurve curveY = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.translate.Count]; for (int i = 0; i < boneAnimation.translate.Count; i++) { Keyframe keyFrameX = new Keyframe((float)boneAnimation.translate[i].time, boneGO.transform.localPosition.x + (float)boneAnimation.translate[i].x * ratio); Keyframe keyFrameY = new Keyframe((float)boneAnimation.translate[i].time, boneGO.transform.localPosition.y + (float)boneAnimation.translate[i].y * ratio); curveX.AddKey(keyFrameX); curveY.AddKey(keyFrameY); curveData[i] = boneAnimation.translate[i].curve; } setTangents(curveX, curveData); setTangents(curveY, curveData); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalPosition.x") ,curveX); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalPosition.y") ,curveY); } if (boneAnimation.rotate != null && boneAnimation.rotate.Count > 0){ AnimationCurve localRotationX = new AnimationCurve(); AnimationCurve localRotationY = new AnimationCurve(); AnimationCurve localRotationZ = new AnimationCurve(); AnimationCurve localRotationW = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.rotate.Count]; Quaternion baseRotation = Quaternion.identity; for (int i = 0; i < boneAnimation.rotate.Count; i++) { float origAngle = (float)boneAnimation.rotate[i].angle; if (origAngle > 0) origAngle = origAngle > 180 ? origAngle - 360 : origAngle; else origAngle = origAngle < -180 ? origAngle + 360 : origAngle; float newZ = boneGO.transform.localRotation.eulerAngles.z + origAngle; Quaternion angle = Quaternion.Euler(0,0,newZ); float time = (float)boneAnimation.rotate[i].time; curveData[i] = boneAnimation.rotate[i].curve; localRotationX.AddKey(new Keyframe(time, angle.x)); localRotationY.AddKey(new Keyframe(time, angle.y)); localRotationZ.AddKey(new Keyframe(time, angle.z)); localRotationW.AddKey(new Keyframe(time, angle.w)); } fixAngleCurve (localRotationX , curveData, baseRotation.x); fixAngleCurve (localRotationY , curveData, baseRotation.y); fixAngleCurve (localRotationZ , curveData, baseRotation.z); fixAngleCurve (localRotationW , curveData, baseRotation.w); AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalRotation.x"), localRotationX); AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalRotation.y"), localRotationY); AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalRotation.z"), localRotationZ); AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bonePath,typeof(Transform),"m_LocalRotation.w"), localRotationW); } if (boneAnimation.scale != null && boneAnimation.scale.Count > 0){ AnimationCurve scaleX = new AnimationCurve(); AnimationCurve scaleY = new AnimationCurve(); AnimationCurve scaleZ = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.scale.Count]; for (int i = 0; i < boneAnimation.scale.Count; i++) { Keyframe keyFrameX = new Keyframe((float)boneAnimation.scale[i].time, boneGO.transform.localScale.x * (float)boneAnimation.scale[i].x); Keyframe keyFrameY = new Keyframe((float)boneAnimation.scale[i].time, boneGO.transform.localScale.y * (float)boneAnimation.scale[i].y); Keyframe keyFrameZ = new Keyframe((float)boneAnimation.scale[i].time, 1); curveData[i] = boneAnimation.scale[i].curve; scaleX.AddKey(keyFrameX); scaleY.AddKey(keyFrameY); scaleZ.AddKey(keyFrameZ); } setTangents(scaleX,curveData); setTangents(scaleY,curveData); clip.SetCurve(bonePath, typeof(Transform),"localScale.x",scaleX); clip.SetCurve(bonePath, typeof(Transform),"localScale.y",scaleY); clip.SetCurve(bonePath, typeof(Transform),"localScale.z",scaleZ); } } }
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); } }
public static void addDrawOrderAnimation( AnimationClip clip, List<SpineDrawOrderAnimation> orderAnimation, SpineData spineData, float zStep, string animName, Dictionary<string, Slot> slotNameByName ) { string[] BaseSlotOrder = new string[ spineData.slotOrder.Count ]; Dictionary< string, AnimationCurve > Curvs = new Dictionary<string, AnimationCurve>( ); foreach ( KeyValuePair<string, int> p in spineData.slotOrder ) { BaseSlotOrder[ p.Value ] = p.Key; AnimationCurve Curv = new AnimationCurve(); Keyframe keyFrame = new Keyframe( 0.0f, ( - p.Value ) * zStep ); Curv.AddKey( keyFrame ); Curvs[ p.Key ] = Curv; } foreach ( SpineDrawOrderAnimation orderAnim in orderAnimation ) { string[] NewSlotOrder = null; if ( orderAnim.offsets != null ) { NewSlotOrder = new string[ BaseSlotOrder.Length ]; string[] BaseOrder_Copy = BaseSlotOrder.Clone( ) as string[]; for ( int i = 0; i != orderAnim.offsets.Length; i++ ) { SpineDrawOrderAnimationSlot slot = orderAnim.offsets[ i ]; int newIdx = spineData.slotOrder[ slot.slot ] + slot.offset; NewSlotOrder[ newIdx ] = slot.slot; int base_idx = Array.IndexOf( BaseOrder_Copy, slot.slot ); BaseOrder_Copy[ base_idx ] = null; } int pos = 0; for ( int i = 0; i != NewSlotOrder.Length; i++ ) { if ( NewSlotOrder[ i ] == null ) { bool found = false; for ( ; pos != BaseOrder_Copy.Length; ) { if ( BaseOrder_Copy[ pos ] != null ) { found = true; NewSlotOrder[ i ] = BaseOrder_Copy[ pos ]; pos++; break; } else pos++; } if ( !found ) Debug.LogError( "Can't create new draw order" ); } } } else NewSlotOrder = BaseSlotOrder; for ( int j = 0; j != NewSlotOrder.Length; j++ ) { float t = ( float )orderAnim.time; float val = ( - j ) * zStep; AnimationCurve curv = Curvs[ NewSlotOrder[ j ] ]; float priv_val = curv.Evaluate( t ); if ( t > 0.0f ) { Keyframe keyFrameY_help = new Keyframe( t - 0.00001f, priv_val ); Keyframe keyFrameY = new Keyframe( t, val ); curv.AddKey( keyFrameY_help ); curv.AddKey( keyFrameY ); } else { Keyframe keyFrameY = new Keyframe( t, val ); curv.AddKey( keyFrameY ); } } } for ( int i = 0; i != BaseSlotOrder.Length; i++ ) { string slotpath = spineData.slotPathByName[ BaseSlotOrder[ i ] ]; AnimationCurve curv = Curvs[ BaseSlotOrder[ i ] ]; AnimationUtility.SetEditorCurve( clip, EditorCurveBinding.FloatCurve( slotpath, typeof( Transform ), "m_LocalPosition.z" ), curv ); } }
public static SkinController addSkinController(GameObject gameObject, SpineData spineData, List<Skin> allSkins, Dictionary<string, Slot> slotByName) { SkinController sk = gameObject.AddComponent<SkinController>(); List<Skin> skins = new List<Skin>(); Skin defaultSkin = null; foreach(Skin skin in allSkins){ if (skin.name.Equals("default")){ defaultSkin = skin; } else { skins.Add(skin); } } sk.defaultSkin = defaultSkin; sk.skins = skins.ToArray(); Slot[] slots = new Slot[slotByName.Count]; slotByName.Values.CopyTo(slots,0); sk.slots = slots; return sk; }
public static void addSlotAnimationToClip(AnimationClip clip, Dictionary<string, SpineSlotAnimation> slotsAnimation, SpineData spineData, List<Skin> skinList, 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){ AnimationCurve Curv_R = new AnimationCurve( ); AnimationCurve Curv_G = new AnimationCurve( ); AnimationCurve Curv_B = new AnimationCurve( ); AnimationCurve Curv_A = new AnimationCurve( ); Keyframe startKeyFrame = new Keyframe( 0.0f, 1.0f ); Curv_R.AddKey( startKeyFrame ); Curv_G.AddKey( startKeyFrame ); Curv_B.AddKey( startKeyFrame ); Curv_A.AddKey( startKeyFrame ); JsonData[] curveData = new JsonData[ slotAnimation.color.Count ]; for( int i = 0 ; i != slotAnimation.color.Count ;i++ ) { SpineSlotColorAnimation color = slotAnimation.color[ i ]; uint col = Convert.ToUInt32( color.color, 16 ); uint r = ( col ) >> 24; uint g = (col & 0xff0000) >> 16; uint b = (col & 0xff00) >> 8; uint a = (col & 0xff); float t = ( (float) (color.time) ); Keyframe keyFrame_R = new Keyframe( t, r / 255.0f ); Keyframe keyFrame_G = new Keyframe( t, g / 255.0f ); Keyframe keyFrame_B = new Keyframe( t, b / 255.0f ); Keyframe keyFrame_A = new Keyframe( t, a / 255.0f ); Curv_R.AddKey( keyFrame_R ); Curv_G.AddKey( keyFrame_G ); Curv_B.AddKey( keyFrame_B ); Curv_A.AddKey( keyFrame_A ); curveData[ i ] = color.curve; } setTangents( Curv_R, curveData ); setTangents( Curv_G, curveData ); setTangents( Curv_B, curveData ); setTangents( Curv_A, curveData ); for ( int i = 0; i != skinList.Count; i++ ) { if ( skinList[ i ].containsSlot( slotName ) ) { SkinSlot skinSlot = skinList[ i ][ slotName ]; for ( int j = 0; j != skinSlot.attachments.Length; j++ ) { SpriteRenderer sprite = skinSlot.attachments[ j ].sprite; if ( sprite != null ) { string spritePath = skinSlot.attachments[ j ].ObPath; AnimationUtility.SetEditorCurve( clip, EditorCurveBinding.FloatCurve( spritePath, typeof( SpriteRenderer ), "m_Color.r" ), Curv_R ); AnimationUtility.SetEditorCurve( clip, EditorCurveBinding.FloatCurve( spritePath, typeof( SpriteRenderer ), "m_Color.g" ), Curv_G ); AnimationUtility.SetEditorCurve( clip, EditorCurveBinding.FloatCurve( spritePath, typeof( SpriteRenderer ), "m_Color.b" ), Curv_B ); AnimationUtility.SetEditorCurve( clip, EditorCurveBinding.FloatCurve( spritePath, typeof( SpriteRenderer ), "m_Color.a" ), Curv_A ); } } } } Debug.LogWarning("slot color animation is not supported yet"); } } }
public static void addAnimation(GameObject rootGO, string rootDirectory, SpineData spineData, Dictionary<string, GameObject> boneGOByName, Dictionary<string, Slot> slotByName, AttachmentGOByNameBySlot attachmentGOByNameBySlot, List<Skin> skinList, int pixelsPerUnit, float zStep, bool useLegacyAnimation, 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; } } animationClip.legacy = useLegacyAnimation; if (spineAnimation.bones!=null) addBoneAnimationToClip(animationClip,spineAnimation.bones, spineData, boneGOByName, ratio); if (spineAnimation.slots!=null) addSlotAnimationToClip(animationClip, spineAnimation.slots, spineData, skinList, attachmentGOByNameBySlot); if ( spineAnimation.events != null ) AddEvents( animationClip, spineAnimation.events, animationName ); if (spineAnimation.draworder!=null) addDrawOrderAnimation( animationClip, spineAnimation.draworder, spineData, zStep, animationName, slotByName ); if (updateCurve){ EditorUtility.SetDirty(animationClip); AssetDatabase.SaveAssets(); } else { animationClip.frameRate = 30; createFolderIfNoExists(rootDirectory, ANIMATION_FOLDER); AssetDatabase.CreateAsset(animationClip, assetPath); AssetDatabase.SaveAssets(); if (useLegacyAnimation){ AddClipToLegacyAnimationComponent(rootGO, animationClip); } else { AddClipToAnimatorComponent(rootGO,animationClip); } } } }
public static void addBoneAnimationToClip(AnimationClip clip, Dictionary <string, SpineBoneAnimation> bonesAnimation, SpineData spineData, Dictionary <string, GameObject> boneGOByName, float ratio) { foreach (KeyValuePair <string, SpineBoneAnimation> kvp in bonesAnimation) { string boneName = kvp.Key; GameObject boneGO = boneGOByName[boneName]; SpineBoneAnimation boneAnimation = kvp.Value; string bonePath = spineData.bonePathByName[boneName]; if (boneAnimation.translate != null && boneAnimation.translate.Count > 0) { AnimationCurve curveX = new AnimationCurve(); AnimationCurve curveY = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.translate.Count]; for (int i = 0; i < boneAnimation.translate.Count; i++) { Keyframe keyFrameX = new Keyframe((float)boneAnimation.translate[i].time, boneGO.transform.localPosition.x + (float)boneAnimation.translate[i].x * ratio); Keyframe keyFrameY = new Keyframe((float)boneAnimation.translate[i].time, boneGO.transform.localPosition.y + (float)boneAnimation.translate[i].y * ratio); curveX.AddKey(keyFrameX); curveY.AddKey(keyFrameY); curveData[i] = boneAnimation.translate[i].curve; } setTangents(curveX, curveData); setTangents(curveY, curveData); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalPosition.x"), curveX); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalPosition.y"), curveY); } if (boneAnimation.rotate != null && boneAnimation.rotate.Count > 0) { AnimationCurve localRotationX = new AnimationCurve(); AnimationCurve localRotationY = new AnimationCurve(); AnimationCurve localRotationZ = new AnimationCurve(); AnimationCurve localRotationW = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.rotate.Count]; for (int i = 0; i < boneAnimation.rotate.Count; i++) { float origAngle = (float)boneAnimation.rotate[i].angle; if (origAngle > 0) { origAngle = origAngle > 180 ? origAngle - 360 : origAngle; } else { origAngle = origAngle < -180 ? origAngle + 360 : origAngle; } float newZ = boneGO.transform.localRotation.eulerAngles.z + origAngle; Quaternion angle = Quaternion.Euler(0, 0, newZ); float time = (float)boneAnimation.rotate[i].time; curveData[i] = boneAnimation.rotate[i].curve; localRotationX.AddKey(new Keyframe(time, angle.x)); localRotationY.AddKey(new Keyframe(time, angle.y)); localRotationZ.AddKey(new Keyframe(time, angle.z)); localRotationW.AddKey(new Keyframe(time, angle.w)); } fixAngles(localRotationX, curveData); setTangents(localRotationX, curveData); fixAngles(localRotationY, curveData); setTangents(localRotationY, curveData); fixAngles(localRotationZ, curveData); setTangents(localRotationZ, curveData); fixAngles(localRotationW, curveData); setTangents(localRotationW, curveData); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalRotation.x"), localRotationX); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalRotation.y"), localRotationY); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalRotation.z"), localRotationZ); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bonePath, typeof(Transform), "m_LocalRotation.w"), localRotationW); } if (boneAnimation.scale != null && boneAnimation.scale.Count > 0) { AnimationCurve scaleX = new AnimationCurve(); AnimationCurve scaleY = new AnimationCurve(); AnimationCurve scaleZ = new AnimationCurve(); JsonData[] curveData = new JsonData[boneAnimation.scale.Count]; for (int i = 0; i < boneAnimation.scale.Count; i++) { Keyframe keyFrameX = new Keyframe((float)boneAnimation.scale[i].time, boneGO.transform.localScale.x * (float)boneAnimation.scale[i].x); Keyframe keyFrameY = new Keyframe((float)boneAnimation.scale[i].time, boneGO.transform.localScale.y * (float)boneAnimation.scale[i].y); Keyframe keyFrameZ = new Keyframe((float)boneAnimation.scale[i].time, 1); curveData[i] = boneAnimation.scale[i].curve; scaleX.AddKey(keyFrameX); scaleY.AddKey(keyFrameY); scaleZ.AddKey(keyFrameZ); } setTangents(scaleX, curveData); setTangents(scaleY, curveData); clip.SetCurve(bonePath, typeof(Transform), "localScale.x", scaleX); clip.SetCurve(bonePath, typeof(Transform), "localScale.y", scaleY); clip.SetCurve(bonePath, typeof(Transform), "localScale.z", scaleZ); } } }
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++) { SpineSlotAttachmentAnimation anim = slotAnimation.attachment[i]; if (string.IsNullOrEmpty( anim.name)) 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, 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, 1, TangentMode.Stepped)); if (i< (slotAnimation.attachment.Count - 1)){ SpineSlotAttachmentAnimation nextAnim = slotAnimation.attachment[i+1]; if (!nextAnim.name.Equals(anim.name)) 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 GameObject buildSceleton( string name, SpineData data, int pixelsPerUnit, float zStep, out Dictionary<string, GameObject> boneGOByName, out Dictionary<string, Slot> slotByName ) { float ratio = 1.0f / (float)pixelsPerUnit; boneGOByName = new Dictionary<string, GameObject>(); slotByName = new Dictionary<string, Slot>(); GameObject rootGO = new GameObject(name); foreach(SpineBone bone in data.bones){ GameObject go = new GameObject(bone.name); boneGOByName.Add(bone.name, go); } foreach(SpineBone bone in data.bones){ GameObject go = boneGOByName[bone.name]; if (bone.parent == null) go.transform.parent = rootGO.transform; else go.transform.parent = boneGOByName[bone.parent].transform; Vector3 position = new Vector3((float)bone.x * ratio, (float)bone.y * ratio, 0.0f); Vector3 scale = new Vector3((float)bone.scaleX, (float)bone.scaleY, 1.0f); Quaternion rotation = Quaternion.Euler(0, 0, (float)bone.rotation); go.transform.localPosition = position; go.transform.localScale = scale; go.transform.localRotation = rotation; } foreach(SpineSlot spineSlot in data.slots){ GameObject go = new GameObject(getSlotGOName(spineSlot.name)); go.transform.parent = boneGOByName[spineSlot.bone].transform; resetLocalTRS(go); int drawOrder = data.slotOrder[ spineSlot.name ]; go.transform.localPosition = new Vector3( 0, 0, (- drawOrder ) * zStep ); Slot slot = new Slot(); slot.bone = spineSlot.bone; slot.name = spineSlot.name; slot.color = hexStringToColor32(spineSlot.color); slot.gameObject = go; slot.defaultAttachmentName = spineSlot.attachment; slotByName.Add(slot.name, slot); } return rootGO; }
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); } } }