Esempio n. 1
0
        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

		}
Esempio n. 3
0
 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();
            }
        }