private static AnimationClip GenerateTriggerableTransition(string name, UnityEditor.Animations.AnimatorController controller) { // Create the clip var clip = UnityEditor.Animations.AnimatorController.AllocateAnimatorClip(name); AssetDatabase.AddObjectToAsset(clip, controller); // Create a state in the animatior controller for this clip var state = controller.AddMotion(clip); // Add a transition property controller.AddParameter(name, AnimatorControllerParameterType.Trigger); // Add an any state transition var stateMachine = controller.layers[0].stateMachine; var transition = stateMachine.AddAnyStateTransition(state); transition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, name); return(clip); }
public static void BakeToPrefab (SkeletonDataAsset skeletonDataAsset, ExposedList<Skin> skins, string outputPath = "", bool bakeAnimations = true, bool bakeIK = true, SendMessageOptions eventOptions = SendMessageOptions.DontRequireReceiver) { if (skeletonDataAsset == null || skeletonDataAsset.GetSkeletonData(true) == null) { Debug.LogError("Could not export Spine Skeleton because SkeletonDataAsset is null or invalid!"); return; } #if !NEW_PREFAB_SYSTEM if (outputPath == "") { outputPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(skeletonDataAsset)) + "/Baked"; System.IO.Directory.CreateDirectory(outputPath); } var skeletonData = skeletonDataAsset.GetSkeletonData(true); bool hasAnimations = bakeAnimations && skeletonData.Animations.Count > 0; UnityEditor.Animations.AnimatorController controller = null; if (hasAnimations) { string controllerPath = outputPath + "/" + skeletonDataAsset.skeletonJSON.name + " Controller.controller"; bool newAnimContainer = false; var runtimeController = AssetDatabase.LoadAssetAtPath(controllerPath, typeof(RuntimeAnimatorController)); if (runtimeController != null) { controller = (UnityEditor.Animations.AnimatorController)runtimeController; } else { controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(controllerPath); newAnimContainer = true; } var existingClipTable = new Dictionary<string, AnimationClip>(); var unusedClipNames = new List<string>(); Object[] animObjs = AssetDatabase.LoadAllAssetsAtPath(controllerPath); foreach (Object o in animObjs) { if (o is AnimationClip) { var clip = (AnimationClip)o; existingClipTable.Add(clip.name, clip); unusedClipNames.Add(clip.name); } } Dictionary<int, List<string>> slotLookup = new Dictionary<int, List<string>>(); int skinCount = skins.Count; for (int s = 0; s < skeletonData.Slots.Count; s++) { List<string> attachmentNames = new List<string>(); for (int i = 0; i < skinCount; i++) { var skin = skins.Items[i]; List<string> temp = new List<string>(); skin.FindNamesForSlot(s, temp); foreach (string str in temp) { if (!attachmentNames.Contains(str)) attachmentNames.Add(str); } } slotLookup.Add(s, attachmentNames); } foreach (var anim in skeletonData.Animations) { AnimationClip clip = null; if (existingClipTable.ContainsKey(anim.Name)) { clip = existingClipTable[anim.Name]; } clip = ExtractAnimation(anim.Name, skeletonData, slotLookup, bakeIK, eventOptions, clip); if (unusedClipNames.Contains(clip.name)) { unusedClipNames.Remove(clip.name); } else { AssetDatabase.AddObjectToAsset(clip, controller); controller.AddMotion(clip); } } if (newAnimContainer) { EditorUtility.SetDirty(controller); AssetDatabase.SaveAssets(); AssetDatabase.ImportAsset(controllerPath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); } else { foreach (string str in unusedClipNames) { AnimationClip.DestroyImmediate(existingClipTable[str], true); } EditorUtility.SetDirty(controller); AssetDatabase.SaveAssets(); AssetDatabase.ImportAsset(controllerPath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); } } foreach (var skin in skins) { bool newPrefab = false; string prefabPath = outputPath + "/" + skeletonDataAsset.skeletonJSON.name + " (" + skin.Name + ").prefab"; Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefab == null) { prefab = PrefabUtility.CreateEmptyPrefab(prefabPath); newPrefab = true; } Dictionary<string, Mesh> meshTable = new Dictionary<string, Mesh>(); List<string> unusedMeshNames = new List<string>(); Object[] assets = AssetDatabase.LoadAllAssetsAtPath(prefabPath); foreach (var obj in assets) { if (obj is Mesh) { meshTable.Add(obj.name, (Mesh)obj); unusedMeshNames.Add(obj.name); } } GameObject prefabRoot = SpineEditorUtilities.EditorInstantiation.NewGameObject("root"); Dictionary<string, Transform> slotTable = new Dictionary<string, Transform>(); Dictionary<string, Transform> boneTable = new Dictionary<string, Transform>(); List<Transform> boneList = new List<Transform>(); //create bones for (int i = 0; i < skeletonData.Bones.Count; i++) { var boneData = skeletonData.Bones.Items[i]; Transform boneTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(boneData.Name).transform; boneTransform.parent = prefabRoot.transform; boneTable.Add(boneTransform.name, boneTransform); boneList.Add(boneTransform); } for (int i = 0; i < skeletonData.Bones.Count; i++) { var boneData = skeletonData.Bones.Items[i]; Transform boneTransform = boneTable[boneData.Name]; Transform parentTransform = null; if (i > 0) parentTransform = boneTable[boneData.Parent.Name]; else parentTransform = boneTransform.parent; boneTransform.parent = parentTransform; boneTransform.localPosition = new Vector3(boneData.X, boneData.Y, 0); var tm = boneData.TransformMode; if (tm.InheritsRotation()) boneTransform.localRotation = Quaternion.Euler(0, 0, boneData.Rotation); else boneTransform.rotation = Quaternion.Euler(0, 0, boneData.Rotation); if (tm.InheritsScale()) boneTransform.localScale = new Vector3(boneData.ScaleX, boneData.ScaleY, 1); } //create slots and attachments for (int i = 0; i < skeletonData.Slots.Count; i++) { var slotData = skeletonData.Slots.Items[i]; Transform slotTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(slotData.Name).transform; slotTransform.parent = prefabRoot.transform; slotTable.Add(slotData.Name, slotTransform); List<Attachment> attachments = new List<Attachment>(); List<string> attachmentNames = new List<string>(); skin.FindAttachmentsForSlot(i, attachments); skin.FindNamesForSlot(i, attachmentNames); if (skin != skeletonData.DefaultSkin) { skeletonData.DefaultSkin.FindAttachmentsForSlot(i, attachments); skeletonData.DefaultSkin.FindNamesForSlot(i, attachmentNames); } for (int a = 0; a < attachments.Count; a++) { var attachment = attachments[a]; string attachmentName = attachmentNames[a]; string attachmentMeshName = "[" + slotData.Name + "] " + attachmentName; Vector3 offset = Vector3.zero; float rotation = 0; Mesh mesh = null; Material material = null; bool isWeightedMesh = false; if (meshTable.ContainsKey(attachmentMeshName)) mesh = meshTable[attachmentMeshName]; if (attachment is RegionAttachment) { var regionAttachment = (RegionAttachment)attachment; offset.x = regionAttachment.X; offset.y = regionAttachment.Y; rotation = regionAttachment.Rotation; mesh = ExtractRegionAttachment(attachmentMeshName, regionAttachment, mesh); material = attachment.GetMaterial(); unusedMeshNames.Remove(attachmentMeshName); if (newPrefab || meshTable.ContainsKey(attachmentMeshName) == false) AssetDatabase.AddObjectToAsset(mesh, prefab); } else if (attachment is MeshAttachment) { var meshAttachment = (MeshAttachment)attachment; isWeightedMesh = (meshAttachment.Bones != null); offset.x = 0; offset.y = 0; rotation = 0; if (isWeightedMesh) mesh = ExtractWeightedMeshAttachment(attachmentMeshName, meshAttachment, i, skeletonData, boneList, mesh); else mesh = ExtractMeshAttachment(attachmentMeshName, meshAttachment, mesh); material = attachment.GetMaterial(); unusedMeshNames.Remove(attachmentMeshName); if (newPrefab || meshTable.ContainsKey(attachmentMeshName) == false) AssetDatabase.AddObjectToAsset(mesh, prefab); } else continue; Transform attachmentTransform = SpineEditorUtilities.EditorInstantiation.NewGameObject(attachmentName).transform; attachmentTransform.parent = slotTransform; attachmentTransform.localPosition = offset; attachmentTransform.localRotation = Quaternion.Euler(0, 0, rotation); if (isWeightedMesh) { attachmentTransform.position = Vector3.zero; attachmentTransform.rotation = Quaternion.identity; var skinnedMeshRenderer = attachmentTransform.gameObject.AddComponent<SkinnedMeshRenderer>(); skinnedMeshRenderer.rootBone = boneList[0]; skinnedMeshRenderer.bones = boneList.ToArray(); skinnedMeshRenderer.sharedMesh = mesh; } else { attachmentTransform.gameObject.AddComponent<MeshFilter>().sharedMesh = mesh; attachmentTransform.gameObject.AddComponent<MeshRenderer>(); } attachmentTransform.GetComponent<Renderer>().sharedMaterial = material; attachmentTransform.GetComponent<Renderer>().sortingOrder = i; if (attachmentName != slotData.AttachmentName) attachmentTransform.gameObject.SetActive(false); } } foreach (var slotData in skeletonData.Slots) { Transform slotTransform = slotTable[slotData.Name]; slotTransform.parent = boneTable[slotData.BoneData.Name]; slotTransform.localPosition = Vector3.zero; slotTransform.localRotation = Quaternion.identity; slotTransform.localScale = Vector3.one; } if (hasAnimations) { var animator = prefabRoot.AddComponent<Animator>(); animator.applyRootMotion = false; animator.runtimeAnimatorController = (RuntimeAnimatorController)controller; EditorGUIUtility.PingObject(controller); } if (newPrefab) { PrefabUtility.ReplacePrefab(prefabRoot, prefab, ReplacePrefabOptions.ConnectToPrefab); } else { foreach (string str in unusedMeshNames) { Mesh.DestroyImmediate(meshTable[str], true); } PrefabUtility.ReplacePrefab(prefabRoot, prefab, ReplacePrefabOptions.ReplaceNameBased); } EditorGUIUtility.PingObject(prefab); AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); GameObject.DestroyImmediate(prefabRoot); } #endif }
public static UnityEditor.Animations.AnimatorController CreateAnimatorControllerAtPathWithClip(string path, AnimationClip clip) { UnityEditor.Animations.AnimatorController controller = CreateAnimatorControllerAtPath(path); controller.AddMotion(clip); return(controller); }
static void ImportScml(string assetPath) { string folderPath = Path.GetDirectoryName(assetPath); //Load the SCML as XML var doc = new XmlDocument(); doc.Load(assetPath); //Parse the SCML file var scml = new Spriter.ScmlObject(doc); //TODO: Verify that all files/folders exist var pb = new PrefabBuilder(); foreach (var entity in scml.Entities) { //TODO: Settings file to customize prefab location var prefabPath = Path.Combine(folderPath, entity.Name + ".prefab"); //Change to forward slash for asset database friendliness prefabPath = prefabPath.Replace('\\', '/'); //Either instantiate the existing prefab or create a new one GameObject go; var prefabGo = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)); if (prefabGo == null) { go = new GameObject(); prefabGo = PrefabUtility.CreatePrefab(prefabPath, go, ReplacePrefabOptions.ConnectToPrefab); } else { go = GameObject.Instantiate(prefabGo) as GameObject; var oldAnimator = go.GetComponent <Animator>(); if (oldAnimator) { GameObject.DestroyImmediate(oldAnimator); } } //Build the prefab based on the supplied entity pb.MakePrefab(entity, go, folderPath); var animator = go.AddComponent <Animator>(); //Add animations to prefab object var anim = new AnimationBuilder(); var allAnimClips = anim.BuildAnimationClips(go, entity, prefabPath); AssetDatabase.SaveAssets(); var animatorControllerPath = Path.ChangeExtension(prefabPath, "controller"); UnityEditor.Animations.AnimatorController oldController = (UnityEditor.Animations.AnimatorController)AssetDatabase.LoadAssetAtPath(animatorControllerPath, typeof(UnityEditor.Animations.AnimatorController)); UnityEditor.Animations.AnimatorController controller = oldController; if (!oldController) { controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(animatorControllerPath); foreach (var animationClip in allAnimClips) { if (animationClip) { #if UNITY_5 controller.AddMotion(animationClip); #else AnimatorController.AddAnimationClipToController(controller, animationClip); #endif } } } UnityEditor.Animations.AnimatorController.SetAnimatorController(animator, controller); go.SetActive(true); //Update the prefab PrefabUtility.ReplacePrefab(go, prefabGo, ReplacePrefabOptions.ConnectToPrefab); //Add a generic avatar - because why not? //TODO: May need to eventually break this into a separate class // ie: if we want to look for a root motion node by naming convention //var avatar = AvatarBuilder.BuildGenericAvatar(go, ""); //avatar.name = go.name; //AssetDatabase.AddObjectToAsset(avatar, prefabPath); GameObject.DestroyImmediate(go); AssetDatabase.SaveAssets(); } }