bool DoFix() { //AnimationClip ac = Selection.activeObject as AnimationClip; { List <AnimationClip> animations = new List <AnimationClip>(ac); if (animations.Contains(null)) { error = "AnimationClip缺失"; return(false); } } if (target == null) { error = "Target丢失"; return(false); } GameObject root = target; int a = 0; //获取所有绑定的EditorCurveBinding(包含path和propertyName) foreach (AnimationClip animation in ac) { if (animation != null) { EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(animation); for (int i = 0; i < bindings.Length; ++i) { EditorCurveBinding binding = bindings[i]; Keyframe[] keyframes = AnimationUtility.GetEditorCurve(animation, binding).keys; foreach (Keyframe keyframe in keyframes) { Debug.Log("Keyframe " + binding.propertyName + ":" + keyframe.value); } Transform bindTransform = root.transform.Find(binding.path); if (!bindTransform) { GameObject bindObj = FindInChildren(root, binding.path); if (bindObj) { string newPath = AnimationUtility.CalculateTransformPath(bindObj.transform, root.transform); Debug.Log("change " + binding.path + " to " + newPath); AnimationCurve curve = AnimationUtility.GetEditorCurve(animation, binding); //remove Old AnimationUtility.SetEditorCurve(animation, binding, null); binding.path = newPath; AnimationUtility.SetEditorCurve(animation, binding, curve); } } } } else { Debug.Log("animation[" + a + "] == null"); } a++; } return(true); }
void DrawCurveEditor() { if (_selectedCurve == null) { return; // Only if any selected } EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Space(padding); EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); EditorGUILayout.LabelField("Path", GUILayout.Width(labelWidth)); _selectedCurve.UpdatePath(EditorGUILayout.TextField(_selectedCurve.path)); if (GUILayout.Button("Get From Scene Selection") && Selection.activeTransform != null) { _selectedCurve.UpdatePath(AnimationUtility.CalculateTransformPath(Selection.activeTransform, Selection.activeTransform.root)); Repaint(); } GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); EditorGUILayout.LabelField("Property", GUILayout.Width(labelWidth)); _selectedCurve.UpdatePropertyName(EditorGUILayout.TextField(_selectedCurve.propertyName)); GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); // Curve editor box. EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Space(padding); // Timestamps. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); GUIStyle style = smallFontStyle; EditorGUILayout.LabelField(_selectedCurve.startTimeString, style); GUILayout.FlexibleSpace(); style.alignment = TextAnchor.MiddleRight; EditorGUILayout.LabelField(_selectedCurve.endTimeString, style); GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); // Keyframes. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.Height(keyframesAreaHeight)); GUILayout.Space(padding); Rect keyframesArea = EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.Height(keyframesAreaHeight)); GUILayout.Space(padding); // Draw grid. GUI.DrawTexture(new Rect(keyframesArea.x, keyframesArea.y, keyframesArea.width, keyframesLineHeight), lineTexture); GUI.DrawTexture(new Rect(keyframesArea.x, keyframesArea.y + keyframesAreaHeight - keyframesLineHeight, keyframesArea.width, keyframesLineHeight), lineTexture); GUI.DrawTexture(new Rect(keyframesArea.x, keyframesArea.y, keyframesMarkerWidth, keyframesArea.height), transparentGrayTexture); GUI.DrawTexture(new Rect(keyframesArea.x + keyframesArea.width - keyframesMarkerWidth, keyframesArea.y, keyframesMarkerWidth, keyframesArea.height), transparentGrayTexture); // Actual keyframes. if (_selectedCurve.animationCurve != null) { for (int eachKeyframeIndex = 0; eachKeyframeIndex < _selectedCurve.animationCurve.keys.Length; eachKeyframeIndex++) { // Model. Keyframe eachKeyframe = _selectedCurve.animationCurve.keys[eachKeyframeIndex]; // Positioning. float left = (keyframesArea.width - 1.0f) * ((eachKeyframe.time - _selectedCurve.startTime) / _selectedCurve.duration); Rect eachKeyframeRect = new Rect( keyframesArea.x + left - Mathf.Floor(keyframeIconSize / 2.0f), keyframesArea.y + 5.0f, keyframeIconSize, keyframeIconSize ); Rect eachKeyframeTextureRect = new Rect( eachKeyframeRect.x, eachKeyframeRect.y, iconSize, iconSize ); // Draw. Texture2D eachTexture = keyframeTexture; bool isKeyframeSelected = (_selectedKeyframeIndex == eachKeyframeIndex); if (isKeyframeSelected) { eachTexture = keyframeSelectedTexture; } GUI.DrawTexture(eachKeyframeTextureRect, eachTexture); // Events. if (IsRectClicked(eachKeyframeRect)) { // Select clicked. _selectedKeyframeIndex = eachKeyframeIndex; Repaint(); } } } GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); // Tangent Clipboard. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); if (GUILayout.Button("Copy Keyframe Tangents")) { CopyKeyframeTangents(_selectedKeyframeIndex); } bool keysChanged = false; if (GUILayout.Button("Paste Keyframe Tangents")) { if (Event.current.type != EventType.Layout && Event.current.type != EventType.Repaint) { PasteKeyframeTangents(_selectedKeyframeIndex); keysChanged = true; ModelChanged(); } } GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); // Actual curve. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); // Temporary model to avoid `CurveField` cache. AnimationCurve curve = _selectedCurve.animationCurve; if (keysChanged) { curve = new AnimationCurve(); curve.keys = _selectedCurve.animationCurve.keys; curve.preWrapMode = _selectedCurve.animationCurve.preWrapMode; curve.postWrapMode = _selectedCurve.animationCurve.postWrapMode; } _selectedCurve.animationCurve = EditorGUILayout.CurveField(curve, GUILayout.Height(40.0f)); GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); // Curve Clipboard. EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Space(padding); if (GUILayout.Button("Copy Entire Curve")) { _clipboard.curve = _selectedCurve; } if (GUILayout.Button("Paste Entire Curve")) { _selectedCurve.PasteCurveData(_clipboard.curve); ModelChanged(); } GUILayout.Space(padding); EditorGUILayout.EndHorizontal(); GUILayout.Space(padding); EditorGUILayout.EndVertical(); // End of Keyframes EditorGUILayout.EndVertical(); // End of Curves }
// private method private void _ConvertAnim_original(string newClipAssetPath) { // 0. prepare if (!m_Animator.isHuman) { Dbg.LogWarn("MuscleClipConverterEditor._ConvertAnim: Need to change to Humanoid rig first!"); return; } m_SMR = m_Animator.GetComponentInChildren <SkinnedMeshRenderer>(); if (m_SMR == null) { Dbg.LogWarn("MuscleClipConverterEditor._ConvertAnim: failed to find SMR under {0}", m_Animator.name); return; } m_Animator.Update(0); #if !U5 var ainfos = m_Animator.GetCurrentAnimationClipState(0); //only effect after Update is called #else var ainfos = m_Animator.GetCurrentAnimatorClipInfo(0); //only effect after Update is called #endif AnimationClip clip = ainfos[0].clip; AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(clip); //{//debug // var bindings = AnimationUtility.GetCurveBindings(clip); // foreach( var b in bindings) // { // Dbg.Log("path: {0}, prop: {1}", b.path, b.propertyName); // } //} Transform animatorTr = m_Animator.transform; Transform hipsBone = null; CurveDict curveDict = new CurveDict(); float SAMPLE_RATE = clip.frameRate; float clipLen = clip.length; Matrix4x4 animatorInitW2LMat = animatorTr.worldToLocalMatrix; Matrix4x4 hipsInitW2LMat = Matrix4x4.identity; List <Transform> boneLst = new List <Transform>(); for (HumanBodyBones boneIdx = 0; boneIdx < HumanBodyBones.LastBone; ++boneIdx) { Transform tr = m_Animator.GetBoneTransform(boneIdx); //Dbg.Log("Map: {0}->{1}", boneIdx, tr); if (tr != null) { boneLst.Add(tr); if (boneIdx == HumanBodyBones.Hips) { hipsBone = tr; hipsInitW2LMat = hipsBone.parent.worldToLocalMatrix; //clipSetting.level = -hipsBone.localPosition.y; // set Y offset clipSetting.keepOriginalPositionY = false; //use RootNode position } } } Transform[] bones = boneLst.ToArray(); // init curves for each bone for (int idx = 0; idx < bones.Length; ++idx) { Transform oneBone = bones[idx]; string trPath = AnimationUtility.CalculateTransformPath(oneBone, animatorTr); var curves = new _Curves(); curves.relPath = trPath; curveDict.Add(oneBone, curves); } // init rootmotion curve { var curves = new _Curves(); curveDict.Add(animatorTr, curves); } AnimatorStateInfo curStateInfo = m_Animator.GetCurrentAnimatorStateInfo(0); float nt = curStateInfo.normalizedTime; m_Animator.Update(-nt * clipLen); //revert to 0 time { // 1. bake animation info into curve on all bones transform float time = 0f; float deltaTime = 1f / (SAMPLE_RATE); for (; time <= clipLen || Mathf.Approximately(time, clipLen); ) { //Dbg.Log("nt = {0}", m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime); // bone for (int idx = 0; idx < bones.Length; ++idx) { Transform oneBone = bones[idx]; _Curves curves = curveDict[oneBone]; if (oneBone == hipsBone) { continue; //skip the HipsBone. This is to add rootMotion matrix on hips, so Legacy is right } Vector3 pos = oneBone.localPosition; Quaternion rot = oneBone.localRotation; curves.X.AddKey(time, rot.x); curves.Y.AddKey(time, rot.y); curves.Z.AddKey(time, rot.z); curves.W.AddKey(time, rot.w); curves.PX.AddKey(time, pos.x); curves.PY.AddKey(time, pos.y); curves.PZ.AddKey(time, pos.z); } // root motion process { { //on Animator transform Vector3 pos = /*animatorTr.localPosition*/ animatorTr.position; Vector3 fwd = animatorTr.forward; Vector3 up = animatorTr.up; _Curves rootMotionCurves = curveDict[animatorTr]; Vector3 lpos = animatorInitW2LMat.MultiplyPoint(pos); Vector3 lfwd = animatorInitW2LMat.MultiplyVector(fwd); Vector3 lup = animatorInitW2LMat.MultiplyVector(up); Quaternion rot = Quaternion.LookRotation(lfwd, lup); rootMotionCurves.X.AddKey(time, rot.x); rootMotionCurves.Y.AddKey(time, rot.y); rootMotionCurves.Z.AddKey(time, rot.z); rootMotionCurves.W.AddKey(time, rot.w); rootMotionCurves.PX.AddKey(time, lpos.x); rootMotionCurves.PY.AddKey(time, lpos.y); rootMotionCurves.PZ.AddKey(time, lpos.z); } { //on hips transform if (hipsBone != null) { Vector3 pos = hipsBone.position; Vector3 fwd = hipsBone.forward; Vector3 up = hipsBone.up; _Curves hipsCurves = curveDict[hipsBone]; Vector3 lpos = hipsInitW2LMat.MultiplyPoint(pos); Vector3 lfwd = hipsInitW2LMat.MultiplyVector(fwd); Vector3 lup = hipsInitW2LMat.MultiplyVector(up); //Dbg.Log("time: {0}, lpos: {1}", time, lpos.ToString("F2")); Quaternion rot = Quaternion.LookRotation(lfwd, lup); hipsCurves.X.AddKey(time, rot.x); hipsCurves.Y.AddKey(time, rot.y); hipsCurves.Z.AddKey(time, rot.z); hipsCurves.W.AddKey(time, rot.w); hipsCurves.PX.AddKey(time, lpos.x); hipsCurves.PY.AddKey(time, lpos.y); hipsCurves.PZ.AddKey(time, lpos.z); } } } if (!Mathf.Approximately(time + deltaTime, clipLen)) { m_Animator.Update(deltaTime); time += deltaTime; } else { m_Animator.Update(deltaTime - 0.005f); //keep it in the range, if go beyond, something bad could happen time += deltaTime - 0.005f; } } } //end of 1. { // 2. set animation clip and store in AssetDatabase AnimationClip newClip = new AnimationClip(); newClip.frameRate = SAMPLE_RATE; newClip.localBounds = clip.localBounds; // set bone curves for (var ie = curveDict.GetEnumerator(); ie.MoveNext();) { var curves = ie.Current.Value; if (ie.Current.Key == animatorTr) { //root motion newClip.SetCurve(curves.relPath, typeof(Animator), "MotionT.x", curves.PX); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionT.y", curves.PY); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionT.z", curves.PZ); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionQ.x", curves.X); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionQ.y", curves.Y); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionQ.z", curves.Z); newClip.SetCurve(curves.relPath, typeof(Animator), "MotionQ.w", curves.W); } else { newClip.SetCurve(curves.relPath, typeof(Transform), "localRotation.x", curves.X); newClip.SetCurve(curves.relPath, typeof(Transform), "localRotation.y", curves.Y); newClip.SetCurve(curves.relPath, typeof(Transform), "localRotation.z", curves.Z); newClip.SetCurve(curves.relPath, typeof(Transform), "localRotation.w", curves.W); newClip.SetCurve(curves.relPath, typeof(Transform), "localPosition.x", curves.PX); newClip.SetCurve(curves.relPath, typeof(Transform), "localPosition.y", curves.PY); newClip.SetCurve(curves.relPath, typeof(Transform), "localPosition.z", curves.PZ); } } // 2.1 copy the unmapped curves to new clip( not mapped by Muscle clip ) _CopyOtherCurves(newClip, clip); // some setting work newClip.EnsureQuaternionContinuity(); #if !U5 AnimationUtility.SetAnimationType(newClip, m_AnimType); RCall.CallMtd("UnityEditor.AnimationUtility", "SetAnimationClipSettings", null, newClip, clipSetting); #else if (m_AnimType == ModelImporterAnimationType.Legacy) { newClip.legacy = true; } AnimationUtility.SetAnimationClipSettings(newClip, clipSetting); #endif EUtil.SaveAnimClip(newClip, newClipAssetPath); EUtil.ShowNotification("Converted to: " + m_AnimType + (hipsBone != null ? ("\nroot=" + AnimationUtility.CalculateTransformPath(hipsBone, animatorTr)) : ""), 3f ); } //end of 2. // 3. clean job curveDict = null; AssetDatabase.SaveAssets(); Dbg.Log("Converted: {0}", newClipAssetPath); }
private void UpdateBlendShapeSetIcon() { if (!blendShapeSetIconUpdate) { return; } blendShapeSetIconUpdate = false; if (va.blendShapeSetList == null || va.blendShapeSetList.Count <= 0) { return; } TransformPoseSave beforePose = new TransformPoseSave(va.editGameObject); BlendShapeWeightSave beforeBlendShape = new BlendShapeWeightSave(va.editGameObject); va.transformPoseSave.ResetDefaultTransform(); va.blendShapeWeightSave.ResetDefaultWeight(); var gameObject = GameObject.Instantiate <GameObject>(va.editGameObject); gameObject.hideFlags |= HideFlags.HideAndDontSave; gameObject.transform.rotation = Quaternion.identity; Action ForceObjectUpdate = () => { gameObject.SetActive(false); gameObject.SetActive(true); }; int blankLayer; { for (blankLayer = 31; blankLayer > 0; blankLayer--) { if (string.IsNullOrEmpty(LayerMask.LayerToName(blankLayer))) { break; } } if (blankLayer < 0) { blankLayer = 31; } } foreach (var renderer in gameObject.GetComponentsInChildren <Renderer>()) { renderer.gameObject.layer = blankLayer; } var renderers = gameObject.GetComponentsInChildren <SkinnedMeshRenderer>().Where(renderer => renderer.sharedMesh != null && renderer.sharedMesh.blendShapeCount > 0).ToArray(); foreach (var renderer in renderers) { renderer.updateWhenOffscreen = true; } { RenderTexture iconTexture = new RenderTexture(IconTextureSize, IconTextureSize, 16, RenderTextureFormat.ARGB32); iconTexture.hideFlags |= HideFlags.HideAndDontSave; iconTexture.Create(); var cameraObject = new GameObject(); cameraObject.hideFlags |= HideFlags.HideAndDontSave; var camera = cameraObject.AddComponent <Camera>(); camera.targetTexture = iconTexture; camera.clearFlags = CameraClearFlags.Color; camera.backgroundColor = Color.clear; camera.cullingMask = 1 << blankLayer; { Bounds bounds = new Bounds(); foreach (var renderer in renderers) { if (Mathf.Approximately(bounds.size.sqrMagnitude, 0f)) { bounds = renderer.bounds; } else { bounds.Encapsulate(renderer.bounds); } } var transform = camera.transform; var sizeMax = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z)); switch (blendShapeSetIconCameraMode) { case IconCameraMode.forward: { var rot = Quaternion.AngleAxis(180f, Vector3.up); transform.localRotation = rot; sizeMax = Mathf.Max(bounds.size.x, bounds.size.y); transform.localPosition = new Vector3(bounds.center.x, bounds.center.y, bounds.max.z) - transform.forward; } break; case IconCameraMode.back: { transform.localRotation = Quaternion.identity; sizeMax = Mathf.Max(bounds.size.x, bounds.size.y); transform.localPosition = new Vector3(bounds.center.x, bounds.center.y, bounds.min.z) - transform.forward; } break; case IconCameraMode.up: { var rot = Quaternion.AngleAxis(90f, Vector3.right); transform.localRotation = rot; sizeMax = Mathf.Max(bounds.size.x, bounds.size.z); transform.localPosition = new Vector3(bounds.center.x, bounds.max.y, bounds.center.z) - transform.forward; } break; case IconCameraMode.down: { var rot = Quaternion.AngleAxis(-90f, Vector3.right); transform.localRotation = rot; sizeMax = Mathf.Max(bounds.size.x, bounds.size.z); transform.localPosition = new Vector3(bounds.center.x, bounds.min.y, bounds.center.z) - transform.forward; } break; case IconCameraMode.right: { var rot = Quaternion.AngleAxis(-90f, Vector3.up); transform.localRotation = rot; sizeMax = Mathf.Max(bounds.size.y, bounds.size.z); transform.localPosition = new Vector3(bounds.max.x, bounds.center.y, bounds.center.z) - transform.forward; } break; case IconCameraMode.left: { var rot = Quaternion.AngleAxis(90f, Vector3.up); transform.localRotation = rot; sizeMax = Mathf.Max(bounds.size.y, bounds.size.z); transform.localPosition = new Vector3(bounds.min.x, bounds.center.y, bounds.center.z) - transform.forward; } break; } camera.orthographic = true; camera.orthographicSize = sizeMax * 0.6f; camera.farClipPlane = 1f + sizeMax * 5f; } cameraObject.transform.SetParent(gameObject.transform); gameObject.transform.rotation = va.editGameObject.transform.rotation; foreach (var set in va.blendShapeSetList) { va.blendShapeWeightSave.ResetDefaultWeight(); if (set.poseTemplate.blendShapePaths != null && set.poseTemplate.blendShapeValues != null) { foreach (var renderer in renderers) { var path = AnimationUtility.CalculateTransformPath(renderer.transform, gameObject.transform); var index = EditorCommon.ArrayIndexOf(set.poseTemplate.blendShapePaths, path); if (index < 0) { continue; } for (int i = 0; i < set.poseTemplate.blendShapeValues[index].names.Length; i++) { var sindex = renderer.sharedMesh.GetBlendShapeIndex(set.poseTemplate.blendShapeValues[index].names[i]); if (sindex < 0 || sindex >= renderer.sharedMesh.blendShapeCount) { continue; } renderer.SetBlendShapeWeight(sindex, set.poseTemplate.blendShapeValues[index].weights[i]); } } } ForceObjectUpdate(); camera.Render(); { RenderTexture save = RenderTexture.active; RenderTexture.active = iconTexture; if (set.icon == null) { set.icon = new Texture2D(iconTexture.width, iconTexture.height, TextureFormat.ARGB32, iconTexture.useMipMap); set.icon.hideFlags |= HideFlags.HideAndDontSave; } set.icon.ReadPixels(new Rect(0, 0, iconTexture.width, iconTexture.height), 0, 0); set.icon.Apply(); RenderTexture.active = save; } } GameObject.DestroyImmediate(cameraObject); iconTexture.Release(); RenderTexture.DestroyImmediate(iconTexture); } GameObject.DestroyImmediate(gameObject); beforePose.ResetDefaultTransform(); beforeBlendShape.ResetDefaultWeight(); { va.editGameObject.SetActive(false); va.editGameObject.SetActive(true); } va.SetUpdateResampleAnimation(); }
// This method will recover references to game objects within the prefab instance hierarchy. // Without it, the newly created prefab variant would simply lose these references altogether. static void RecoverObjectReferences(Transform srcRoot, GameObject src, Transform dstRoot, GameObject dst) { var srcChildren = GetChildrenAndSelf(src.transform); var dstChildren = GetChildrenAndSelf(dst.transform); for (int i = 0; i < dstChildren.Length; i++) { src = srcChildren[i].gameObject; dst = dstChildren[i].gameObject; var srcComponents = src.GetComponents <Component>(); var dstComponents = dst.GetComponents <Component>(); for (int j = 0; j < srcComponents.Length; j++) { var srcObject = new SerializedObject(srcComponents[j]); var dstObject = new SerializedObject(dstComponents[j]); var srcIterator = srcObject.GetIterator(); var dstIterator = dstObject.GetIterator(); while (srcIterator.Next(true) && dstIterator.Next(true)) { if (srcIterator.propertyType != SerializedPropertyType.ObjectReference) { continue; } if (!TryGetTransform(srcIterator.objectReferenceValue, out var transform)) { continue; } if (!transform.IsChildOf(srcRoot)) { continue; } var path = AnimationUtility.CalculateTransformPath(transform, srcRoot.parent); var value = FindTransformByPath(dstRoot, path); if (value) { if (srcIterator.objectReferenceValue is GameObject) { dstIterator.objectReferenceValue = value.gameObject; } if (srcIterator.objectReferenceValue is Component component) { dstIterator.objectReferenceValue = value.GetComponent(component.GetType()); } } } dstObject.ApplyModifiedProperties(); } if (i > 0) { RecoverObjectReferences(srcRoot, src, dstRoot, dst); } } }
public string Path(Transform item) => AnimationUtility.CalculateTransformPath(item, avatar.transform);
private void MakeAnimationCurves(GameObject root, AnimationClip animClip, Animation animation) { acb = new AnimationCurveBuilder(); //Get a list of all sprites on this GO var allSprites = root.GetComponentsInChildren <Transform>(true).Select(sr => AnimationUtility.CalculateTransformPath(sr.transform, root.transform)); //Add a key for all objects on the first frame SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), 0); foreach (var mainlineKey in animation.MainlineKeys) { var visibleSprites = SetGameObjectForKey(root, animClip, mainlineKey); var hiddenSprites = allSprites.Except(visibleSprites); HideSprites(root, hiddenSprites, mainlineKey.Time); } switch (animation.LoopType) { case LoopType.True: //Cycle back to first frame SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), animation.Length); break; case LoopType.False: //Duplicate the last key at the end time of the animation SetGameObjectForKey(root, animClip, animation.MainlineKeys.Last(), animation.Length); break; default: Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString()); break; } //Add the curves to our animation clip //NOTE: This MUST be done before modifying the settings, thus the double switch statement acb.AddCurves(animClip); foreach (var sprite in spriteChangeKeys) { if (sprite.Value.Count > 0) { BuildSpriteChangeCurve(ref animClip, sprite); } } //Set the loop/wrap settings for the animation clip var animSettings = AnimationUtility.GetAnimationClipSettings(animClip); switch (animation.LoopType) { case LoopType.True: animClip.wrapMode = WrapMode.Loop; animSettings.loopTime = true; break; case LoopType.False: animClip.wrapMode = WrapMode.ClampForever; break; case LoopType.PingPong: animClip.wrapMode = WrapMode.PingPong; animSettings.loopTime = true; break; default: Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString()); break; } animClip.SetAnimationSettings(animSettings); //Debug.Log(string.Format("Setting animation {0} to {1} loop mode (WrapMode:{2} LoopTime:{3}) ", animClip.name, animation.LoopType, animClip.wrapMode, animSettings.loopTime)); }
private static void CheckPropertyFieldsOnObject(Object @object) { SerializedObject serializedObject = new SerializedObject(@object); SerializedProperty property = serializedObject.GetIterator(); while (property.NextVisible(true)) { if (property.propertyPath.EndsWith("m_Script")) { continue; } try { object objectFromProperty = EditorUtils.GetObjectFromProperty(property, out _, out _); switch (property.propertyType) { case SerializedPropertyType.ObjectReference: if (CheckObjectEquality((Object)objectFromProperty, property.objectReferenceValue)) { continue; } break; case SerializedPropertyType.Integer: if (objectFromProperty is uint) { if (CheckEquality(objectFromProperty, (uint)property.intValue)) { continue; } } else if (objectFromProperty is long) { if (CheckEquality(objectFromProperty, property.longValue)) { continue; } } else if (objectFromProperty is byte) { if (CheckEquality(objectFromProperty, (byte)property.intValue)) { continue; } } else if (objectFromProperty is short) { if (CheckEquality(objectFromProperty, (short)property.intValue)) { continue; } } else { if (CheckEquality(objectFromProperty, property.intValue)) { continue; } } break; case SerializedPropertyType.Enum: Type baseEnumType = Enum.GetUnderlyingType(objectFromProperty.GetType()); if (baseEnumType == typeof(int)) { if (CheckEquality(objectFromProperty, property.intValue)) { continue; } } else if (baseEnumType == typeof(uint)) { if (CheckEquality(objectFromProperty, (uint)property.intValue)) { continue; } } else if (baseEnumType == typeof(byte)) { if (CheckEquality(objectFromProperty, (byte)property.intValue)) { continue; } } else if (baseEnumType == typeof(long)) { if (CheckEquality(objectFromProperty, (long)property.intValue)) { continue; } } else if (baseEnumType == typeof(short)) { if (CheckEquality(objectFromProperty, (short)property.intValue)) { continue; } } break; case SerializedPropertyType.Boolean: if (CheckEquality(objectFromProperty, property.boolValue)) { continue; } break; case SerializedPropertyType.Float: if (objectFromProperty is double) { if (CheckEquality(objectFromProperty, property.doubleValue)) { continue; } } else { if (CheckEquality(objectFromProperty, property.floatValue)) { continue; } } break; case SerializedPropertyType.String: if (objectFromProperty == null && string.IsNullOrEmpty(property.stringValue)) { continue; } if (property.stringValue.Equals((string)objectFromProperty, StringComparison.Ordinal)) { continue; } Debug.Log($"{property.stringValue} != {objectFromProperty}"); break; case SerializedPropertyType.Color: if (objectFromProperty is Color) { if (CheckEquality(objectFromProperty, property.colorValue)) { continue; } } else { if (CheckEquality <Color32>(objectFromProperty, property.colorValue)) { continue; } } break; case SerializedPropertyType.LayerMask: if (CheckEquality <LayerMask>(objectFromProperty, property.intValue)) { continue; } break; case SerializedPropertyType.Vector2: if (CheckEquality(objectFromProperty, property.vector2Value)) { continue; } break; case SerializedPropertyType.Vector3: if (CheckEquality(objectFromProperty, property.vector3Value)) { continue; } break; case SerializedPropertyType.Vector4: if (CheckEquality(objectFromProperty, property.vector4Value)) { continue; } break; case SerializedPropertyType.Rect: if (CheckEquality(objectFromProperty, property.rectValue)) { continue; } break; case SerializedPropertyType.ArraySize: if (CheckEquality(objectFromProperty, property.intValue)) { continue; } break; case SerializedPropertyType.Character: if (CheckEquality(objectFromProperty, (char)property.intValue)) { continue; } break; case SerializedPropertyType.AnimationCurve: if (CheckEquality(objectFromProperty, property.animationCurveValue)) { continue; } break; case SerializedPropertyType.Bounds: if (CheckEquality(objectFromProperty, property.boundsValue)) { continue; } break; case SerializedPropertyType.Quaternion: if (CheckEquality(objectFromProperty, property.quaternionValue)) { continue; } break; case SerializedPropertyType.ExposedReference: if (CheckObjectEquality((Object)objectFromProperty, property.exposedReferenceValue)) { continue; } break; case SerializedPropertyType.FixedBufferSize: if (CheckEquality(objectFromProperty, property.fixedBufferSize)) { continue; } break; case SerializedPropertyType.Vector2Int: if (CheckEquality(objectFromProperty, property.vector2IntValue)) { continue; } break; case SerializedPropertyType.Vector3Int: if (CheckEquality(objectFromProperty, property.vector3IntValue)) { continue; } break; case SerializedPropertyType.RectInt: if (CheckEquality(objectFromProperty, property.rectIntValue)) { continue; } break; case SerializedPropertyType.BoundsInt: if (CheckEquality(objectFromProperty, property.boundsIntValue)) { continue; } break; case SerializedPropertyType.Gradient: case SerializedPropertyType.Generic: continue; default: continue; } } catch (Exception e) { if (e is FieldAccessException) { continue; } Log(e); throw; } Log(); void Log(Exception exception = null) { string path = EditorUtility.IsPersistent(@object) ? $"{AssetDatabase.GetAssetPath(@object)}/" : string.Empty; if (@object is Component component) { Transform transform = component.transform; string tPath = AnimationUtility.CalculateTransformPath(transform, transform.root); path += string.IsNullOrEmpty(tPath) ? component.ToString() : $"{tPath}/{component}"; } else { path += @object.ToString(); } Assert.Fail($"{path}.{property.propertyPath}\nFailed {nameof(EditorUtils.GetObjectFromProperty)}.\n{exception}"); } } }
void StartClipBaker(Transform transform) { var playbackBuffer = m_PlaybackStream.activePlaybackBuffer; if (playbackBuffer == null) { return; } if (m_CharacterRigController == null) { Debug.LogWarning("No Character Rig Controller Found! Will not be able to bake Character Bone Animations."); } if (m_BlendShapesController == null) { Debug.LogWarning("No Blend Shape Controller Found! Will not be able to bake Character Blend Shape Animations."); } m_AnimationClipCurveData.Clear(); baking = true; if (m_BlendShapesController != null) { m_BlendShapesController.UpdateBlendShapeIndices(playbackBuffer); // Get curve data for blend shapes foreach (var skinnedMeshRenderer in m_BlendShapesController.skinnedMeshRenderers) { if (skinnedMeshRenderer == null || m_AnimationCurves.ContainsKey(skinnedMeshRenderer)) // Skip duplicates { continue; } var path = AnimationUtility.CalculateTransformPath(skinnedMeshRenderer.transform, transform); path = path.Replace(string.Format("{0}/", skinnedMeshRenderer.transform), ""); var mesh = skinnedMeshRenderer.sharedMesh; var count = mesh.blendShapeCount; var animationCurves = new Dictionary <string, AnimationClipCurveData>(); for (var i = 0; i < count; i++) { var shapeName = mesh.GetBlendShapeName(i); var prop = string.Format(k_BlendShapeProp, shapeName); var curve = new AnimationCurve(); var curveData = new AnimationClipCurveData { path = path, curve = curve, propertyName = prop, type = skinnedMeshRenderer.GetType() }; m_AnimationClipCurveData.Add(curveData); animationCurves.Add(prop, curveData); } m_AnimationCurves.Add(skinnedMeshRenderer, animationCurves); } } if (m_CharacterRigController != null) { m_CharacterRigController.UpdateBlendShapeIndices(playbackBuffer); m_CharacterRigController.SetupCharacterRigController(); // Get curve data for bone transforms var transformType = typeof(Transform); foreach (var bone in m_CharacterRigController.animatedBones) { if (bone == null || m_AnimationCurves.ContainsKey(bone)) // Skip duplicates { continue; } var path = AnimationUtility.CalculateTransformPath(bone, transform); var animationCurves = new Dictionary <string, AnimationClipCurveData>(); foreach (var prop in k_RotParams) { var curve = new AnimationCurve(); var curveData = new AnimationClipCurveData { path = path, curve = curve, propertyName = prop, type = transformType }; m_AnimationClipCurveData.Add(curveData); animationCurves.Add(prop, curveData); } m_AnimationCurves.Add(bone, animationCurves); } } currentFrame = 0; var recordStream = playbackBuffer.recordStream; frameCount = recordStream.Length / playbackBuffer.bufferSize; Buffer.BlockCopy(recordStream, playbackBuffer.FrameTimeOffset, m_FrameTime, 0, playbackBuffer.FrameTimeSize); m_FirstFrameTime = m_FrameTime[0]; }
public IEnumerator ComputeAnimation(AnimationClip clip, Action <BitAnimator> finishCallback = null, Action <BitAnimator> updateCallback = null) { float time = Time.realtimeSinceStartup; if (core == null || core.audioClip != audioClip) { status = "Loading audio"; if (updateCallback != null) { updateCallback(this); } yield return(null); FFTWindow = 1 << FFTWindowLog; if (core == null) { core = new ComputeProgram(computeShader); } core.Initialize(FFTWindowLog, filter, multisamples, windowParam); core.LoadAudio(audioClip); core.resolveFactor = deconvolution; SetMode(ref core.mode, calculateLoudness, energyCorrection); chunks = core.chunks; Debug.LogFormat("[BitAnimator] Setup time = {0:F3}", Time.realtimeSinceStartup - time); time = Time.realtimeSinceStartup; } if (animatorObject == null) { animatorObject = GetComponent <Animator>(); } if (targetObject == null) { targetObject = gameObject; } //Создаем группу задач для вычисления значений ключевых кадров Task[] tasks = new Task[recordSlots.Count]; for (int p = 0; p < recordSlots.Count; p++) { tasks[p].SetRemapCurve(recordSlots[p].minValue, recordSlots[p].maxValue, recordSlots[p].remap, recordSlots[p].channelMask); //Устанавливаем соотношение амплитуды спектра и результирующих значений ключевых кадров if (recordSlots[p].type == RecordSlot.PropertyType.Color) { tasks[p].SetRemapGradient(recordSlots[p].colors, recordSlots[p].channelMask); } tasks[p].values = new ComputeBuffer(chunks, 4); tasks[p].buffer = new ComputeBuffer(chunks, 4); //Резервируем буффер для ключей XYZW|RGBA tasks[p].keyframes = new ComputeBuffer(chunks * tasks[p].Channels, 20); } status = "Calculating spectrum"; if (updateCallback != null) { updateCallback(this); } yield return(null); //разделяем вычисление спектра на блоки int maxUseVRAM = SystemInfo.graphicsMemorySize / 10; // use 10% of total video memory int calculatedMemory = chunks * FFTWindow / 1024 * 21 / 1024; int blocks = (calculatedMemory - 1) / maxUseVRAM + 1; int batches = (chunks - 1) / blocks + 1; float[] temp = new float[1]; for (int block = 0; block < blocks; block++) { int offset = batches * block; //Вычисляем спектрограмму core.FFT_Execute(0, offset, Math.Min(batches, chunks - 1 - offset)); //Преобразуем спектр из комплексных чисел в частотно-амплитудный спектр core.ConvertToSpectrum(); core.ResolveMultisamples(); for (int p = 0; p < recordSlots.Count; p++) { //Интегрируем полосу частот в 1D массив core.MergeBand(recordSlots[p].startFreq, recordSlots[p].endFreq, tasks[p].values, offset); } taskProgress += 0.5f / blocks; if (updateCallback != null) { updateCallback(this); } yield return(null); } Debug.LogFormat("[BitAnimator] Calculating spectrum time = {0:F3}", Time.realtimeSinceStartup - time); time = Time.realtimeSinceStartup; ComputeBuffer mask = new ComputeBuffer(chunks, 4); for (int p = 0; p < recordSlots.Count; p++) { core.Normalize(tasks[p].values); core.ApplyRemap(tasks[p].values, tasks[p].buffer, tasks[p].values.count, tasks[p].remapKeyframes); ComputeProgram.Swap(ref tasks[p].values, ref tasks[p].buffer); //сглаживаем анимацию кривой if (recordSlots[p].ampSmoothness > 0.0f) { core.SmoothSpectrum(tasks[p].values, tasks[p].buffer, recordSlots[p].ampSmoothness); ComputeProgram.Swap(ref tasks[p].values, ref tasks[p].buffer); } if (recordSlots[p].damping >= 0.0001f) { core.ApplyFading(tasks[p].values, tasks[p].buffer, tasks[p].values.count, 1.0f / recordSlots[p].damping - 1.0f); ComputeProgram.Swap(ref tasks[p].values, ref tasks[p].buffer); } //создание неубывающей кривой (каждый пик потихоньку сдвигает позицию к конечному значению) if (recordSlots[p].accumulate) { core.CalculatePrefixSum(tasks[p].values, tasks[p].buffer, tasks[p].values.count); ComputeProgram.Swap(ref tasks[p].values, ref tasks[p].buffer); } int prop = p; if (recordSlots[prop].modificators.Count > 0) { core.Multiply(mask, 0, mask.count, 0.0f); foreach (Modificator mod in recordSlots[prop].modificators) { mod.Apply(core, mask, tasks[prop].buffer); if (mod.useTempBuffer) { ComputeProgram.Swap(ref mask, ref tasks[prop].buffer); } } core.Multiply(tasks[prop].values, mask); } core.Normalize(tasks[p].values); core.Multiply(tasks[p].values, 0, tasks[p].values.count, multiply); if (recordSlots[p].type == RecordSlot.PropertyType.Color) { core.RemapGradient(tasks[p].values, tasks[p].keyframes, tasks[p].gradientKeyframes, tasks[p].Channels, tasks[p].gradientKeys, recordSlots[p].loops); } else { core.CreateKeyframes(tasks[p].values, tasks[p].keyframes, tasks[p].min, tasks[p].max, tasks[p].Channels, recordSlots[p].loops); } //перевод углов Эйлера в кватернионы if (recordSlots[p].type == RecordSlot.PropertyType.Quaternion) { core.ConvertKeyframesRotation(tasks[p].keyframes, tasks[p].values.count); } } mask.Dispose(); tasks[0].values.GetData(temp); status = quality < 1.0f ? "Optimization keyframes" : "Writing animation"; if (updateCallback != null) { updateCallback(this); } yield return(null); string go_path = AnimationUtility.CalculateTransformPath(targetObject.transform, animatorObject.transform); //Получаем результат с GPU и записываем в анимацию for (int p = 0; p < recordSlots.Count; p++) { Type renderType = GetCurveAnimationType(recordSlots[p].typeSet); string[] animationProperties = recordSlots[p].property; for (int c = 0; c < animationProperties.Length; c++) { yield return(null); if (updateCallback != null) { updateCallback(this); } AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, audioClip.length, 0); Keyframe[] keyframes = tasks[p].GetKeyframes(c); if (quality < 1.0f) { float step = 1.0f / 32.0f; float partsTaskProgress = 0; float lastFrame = Time.realtimeSinceStartup; float rmsQuality = Mathf.Pow(10.0f, -6.0f * quality * quality - 1.0f); //quality to RMS [0..1] => [1e-1 .. 1e-7] foreach (Keyframe[] k in core.DecimateAnimationCurve(keyframes, rmsQuality * (tasks[p].max[c] - tasks[p].min[c]))) { partsTaskProgress += step; taskProgress += 0.5f * step / recordSlots.Count / animationProperties.Length; //Делаем паузу если уходит много времени на обработку if (k == null && Time.realtimeSinceStartup - lastFrame >= Time.fixedUnscaledDeltaTime) { lastFrame = Time.realtimeSinceStartup; if (updateCallback != null) { updateCallback(this); } yield return(null); } else { keyframes = k; } } taskProgress += 0.5f * Mathf.Max(0, 1.0f - partsTaskProgress) / recordSlots.Count / animationProperties.Length; } else { taskProgress += 0.5f / recordSlots.Count / animationProperties.Length; } curve.keys = keyframes; clip.SetCurve(go_path, renderType, animationProperties[c], curve); } tasks[p].Release(); } Debug.LogFormat("[BitAnimator] Writing animation time = {0:F3}", Time.realtimeSinceStartup - time); status = "Done"; taskProgress = 0; yield return(null); if (finishCallback != null) { finishCallback(this); } }
protected void findObjsUnderTransformTree(int recursionLevel, int maxRecursionLevel, Transform currentTransform, string parentPanelPath, ref Dictionary <string, Dictionary <string, Dictionary <int, List <UIWidget> > > > widgetHierarchy) { if (recursionLevel > maxRecursionLevel) { return; } UIPanel currentPanel = currentTransform.gameObject.GetComponent <UIPanel>(); if (currentPanel != null) { string underPath = AnimationUtility.CalculateTransformPath(currentTransform, this.NGUIRootObject.transform); if (underPath.Length > 0) { parentPanelPath = string.Format("{0}/{1}", this.NGUIRootObject.name, underPath); } else { parentPanelPath = this.NGUIRootObject.name; } } foreach (Transform child in currentTransform) { UIWidget widget = child.gameObject.GetComponent <UIWidget>(); if (widget != null) { string atlasName = RSDepthManager.atlasNameFromObj(widget); int depth = widget.depth; Dictionary <string, Dictionary <int, List <UIWidget> > > hierarchyUnderPanel = null; if (!widgetHierarchy.TryGetValue(parentPanelPath, out hierarchyUnderPanel)) { hierarchyUnderPanel = new Dictionary <string, Dictionary <int, List <UIWidget> > >(); widgetHierarchy[parentPanelPath] = hierarchyUnderPanel; } Dictionary <int, List <UIWidget> > hierarchyUnderAtlas = null; if (!hierarchyUnderPanel.TryGetValue(atlasName, out hierarchyUnderAtlas)) { hierarchyUnderAtlas = new Dictionary <int, List <UIWidget> >(); hierarchyUnderPanel[atlasName] = hierarchyUnderAtlas; } List <UIWidget> widgetsAtDepth = null; if (!hierarchyUnderAtlas.TryGetValue(depth, out widgetsAtDepth)) { widgetsAtDepth = new List <UIWidget>(); hierarchyUnderAtlas[depth] = widgetsAtDepth; } widgetsAtDepth.Add(widget); } this.findObjsUnderTransformTree(recursionLevel + 1, maxRecursionLevel, child, parentPanelPath, ref widgetHierarchy); } }
public void FixMissingAnimation() { var animator = voxelBone.voxelObject.GetComponent <Animator>(); if (animator != null && animator.runtimeAnimatorController != null) { string[] bonePaths = new string[objectCore.animationObject.bones.Length]; for (int i = 0; i < objectCore.animationObject.bones.Length; i++) { if (objectCore.animationObject.bones[i] == null) { continue; } bonePaths[i] = AnimationUtility.CalculateTransformPath(objectCore.animationObject.bones[i].transform, voxelBone.voxelObject.transform); } foreach (var clip in animator.runtimeAnimatorController.animationClips) { var bindings = AnimationUtility.GetCurveBindings(clip); if (bindings.IsReadOnly) { continue; } for (int i = 0; i < bindings.Length; i++) { bool missing = true; for (int j = 0; j < bonePaths.Length; j++) { if (bindings[i].path == bonePaths[j]) { missing = false; break; } } if (!missing) { continue; } var curve = AnimationUtility.GetEditorCurve(clip, bindings[i]); { var index = bindings[i].path.IndexOf(fullPathBoneName); if (index >= 0 && bindings[i].path.Length == index + fullPathBoneName.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } { var index = fullPathBoneName.IndexOf(bindings[i].path); if (index >= 0 && fullPathBoneName.Length == index + bindings[i].path.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } { var index = bindings[i].path.LastIndexOf(voxelBone.name); if (index >= 0 && bindings[i].path.Length == index + voxelBone.name.Length) { AnimationUtility.SetEditorCurve(clip, bindings[i], null); bindings[i].path = fullPathBoneName; AnimationUtility.SetEditorCurve(clip, bindings[i], curve); continue; } } } } } }
private void AddBoxColliderCurve(AnimationClip animClip, BoxCollider2D collider, Sprite[] sprites) { Debug.Assert(framePivots != null && sprites.Length == framePivots.Length); AnimationCurve xSizeCurve = new AnimationCurve(); AnimationCurve ySizeCurve = new AnimationCurve(); AnimationCurve xOffsetCurve = new AnimationCurve(); AnimationCurve yOffsetCurve = new AnimationCurve(); for (int i = 0; i < sprites.Length; ++i) { float unitTime = 1f / animClip.frameRate; float time = studio.output.frameInterval * i * unitTime; Texture2D texture = frameModelTextures[i]; // size curve Vector3 spriteSize = sprites[i].bounds.size; if (frameCompactBounds != null) { int compactWidth = frameCompactBounds[i].max.x - frameCompactBounds[i].min.x + 1; int compactHeight = frameCompactBounds[i].max.y - frameCompactBounds[i].min.y + 1; float widthRatio = (float)compactWidth / (float)texture.width; float heightRatio = (float)compactHeight / (float)texture.height; spriteSize.x *= widthRatio; spriteSize.y *= heightRatio; } xSizeCurve.AddKey(time, spriteSize.x); ySizeCurve.AddKey(time, spriteSize.y); // offset curve float xPivotRatio = (float)framePivots[i].x / (float)texture.width; float yPivotRatio = (float)framePivots[i].y / (float)texture.height; float xCenterRatio = 0.5f; float yCenterRatio = 0.5f; if (frameCompactVectors != null) { xCenterRatio += frameCompactVectors[i].x; yCenterRatio += frameCompactVectors[i].y; } float offsetX = (xCenterRatio - xPivotRatio) * sprites[i].bounds.size.x; float offsetY = (yCenterRatio - yPivotRatio) * sprites[i].bounds.size.y; xOffsetCurve.AddKey(time, offsetX); yOffsetCurve.AddKey(time, offsetY); // setup for firstSprite if (!wasColliderSetup && i == 0) { wasColliderSetup = true; collider.size = new Vector2(spriteSize.x, spriteSize.y); collider.offset = new Vector2(offsetX, offsetY); } } string path = AnimationUtility.CalculateTransformPath(collider.transform, outRootPrefab.transform); EditorCurveBinding xSizeCurveBinding = EditorCurveBinding.FloatCurve(path, typeof(BoxCollider2D), "m_Size.x"); EditorCurveBinding ySizeCurveBinding = EditorCurveBinding.FloatCurve(path, typeof(BoxCollider2D), "m_Size.y"); EditorCurveBinding xOffsetCurveBinding = EditorCurveBinding.FloatCurve(path, typeof(BoxCollider2D), "m_Offset.x"); EditorCurveBinding yOffsetCurveBinding = EditorCurveBinding.FloatCurve(path, typeof(BoxCollider2D), "m_Offset.y"); AnimationUtility.SetEditorCurve(animClip, xSizeCurveBinding, xSizeCurve); AnimationUtility.SetEditorCurve(animClip, ySizeCurveBinding, ySizeCurve); AnimationUtility.SetEditorCurve(animClip, xOffsetCurveBinding, xOffsetCurve); AnimationUtility.SetEditorCurve(animClip, yOffsetCurveBinding, yOffsetCurve); }
public static void ReplaceConstraintTransformReference(GameObject gameObject, Rig rig, GameObject originalGameObject, Rig originalRig) { Func <Transform, Transform> GetPreviewTransform = (t) => { if (t == null) { return(null); } var path = AnimationUtility.CalculateTransformPath(t, originalGameObject.transform); return(gameObject.transform.Find(path)); }; var originalRigConstraints = originalGameObject.GetComponentsInChildren <IRigConstraint>(); foreach (var originalRigConstraint in originalRigConstraints) { #region BlendConstraint if (originalRigConstraint is BlendConstraint) { var blendConstraint = originalRigConstraint as BlendConstraint; var constraint = GetPreviewTransform(blendConstraint.transform).GetComponent <BlendConstraint>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(blendConstraint.data.constrainedObject); constraint.data.sourceObjectA = GetPreviewTransform(blendConstraint.data.sourceObjectA); constraint.data.sourceObjectB = GetPreviewTransform(blendConstraint.data.sourceObjectB); } } #endregion #region ChainIKConstraint else if (originalRigConstraint is ChainIKConstraint) { var chainIKConstraint = originalRigConstraint as ChainIKConstraint; var constraint = GetPreviewTransform(chainIKConstraint.transform).GetComponent <ChainIKConstraint>(); if (constraint != null) { constraint.data.root = GetPreviewTransform(chainIKConstraint.data.root); constraint.data.tip = GetPreviewTransform(chainIKConstraint.data.tip); constraint.data.target = GetPreviewTransform(chainIKConstraint.data.target); } } #endregion #region ChainIKConstraint else if (originalRigConstraint is DampedTransform) { var dampedTransform = originalRigConstraint as DampedTransform; var constraint = GetPreviewTransform(dampedTransform.transform).GetComponent <DampedTransform>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(dampedTransform.data.constrainedObject); constraint.data.sourceObject = GetPreviewTransform(dampedTransform.data.sourceObject); } } #endregion #region MultiAimConstraint else if (originalRigConstraint is MultiAimConstraint) { var multiAimConstraint = originalRigConstraint as MultiAimConstraint; var constraint = GetPreviewTransform(multiAimConstraint.transform).GetComponent <MultiAimConstraint>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(multiAimConstraint.data.constrainedObject); var sourceObjects = constraint.data.sourceObjects; for (int i = 0; i < multiAimConstraint.data.sourceObjects.Count; i++) { sourceObjects.SetTransform(i, GetPreviewTransform(multiAimConstraint.data.sourceObjects.GetTransform(i))); } constraint.data.sourceObjects = sourceObjects; } } #endregion #region MultiParentConstraint else if (originalRigConstraint is MultiParentConstraint) { var multiParentConstraint = originalRigConstraint as MultiParentConstraint; var constraint = GetPreviewTransform(multiParentConstraint.transform).GetComponent <MultiParentConstraint>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(multiParentConstraint.data.constrainedObject); var sourceObjects = constraint.data.sourceObjects; for (int i = 0; i < multiParentConstraint.data.sourceObjects.Count; i++) { sourceObjects.SetTransform(i, GetPreviewTransform(multiParentConstraint.data.sourceObjects.GetTransform(i))); } constraint.data.sourceObjects = sourceObjects; } } #endregion #region MultiPositionConstraint else if (originalRigConstraint is MultiPositionConstraint) { var multiPositionConstraint = originalRigConstraint as MultiPositionConstraint; var constraint = GetPreviewTransform(multiPositionConstraint.transform).GetComponent <MultiPositionConstraint>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(multiPositionConstraint.data.constrainedObject); var sourceObjects = constraint.data.sourceObjects; for (int i = 0; i < multiPositionConstraint.data.sourceObjects.Count; i++) { sourceObjects.SetTransform(i, GetPreviewTransform(multiPositionConstraint.data.sourceObjects.GetTransform(i))); } constraint.data.sourceObjects = sourceObjects; } } #endregion #region MultiReferentialConstraint else if (originalRigConstraint is MultiReferentialConstraint) { var multiReferentialConstraint = originalRigConstraint as MultiReferentialConstraint; var constraint = GetPreviewTransform(multiReferentialConstraint.transform).GetComponent <MultiReferentialConstraint>(); if (constraint != null) { var sourceObjects = constraint.data.sourceObjects; for (int i = 0; i < multiReferentialConstraint.data.sourceObjects.Count; i++) { sourceObjects[i] = GetPreviewTransform(multiReferentialConstraint.data.sourceObjects[i]); } constraint.data.sourceObjects = sourceObjects; } } #endregion #region MultiRotationConstraint else if (originalRigConstraint is MultiRotationConstraint) { var multiRotationConstraint = originalRigConstraint as MultiRotationConstraint; var constraint = GetPreviewTransform(multiRotationConstraint.transform).GetComponent <MultiRotationConstraint>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(multiRotationConstraint.data.constrainedObject); var sourceObjects = constraint.data.sourceObjects; for (int i = 0; i < multiRotationConstraint.data.sourceObjects.Count; i++) { sourceObjects.SetTransform(i, GetPreviewTransform(multiRotationConstraint.data.sourceObjects.GetTransform(i))); } constraint.data.sourceObjects = sourceObjects; } } #endregion #region OverrideTransform else if (originalRigConstraint is OverrideTransform) { var overrideTransform = originalRigConstraint as OverrideTransform; var constraint = GetPreviewTransform(overrideTransform.transform).GetComponent <OverrideTransform>(); if (constraint != null) { constraint.data.constrainedObject = GetPreviewTransform(overrideTransform.data.constrainedObject); constraint.data.sourceObject = GetPreviewTransform(overrideTransform.data.sourceObject); } } #endregion #region TwistCorrection else if (originalRigConstraint is TwistCorrection) { var twistCorrection = originalRigConstraint as TwistCorrection; var constraint = GetPreviewTransform(twistCorrection.transform).GetComponent <TwistCorrection>(); if (constraint != null) { constraint.data.sourceObject = GetPreviewTransform(twistCorrection.data.sourceObject); var twistNodes = constraint.data.twistNodes; for (int i = 0; i < twistCorrection.data.twistNodes.Count; i++) { twistNodes.SetTransform(i, GetPreviewTransform(twistCorrection.data.twistNodes.GetTransform(i))); } constraint.data.twistNodes = twistNodes; } } #endregion #region TwoBoneIKConstraint else if (originalRigConstraint is TwoBoneIKConstraint) { var twoBoneIKConstraint = originalRigConstraint as TwoBoneIKConstraint; var constraint = GetPreviewTransform(twoBoneIKConstraint.transform).GetComponent <TwoBoneIKConstraint>(); if (constraint != null) { constraint.data.root = GetPreviewTransform(twoBoneIKConstraint.data.root); constraint.data.mid = GetPreviewTransform(twoBoneIKConstraint.data.mid); constraint.data.tip = GetPreviewTransform(twoBoneIKConstraint.data.tip); constraint.data.target = GetPreviewTransform(twoBoneIKConstraint.data.target); constraint.data.hint = GetPreviewTransform(twoBoneIKConstraint.data.hint); } } #endregion #if UNITY_2020_1_OR_NEWER #region TwistChainConstraint else if (originalRigConstraint is TwistChainConstraint) //version 0.3 { var twistChainConstraint = originalRigConstraint as TwistChainConstraint; var constraint = GetPreviewTransform(twistChainConstraint.transform).GetComponent <TwistChainConstraint>(); if (constraint != null) { constraint.data.root = GetPreviewTransform(twistChainConstraint.data.root); constraint.data.tip = GetPreviewTransform(twistChainConstraint.data.tip); constraint.data.rootTarget = GetPreviewTransform(twistChainConstraint.data.rootTarget); constraint.data.tipTarget = GetPreviewTransform(twistChainConstraint.data.tipTarget); } } #endregion #endif else { Debug.LogErrorFormat("<color=blue>[Very Animation]</color>Unknown IRigConstraint. {0}", originalRigConstraint); } } #region VeryAnimationRig { var vaRig = rig.GetComponent <VeryAnimationRig>(); var originalVaRig = originalRig.GetComponent <VeryAnimationRig>(); if (vaRig != null && originalVaRig != null) { vaRig.basePoseLeftHand.constraint = GetPreviewTransform(originalVaRig.basePoseLeftHand.constraint); vaRig.basePoseRightHand.constraint = GetPreviewTransform(originalVaRig.basePoseRightHand.constraint); vaRig.basePoseLeftFoot.constraint = GetPreviewTransform(originalVaRig.basePoseLeftFoot.constraint); vaRig.basePoseRightFoot.constraint = GetPreviewTransform(originalVaRig.basePoseRightFoot.constraint); } } #endregion }
protected void finishRecording(ProgressBar progress) { progress.Begin(5, "Saving Recording", "", () => { if (!_isRecording) { return; } _isRecording = false; //Turn on auto-pushing for all auto-proxy components foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>()) { autoProxy.autoPushingEnabled = true; } progress.Begin(1, "", "Reverting Scene State", () => { foreach (var pair in _initialTransformData) { pair.Key.localPosition = pair.Value.localPosition; pair.Key.localRotation = pair.Value.localRotation; pair.Key.localScale = pair.Value.localScale; pair.Key.gameObject.SetActive(pair.Value.enabled); } foreach (var pair in _initialActivityData) { EditorUtility.SetObjectEnabled(pair.Key, pair.Value); } }); progress.Begin(1, "", "Patching Materials: ", () => { GetComponentsInChildren(true, _recorders); foreach (var recorder in _recorders) { DestroyImmediate(recorder); } //Patch up renderer references to materials var allMaterials = Resources.FindObjectsOfTypeAll <Material>(). Query(). Where(AssetDatabase.IsMainAsset). ToList(); var renderers = GetComponentsInChildren <Renderer>(includeInactive: true); progress.Begin(renderers.Length, "", "", () => { foreach (var renderer in renderers) { progress.Step(renderer.name); var materials = renderer.sharedMaterials; for (int i = 0; i < materials.Length; i++) { var material = materials[i]; if (!AssetDatabase.IsMainAsset(material)) { var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) && material.shader == m.shader); if (matchingMaterial != null) { materials[i] = matchingMaterial; } } } renderer.sharedMaterials = materials; } }); }); progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => { foreach (var pair in _behaviourActivity) { var targetBehaviour = pair.Key; var activityData = pair.Value; progress.Step(targetBehaviour.name); string path = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform); Type type = targetBehaviour.GetType(); string propertyName = "m_Enabled"; AnimationCurve curve = new AnimationCurve(); foreach (var dataPoint in activityData) { int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0); AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } if (curve.IsConstant()) { continue; } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.ContainsKey(binding)) { Debug.LogError("Binding already existed?"); Debug.LogError(binding.path + " : " + binding.propertyName); continue; } _curves.Add(binding, curve); } }); progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => { foreach (var pair in _transformData) { var targetTransform = pair.Key; var targetData = pair.Value; progress.Step(targetTransform.name); string path = AnimationUtility.CalculateTransformPath(targetTransform, transform); bool isActivityConstant = true; bool isPositionConstant = true; bool isRotationConstant = true; bool isScaleConstant = true; { bool startEnabled = targetData[0].enabled; Vector3 startPosition = targetData[0].localPosition; Quaternion startRotation = targetData[0].localRotation; Vector3 startScale = targetData[0].localScale; for (int i = 1; i < targetData.Count; i++) { isActivityConstant &= targetData[i].enabled == startEnabled; isPositionConstant &= targetData[i].localPosition == startPosition; isRotationConstant &= targetData[i].localRotation == startRotation; isScaleConstant &= targetData[i].localScale == startScale; } } for (int i = 0; i < TransformData.CURVE_COUNT; i++) { string propertyName = TransformData.GetName(i); Type type = typeof(Transform); AnimationCurve curve = new AnimationCurve(); var dataType = TransformData.GetDataType(i); switch (dataType) { case TransformDataType.Position: if (isPositionConstant) { continue; } break; case TransformDataType.Rotation: if (isRotationConstant) { continue; } break; case TransformDataType.Scale: if (isScaleConstant) { continue; } break; case TransformDataType.Activity: if (isActivityConstant) { continue; } type = typeof(GameObject); break; } for (int j = 0; j < targetData.Count; j++) { int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i)); if (dataType == TransformDataType.Activity) { AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.ContainsKey(binding)) { Debug.LogError("Duplicate object was created??"); Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName); } else { _curves.Add(binding, curve); } } } }); progress.Begin(_curves.Count, "", "Compressing Data: ", () => { foreach (var pair in _curves) { EditorCurveBinding binding = pair.Key; AnimationCurve curve = pair.Value; progress.Step(binding.propertyName); GameObject animationGameObject; { var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (animatedObj is GameObject) { animationGameObject = animatedObj as GameObject; } else { animationGameObject = (animatedObj as Component).gameObject; } } //But if the curve is constant, just get rid of it! if (curve.IsConstant()) { //Check to make sure there are no other matching curves that are //non constant. If X and Y are constant but Z is not, we need to //keep them all :( if (_curves.Query().Where(p => p.Key.path == binding.path && p.Key.type == binding.type && p.Key.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)). All(k => k.Value.IsConstant())) { continue; } } //First do a lossless compression curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon); Transform targetTransform = null; var targetObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (targetObj is GameObject) { targetTransform = (targetObj as GameObject).transform; } else if (targetObj is Component) { targetTransform = (targetObj as Component).transform; } else { Debug.LogError("Target obj was of type " + targetObj.GetType().Name); } var dataRecorder = targetTransform.GetComponent <RecordedData>(); if (dataRecorder == null) { dataRecorder = targetTransform.gameObject.AddComponent <RecordedData>(); } dataRecorder.data.Add(new RecordedData.EditorCurveBindingData() { path = binding.path, propertyName = binding.propertyName, typeName = binding.type.Name, curve = curve }); } }); progress.Step("Finalizing Prefab..."); var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>(); GameObject myGameObject = gameObject; DestroyImmediate(this); string targetFolderPath = targetFolder.Path; if (targetFolderPath == null) { if (myGameObject.scene.IsValid() && !string.IsNullOrEmpty(myGameObject.scene.path)) { string sceneFolder = Path.GetDirectoryName(myGameObject.scene.path); targetFolderPath = Path.Combine(sceneFolder, "Recordings"); } else { targetFolderPath = Path.Combine("Assets", "Recordings"); } } int folderSuffix = 1; string finalSubFolder; do { finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0')); folderSuffix++; } while (Directory.Exists(finalSubFolder)); Directory.CreateDirectory(finalSubFolder); AssetDatabase.Refresh(); postProcessComponent.recordingName = recordingName; postProcessComponent.assetFolder.Path = finalSubFolder; postProcessComponent.leapData = _leapData; string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab"); PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject); AssetDatabase.Refresh(); EditorApplication.isPlaying = false; }); }
/// <summary> /// /// </summary> /// <param name="trans"></param> /// <param name="selectTrans"></param> /// <param name="export">导出对象的根节点是否为export类型</param> private static void findChild(Transform trans, Transform selectTrans, bool export) { if (!export && trans.CompareTag("Except")) { return; } string propName = SimplifyName(trans.name); if (trans.CompareTag("Prefabs")) //嵌套的预制体 { propertiesStr.Append($" protected {propName}Controller _{propName}Ctrl;\n"); getPropertiesStr.Append($" _{propName}Ctrl = new {propName}Controller();\n _{propName}Ctrl.Init({selectTrans.name}.transform);\n"); return; } if (trans.childCount > 0) { for (int j = 0; j < trans.childCount; j++) { // UnityEngine.Debug.LogError ("c trans.tag=" + trans.tag); findChild(trans.GetChild(j), selectTrans, export); } } if (export && !trans.CompareTag("Export")) { return; } /* * "Slider", "Button", "Toggle", "ScrollRect", * "Image", "Animator", "Canvas", * "LocalizeTextMeshProUGUI", "Text", */ int uniqueValue; if (uniqueNames.TryGetValue(propName, out uniqueValue)) { uniqueValue = uniqueNames[propName] += 1; } else { uniqueValue = uniqueNames[propName] = 0; } if (uniqueValue > 0) { propName = $"{propName}_{uniqueValue}"; } string menType = "btn"; Component comp = trans.GetComponent <Button> (); if (comp == null) { comp = trans.GetComponent <Image> (); menType = "img"; } if (comp == null) { comp = trans.GetComponent <TMPro.TextMeshProUGUI> (); menType = "tmp"; } if (comp == null) { comp = trans.GetComponent <Text> (); menType = "txt"; } if (comp == null) { comp = trans.GetComponent <Animator> (); menType = "anim"; } if (comp == null) { comp = trans.GetComponent <Slider> (); menType = "sld"; } if (comp == null) { comp = trans.GetComponent <Toggle> (); menType = "tog"; } if (comp == null) { comp = trans.GetComponent <InputField> (); menType = "inf"; } if (comp == null) { comp = trans.GetComponent <ScrollRect> (); menType = "scr"; } if (comp == null) { comp = trans.GetComponent <Dropdown> (); menType = "dpd"; } if (comp == null) { comp = trans.GetComponent <Scrollbar> (); menType = "scb"; } if (comp == null) { comp = trans.GetComponent <Canvas> (); menType = "cvs"; } if (comp == null) { comp = trans.GetComponent <CanvasGroup> (); menType = "cgp"; } if (comp == null) { comp = trans.GetComponent <RawImage> (); menType = "imgr"; } if (comp == null) { comp = trans.GetComponent <GridLayoutGroup> (); menType = "grid"; } if (comp == null) { comp = trans.GetComponent <VerticalLayoutGroup> (); menType = "vlg"; } if (comp == null) { comp = trans.GetComponent <HorizontalLayoutGroup> (); menType = "hlg"; } if (comp == null) { comp = trans.GetComponent <HorizontalOrVerticalLayoutGroup> (); menType = "hvlg"; } var fieldName = $"_{menType}{propName}"; if (comp != null) { string className = SimplifyClassName(comp.GetType() != typeof(TMPro.TextMeshProUGUI) ? comp.GetType().ToString(): "DragonPlus.LocalizeTextMeshProUGUI"); propertiesStr.Append($" protected {className} {fieldName};\n"); //获取组件在预制体中的路径 string compPath = AnimationUtility.CalculateTransformPath(comp.transform, selectTrans); if (!uniquePaths.Contains(compPath)) { uniquePaths.Add(compPath); } else { UnityEngine.Debug.LogError(compPath + "路径重复"); } getPropertiesStr.Append($" {fieldName} = transform.Find(\"{compPath}\").GetComponent<{className}>();\n"); if (comp.GetType() == typeof(Button)) { addListenerStr.Append($" {fieldName}.onClick.AddListener({propName}Clicked);\n"); // clickListenStr.Append ($" public abstract void {propName}Clicked();\n"); clickListenOverrideStr.Append($" public void {propName}Clicked()").Append("{}\n"); removeListenerstr.Append($" {fieldName}.onClick.RemoveAllListeners();\n"); } } else { if (!export && trans.tag != "Export") { UnityEngine.Debug.LogError(comp + "减少不必要的导出"); return; } comp = trans.GetComponent <RectTransform> (); if (!comp) { UnityEngine.Debug.LogError(comp + "不是UI组件"); return; } menType = "rtf"; string className = SimplifyClassName(comp?comp.GetType().ToString() : trans.GetType().ToString()); propertiesStr.Append($" protected {className} {fieldName};\n"); string compPath = AnimationUtility.CalculateTransformPath(trans, selectTrans); if (!uniquePaths.Contains(compPath)) { uniquePaths.Add(compPath); } else { UnityEngine.Debug.LogError(compPath + "路径重复"); } getPropertiesStr.Append($" {fieldName} = transform.Find(\"{compPath}\") as {className};\n"); } }
void OnGUI() { sourceSkeleton = EditorGUILayout.ObjectField("Rig Prefab", sourceSkeleton, typeof(Transform), true) as Transform; poseFolder = EditorGUILayout.ObjectField("Pose Folder", poseFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object; EnforceFolder(ref poseFolder); EditorGUILayout.Space(); // Single pose from skeleton if (skelOpen = EditorGUILayout.Foldout(skelOpen, "Rig Source")) { EditorGUI.indentLevel++; poseSkeleton = EditorGUILayout.ObjectField("Pose Rig", poseSkeleton, typeof(Transform), false) as Transform; skelPoseID = EditorGUILayout.TextField("ID", skelPoseID); if ((sourceSkeleton == null) || (poseSkeleton == null) || (skelPoseID == null) || (skelPoseID.Length < 1)) { GUI.enabled = false; } if (GUILayout.Button("Build Pose")) { string folderPath; if (poseFolder != null) { folderPath = AssetDatabase.GetAssetPath(poseFolder); } else { folderPath = AssetDatabase.GetAssetPath(poseAnimation); folderPath = folderPath.Substring(0, folderPath.LastIndexOf('/')); } UMABonePose bonePose = CreatePoseAsset(folderPath, skelPoseID); Transform[] sourceBones = UMABonePose.GetTransformsInPrefab(sourceSkeleton); Transform[] poseBones = UMABonePose.GetTransformsInPrefab(poseSkeleton); List <UMABonePose.PoseBone> poseList = new List <UMABonePose.PoseBone>(); foreach (Transform bone in poseBones) { Transform source = System.Array.Find <Transform>(sourceBones, entry => entry.name == bone.name); if (source) { if ((bone.localPosition != source.localPosition) || (bone.localRotation != source.localRotation) || (bone.localScale != source.localScale)) { UMABonePose.PoseBone poseB = new UMABonePose.PoseBone(); poseB.bone = bone.name; poseB.position = bone.localPosition - source.localPosition; poseB.rotation = bone.localRotation * Quaternion.Inverse(source.localRotation); poseB.scale = new Vector3(bone.localScale.x / source.localScale.x, bone.localScale.y / source.localScale.y, bone.localScale.z / source.localScale.z); poseList.Add(poseB); } } else { Debug.Log("Unmatched bone: " + bone.name); } } bonePose.poses = poseList.ToArray(); EditorUtility.SetDirty(bonePose); AssetDatabase.SaveAssets(); } GUI.enabled = true; EditorGUI.indentLevel--; } EditorGUILayout.Space(); // Multiple poses from animation frames if (animOpen = EditorGUILayout.Foldout(animOpen, "Animation Source")) { EditorGUI.indentLevel++; poseAnimation = EditorGUILayout.ObjectField("Pose Animation", poseAnimation, typeof(AnimationClip), false) as AnimationClip; if (poses == null) { poses = new List <AnimationPose>(); poses.Add(new AnimationPose()); } bool validPose = false; AnimationPose deletedPose = null; scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach (AnimationPose pose in poses) { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("ID", GUILayout.Width(50f)); pose.ID = EditorGUILayout.TextField(pose.ID); EditorGUILayout.LabelField("Frame", GUILayout.Width(60f)); pose.frame = EditorGUILayout.IntField(pose.frame, GUILayout.Width(50f)); if ((pose.ID != null) && (pose.ID.Length > 0)) { validPose = true; } if (GUILayout.Button("-", GUILayout.Width(20f))) { deletedPose = pose; validPose = false; break; } GUILayout.EndHorizontal(); } if (deletedPose != null) { poses.Remove(deletedPose); } GUILayout.EndScrollView(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("+", GUILayout.Width(30f))) { poses.Add(new AnimationPose()); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Load Pose Set")) { LoadPoseSet(); } if (!validPose) { GUI.enabled = false; } if (GUILayout.Button("Save Pose Set")) { SavePoseSet(); } GUI.enabled = true; GUILayout.EndHorizontal(); if ((sourceSkeleton == null) || (poseAnimation == null) || (!validPose)) { GUI.enabled = false; } if (GUILayout.Button("Build Poses")) { string folderPath; if (poseFolder != null) { folderPath = AssetDatabase.GetAssetPath(poseFolder); } else { folderPath = AssetDatabase.GetAssetPath(poseAnimation); folderPath = folderPath.Substring(0, folderPath.LastIndexOf('/')); } Transform[] sourceBones = UMABonePose.GetTransformsInPrefab(sourceSkeleton); EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(poseAnimation); Dictionary <string, Vector3> positions = new Dictionary <string, Vector3>(); Dictionary <string, Quaternion> rotations = new Dictionary <string, Quaternion>(); Dictionary <string, Vector3> scales = new Dictionary <string, Vector3>(); foreach (AnimationPose pose in poses) { if ((pose.ID == null) || (pose.ID.Length < 1)) { Debug.LogWarning("Bad pose identifier, not building for frame: " + pose.frame); continue; } float time = (float)pose.frame / poseAnimation.frameRate; if ((time < 0f) || (time > poseAnimation.length)) { Debug.LogWarning("Bad frame number, not building for pose: " + pose.ID); continue; } positions.Clear(); rotations.Clear(); scales.Clear(); foreach (EditorCurveBinding binding in bindings) { if (binding.type == typeof(Transform)) { AnimationCurve curve = AnimationUtility.GetEditorCurve(poseAnimation, binding); float val = curve.Evaluate(time); Vector3 position; Quaternion rotation; Vector3 scale; switch (binding.propertyName) { case "m_LocalPosition.x": if (positions.TryGetValue(binding.path, out position)) { position.x = val; positions[binding.path] = position; } else { position = new Vector3(); position.x = val; positions.Add(binding.path, position); } break; case "m_LocalPosition.y": if (positions.TryGetValue(binding.path, out position)) { position.y = val; positions[binding.path] = position; } else { position = new Vector3(); position.y = val; positions.Add(binding.path, position); } break; case "m_LocalPosition.z": if (positions.TryGetValue(binding.path, out position)) { position.z = val; positions[binding.path] = position; } else { position = new Vector3(); position.z = val; positions.Add(binding.path, position); } break; case "m_LocalRotation.w": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.w = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.w = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.x": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.x = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.x = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.y": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.y = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.y = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.z": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.z = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.z = val; rotations.Add(binding.path, rotation); } break; case "m_LocalScale.x": if (scales.TryGetValue(binding.path, out scale)) { scale.x = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.x = val; scales.Add(binding.path, scale); } break; case "m_LocalScale.y": if (scales.TryGetValue(binding.path, out scale)) { scale.y = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.y = val; scales.Add(binding.path, scale); } break; case "m_LocalScale.z": if (scales.TryGetValue(binding.path, out scale)) { scale.z = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.z = val; scales.Add(binding.path, scale); } break; default: Debug.LogError("Unexpected property:" + binding.propertyName); break; } } } UMABonePose bonePose = CreatePoseAsset(folderPath, pose.ID); foreach (Transform bone in sourceBones) { string path = AnimationUtility.CalculateTransformPath(bone, sourceSkeleton.parent); Vector3 position; Quaternion rotation; Vector3 scale; if (!positions.TryGetValue(path, out position)) { position = bone.localPosition; } if (!rotations.TryGetValue(path, out rotation)) { rotation = bone.localRotation; } if (!scales.TryGetValue(path, out scale)) { scale = bone.localScale; } if ((bone.localPosition != position) || (bone.localRotation != rotation) || (bone.localScale != scale)) { bonePose.AddBone(bone, position, rotation, scale); } } EditorUtility.SetDirty(bonePose); } AssetDatabase.SaveAssets(); } GUI.enabled = true; EditorGUI.indentLevel--; } }
void UpgradeMaterials() { // upgrade material template assets var assetList = new AssetList(); assetList.AddRange( AssetDatabase.FindAssets($"t:{nameof(PhysicsMaterialTemplate)}") .Select(guid => AssetDatabase.GUIDToAssetPath(guid)) .Select(path => new Asset(path)) ); if (assetList.Count > 0) { if (IsEditable(assetList, m_Failures)) { foreach (var asset in assetList) { if (!IsEditable(asset, m_Failures)) { continue; } // material templates are upgraded in OnEnable(), so it should be sufficient to merely load them var materialTemplate = AssetDatabase.LoadAssetAtPath <PhysicsMaterialTemplate>(asset.path); EditorUtility.SetDirty(materialTemplate); m_Successes.AddEntry(asset.path, string.Empty); } } } // upgrade prefabs assetList.Clear(); foreach (var guid in AssetDatabase.FindAssets("t:Prefab")) { var prefabAssetPath = AssetDatabase.GUIDToAssetPath(guid); var prefab = AssetDatabase.LoadAssetAtPath <GameObject>(prefabAssetPath); var shapeComponents = prefab.GetComponentsInChildren <PhysicsShapeAuthoring>(true); if (shapeComponents.Length == 0) { continue; } var asset = new Asset(prefabAssetPath); if (!IsEditable(asset, m_Failures)) { continue; } assetList.Add(asset); } if (assetList.Count > 0) { if (IsEditable(assetList, m_Failures)) { var upgradedAssets = new HashSet <Asset>(); foreach (var asset in assetList) { UpgradePrefabAsset(asset, assetList, upgradedAssets, m_Successes, m_Failures); } } } // update scene objects EditorSceneManager.SetActiveScene(EditorSceneManager.NewScene(NewSceneSetup.EmptyScene)); foreach (var guid in AssetDatabase.FindAssets("t:Scene")) { var scenePath = AssetDatabase.GUIDToAssetPath(guid); var asset = new Asset(scenePath); if (!IsEditable(asset, m_Failures)) { continue; } Scene scene; try { scene = EditorSceneManager.OpenScene(scenePath); } catch (Exception e) { m_Failures.AddEntry(asset.path, $"{e.Message}\n\n{e.StackTrace}"); continue; } EditorSceneManager.SetActiveScene(scene); var succcess = true; if (IsEditable(new AssetList { new Asset(scenePath) }, m_Failures)) { var upgradedAny = false; foreach ( var sceneObject in scene.GetRootGameObjects() .Where(go => go.GetComponentsInChildren <PhysicsShapeAuthoring>(true).Any()) ) { try { UpgradePrefabInstance(sceneObject); upgradedAny = true; } catch (Exception e) { succcess = false; m_Failures.AddEntry( $"{scenePath}::{AnimationUtility.CalculateTransformPath(sceneObject.transform, sceneObject.transform.root)}", $"{e.Message}\n\n{e.StackTrace}" ); } } if (upgradedAny) { EditorSceneManager.SaveScene(scene); } } if (succcess) { m_Successes.AddEntry(scenePath, string.Empty); } EditorSceneManager.SetActiveScene(EditorSceneManager.NewScene(NewSceneSetup.EmptyScene)); EditorSceneManager.CloseScene(scene, true); } }
private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, GameObject rootGameObject, AnimationClip animationClip, TreeViewItem parent) { string path = AnimationUtility.CalculateTransformPath(gameObject.transform, rootGameObject.transform); TreeViewItem treeViewItem = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); List <TreeViewItem> list = new List <TreeViewItem>(); if (this.m_RootItem == null) { this.m_RootItem = treeViewItem; } EditorCurveBinding[] animatableBindings = AnimationUtility.GetAnimatableBindings(gameObject, rootGameObject); List <EditorCurveBinding> list2 = new List <EditorCurveBinding>(); for (int i = 0; i < animatableBindings.Length; i++) { EditorCurveBinding editorCurveBinding = animatableBindings[i]; list2.Add(editorCurveBinding); if (editorCurveBinding.propertyName == "m_IsActive") { if (editorCurveBinding.path != "") { TreeViewItem treeViewItem2 = this.CreateNode(list2.ToArray(), treeViewItem); if (treeViewItem2 != null) { list.Add(treeViewItem2); } list2.Clear(); } else { list2.Clear(); } } else { bool flag = i == animatableBindings.Length - 1; bool flag2 = false; if (!flag) { flag2 = (animatableBindings[i + 1].type != editorCurveBinding.type); } if (AnimationWindowUtility.IsCurveCreated(animationClip, editorCurveBinding)) { list2.Remove(editorCurveBinding); } if (editorCurveBinding.type == typeof(Animator) && editorCurveBinding.propertyName == "m_Enabled") { list2.Remove(editorCurveBinding); } if ((flag || flag2) && list2.Count > 0) { list.Add(this.AddAnimatableObjectToHierarchy(list2.ToArray(), treeViewItem, path)); list2.Clear(); } } } if (AddCurvesPopupHierarchyDataSource.showEntireHierarchy) { for (int j = 0; j < gameObject.transform.childCount; j++) { Transform child = gameObject.transform.GetChild(j); TreeViewItem treeViewItem3 = this.AddGameObjectToHierarchy(child.gameObject, rootGameObject, animationClip, treeViewItem); if (treeViewItem3 != null) { list.Add(treeViewItem3); } } } TreeViewUtility.SetChildParentReferences(list, treeViewItem); return(treeViewItem); }
private void addGLTFChannelDataToClip(GLTF.Schema.AnimationChannel channel, AnimationClip clip) { int animatedNodeIndex = channel.Target.Node.Id; if (!_importedObjects.ContainsKey(animatedNodeIndex)) { Debug.Log("Node '" + animatedNodeIndex + "' found for animation, aborting."); } Transform animatedNode = _importedObjects[animatedNodeIndex].transform; string nodePath = AnimationUtility.CalculateTransformPath(animatedNode, _sceneObject.transform); bool isStepInterpolation = channel.Sampler.Value.Interpolation != InterpolationType.LINEAR; byte[] timeBufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] times = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Input.Value, timeBufferData); if (channel.Target.Path == GLTFAnimationChannelPath.translation || channel.Target.Path == GLTFAnimationChannelPath.scale) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; GLTF.Math.Vector3[] keyValues = GLTFHelpers.ParseVector3Keyframes(channel.Sampler.Value.Output.Value, bufferData); if (keyValues == null) { return; } Vector3[] values = keyValues.ToUnityVector3(); AnimationCurve[] vector3Curves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation, channel.Target.Path == GLTFAnimationChannelPath.translation); if (channel.Target.Path == GLTFAnimationChannelPath.translation) { GLTFUtils.addTranslationCurvesToClip(vector3Curves, nodePath, ref clip); } else { GLTFUtils.addScaleCurvesToClip(vector3Curves, nodePath, ref clip); } } else if (channel.Target.Path == GLTFAnimationChannelPath.rotation) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; Vector4[] values = GLTFHelpers.ParseRotationKeyframes(channel.Sampler.Value.Output.Value, bufferData).ToUnityVector4(); AnimationCurve[] rotationCurves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation); GLTFUtils.addRotationCurvesToClip(rotationCurves, nodePath, ref clip); } else if (channel.Target.Path == GLTFAnimationChannelPath.weights) { List <string> morphTargets = new List <string>(); int meshIndex = _root.Nodes[animatedNodeIndex].Mesh.Id; for (int i = 0; i < _root.Meshes[meshIndex].Primitives[0].Targets.Count; ++i) { morphTargets.Add(GLTFUtils.buildBlendShapeName(meshIndex, i)); } byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] values = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Output.Value, bufferData); AnimationCurve[] morphCurves = GLTFUtils.buildMorphAnimationCurves(times, values, morphTargets.Count); GLTFUtils.addMorphAnimationCurvesToClip(morphCurves, nodePath, morphTargets.ToArray(), ref clip); } else { Debug.Log("Unsupported animation channel target: " + channel.Target.Path); } }
void DrawItem(ViewPageItem vpi, bool isViewState = false) { using (var vertical2 = new GUILayout.VerticalScope(Drawer.darkBoxStyle)) { using (var horizon = new GUILayout.HorizontalScope()) { GUILayout.Label(new GUIContent($"{vpi.displayName}", Drawer.prefabIcon), EditorStyles.whiteLabel, GUILayout.Height(16)); GUILayout.FlexibleSpace(); GUILayout.Label($"({vpi.Id})"); } if (vpi.viewElement == null) { GUILayout.Label(new GUIContent("ViewElement is not set up!", Drawer.miniErrorIcon)); return; } var selectables = vpi.viewElement.GetComponentsInChildren <Selectable>(); foreach (var select in selectables) { using (var vertical3 = new GUILayout.VerticalScope("box")) { var path = AnimationUtility.CalculateTransformPath(select.transform, vpi.viewElement.transform); var component = select.GetType().ToString(); using (var horizon = new GUILayout.HorizontalScope()) { using (var vertical4 = new GUILayout.VerticalScope()) { var p = path.Split('/'); GUILayout.Label(new GUIContent($"{vpi.viewElement.name}", Drawer.prefabIcon), GUILayout.Height(16)); for (int i = 0; i < p.Length; i++) { if (string.IsNullOrEmpty(p[i])) { continue; } using (var horizon2 = new GUILayout.HorizontalScope()) { GUILayout.Space((i + 1) * 15); GUILayout.Label(new GUIContent($"{p[i]}", Drawer.prefabIcon), GUILayout.Height(16)); } } } GUILayout.FlexibleSpace(); GUILayout.Label(new GUIContent(Drawer.arrowIcon)); var editorContent = new GUIContent(EditorGUIUtility.ObjectContent(select, select.GetType())); GUILayout.FlexibleSpace(); GUILayout.Label(editorContent, height); } ViewElementNavigationData currentNavSetting = null; ViewElementNavigationDataViewState viewElementNavigationDataViewState = null; if (isViewState == false) { currentNavSetting = vpi.navigationDatas .SingleOrDefault(m => m.targetComponentType == component && m.targetTransformPath == path ); } else { viewElementNavigationDataViewState = viewPage.navigationDatasForViewState.SingleOrDefault(m => m.viewPageItemId == vpi.Id); if (viewElementNavigationDataViewState != null) { currentNavSetting = viewElementNavigationDataViewState.navigationDatas .SingleOrDefault(m => m.targetComponentType == component && m.targetTransformPath == path ); } } bool hasSetting = currentNavSetting != null; using (var horizon = new GUILayout.HorizontalScope()) { if (GUILayout.Button("Select In Hierarchy", EditorStyles.miniButton)) { if (vpi.previewViewElement) { Selection.objects = new UnityEngine.Object[] { vpi.previewViewElement.transform.Find(path).gameObject }; } } using (var disable = new EditorGUI.DisabledGroupScope(!hasSetting)) { if (GUILayout.Button("Apply Setting", EditorStyles.miniButton)) { ApplySetting(); } } } if (!hasSetting) { if (GUILayout.Button("Add Navigation Setting")) { if (isViewState == false) { var nav = new ViewElementNavigationData(); nav.targetComponentType = component; nav.targetTransformPath = path; nav.mode = select.navigation.mode; vpi.navigationDatas.Add(nav); } else { if (viewElementNavigationDataViewState == null) { viewElementNavigationDataViewState = new ViewElementNavigationDataViewState(); viewElementNavigationDataViewState.viewPageItemId = vpi.Id; } var nav = new ViewElementNavigationData(); nav.targetComponentType = component; nav.targetTransformPath = path; nav.mode = select.navigation.mode; viewElementNavigationDataViewState.navigationDatas.Add(nav); viewPage.navigationDatasForViewState.Add(viewElementNavigationDataViewState); } } } else { using (var horizon = new GUILayout.HorizontalScope()) { using (var check = new EditorGUI.ChangeCheckScope()) { var result = (UnityEngine.UI.Navigation.Mode) EditorGUILayout.EnumPopup(currentNavSetting.mode); if (result != UnityEngine.UI.Navigation.Mode.Explicit) { currentNavSetting.mode = result; } else { ViewSystemLog.LogError("Currently Navigation Setting doesn't support Mode with Explicit"); } if (check.changed) { //Do something if (autoApplyNavigation) { ApplySetting(); } } } if (GUILayout.Button(new GUIContent(EditorGUIUtility.FindTexture("d_TreeEditor.Trash")), Drawer.removeButtonStyle, GUILayout.Width(25))) { if (isViewState == false) { vpi.navigationDatas.Remove(currentNavSetting); } else { viewElementNavigationDataViewState.navigationDatas.Remove(currentNavSetting); } } } } void ApplySetting() { if (isViewState == false) { vpi.previewViewElement.ApplyNavigation(vpi.navigationDatas); } else { vpi.previewViewElement.ApplyNavigation(viewElementNavigationDataViewState.navigationDatas); } SceneView.RepaintAll(); } } } } }
private void CacheComponent() { if (m_ComponentTreeViewState == null) { m_ComponentTreeViewState = new TreeViewState(); } componentTreeView = new ComponentTreeView( currentSelectGameObject, target, m_ComponentTreeViewState, currentSelectGameObject == target, (a, b) => { return(false); }, () => { }); componentTreeView.OnItemClick += (sp) => { Component c; try { c = (Component)sp.serializedObject.targetObject; } catch { c = ((GameObject)sp.serializedObject.targetObject).transform; } if (sp.propertyType == SerializedPropertyType.Generic) { System.Type parentType = sp.serializedObject.targetObject.GetType(); System.Reflection.FieldInfo fi = parentType.GetField(sp.propertyPath); System.Type propertyType = null; if (fi != null) { propertyType = fi.FieldType; } string propertyName = sp.propertyPath; if (parentType.ToString().Contains("UnityEngine.")) { if (propertyName == "m_Navigation") { var content = new GUIContent("UnityEngine.UI.Navigation is not supported with ViewSystem OverrideSystem"); #if UNITY_2019_1_OR_NEWER editorWindow.ShowNotification(content, toastMessageFadeOutTimt); #else editorWindow.ShowNotification(content); #endif return; } propertyName = ViewSystemUtilitys.ParseUnityEngineProperty(sp.propertyPath); } System.Reflection.PropertyInfo pi = parentType.GetProperty(propertyName); if (pi != null && fi == null) { propertyType = pi.PropertyType; } } else { data.targetTransformPath = AnimationUtility.CalculateTransformPath(c.transform, target.transform); data.targetPropertyName = sp.name; data.targetComponentType = sp.serializedObject.targetObject.GetType().ToString(); data.Value.SetValue(sp); editorWindow.Close(); } sp.serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(currentSelectGameObject); }; }
private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, GameObject rootGameObject, AnimationClip animationClip, TreeViewItem parent) { string path = AnimationUtility.CalculateTransformPath(gameObject.transform, rootGameObject.transform); AddCurvesPopupGameObjectNode node = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); List <TreeViewItem> childNodes = new List <TreeViewItem>(); if (m_RootItem == null) { m_RootItem = node; } // Iterate over all animatable objects EditorCurveBinding[] allCurveBindings = AnimationUtility.GetAnimatableBindings(gameObject, rootGameObject); List <EditorCurveBinding> singleObjectBindings = new List <EditorCurveBinding>(); for (int i = 0; i < allCurveBindings.Length; i++) { EditorCurveBinding curveBinding = allCurveBindings[i]; singleObjectBindings.Add(curveBinding); // Don't create group for GameObject.m_IsActive. It looks messy if (curveBinding.propertyName == "m_IsActive") { // Don't show for the root go if (curveBinding.path != "") { TreeViewItem newNode = CreateNode(singleObjectBindings.ToArray(), node); if (newNode != null) { childNodes.Add(newNode); } singleObjectBindings.Clear(); } else { singleObjectBindings.Clear(); } } else { // We expect allCurveBindings to come sorted by type bool isLastItemOverall = (i == allCurveBindings.Length - 1); bool isLastItemOnThisGroup = false; if (!isLastItemOverall) { isLastItemOnThisGroup = (allCurveBindings[i + 1].type != curveBinding.type); } // Let's not add those that already have a existing curve. if (AnimationWindowUtility.IsCurveCreated(animationClip, curveBinding)) { singleObjectBindings.Remove(curveBinding); } // Remove animator enabled property which shouldn't be animated. if (curveBinding.type == typeof(Animator) && curveBinding.propertyName == "m_Enabled") { singleObjectBindings.Remove(curveBinding); } if ((isLastItemOverall || isLastItemOnThisGroup) && singleObjectBindings.Count > 0) { childNodes.Add(AddAnimatableObjectToHierarchy(singleObjectBindings.ToArray(), node, path)); singleObjectBindings.Clear(); } } } var animator = rootGameObject.GetComponent <Animator>(); if (animator != null) { //If the Animator has a human avatar, we need to check if the avatar's hierarchy matches that of the current GameObject. If they do not match, disable the node. if (animator.avatarRoot != null && animator.isHuman) { if (animator.avatarRoot.Find(path) == null) { node.propertyPathMismatchWithHumanAvatar = true; } } } if (showEntireHierarchy) { // Iterate over all child GOs for (int i = 0; i < gameObject.transform.childCount; i++) { Transform childTransform = gameObject.transform.GetChild(i); TreeViewItem childNode = AddGameObjectToHierarchy(childTransform.gameObject, rootGameObject, animationClip, node); if (childNode != null) { childNodes.Add(childNode); } } } TreeViewUtility.SetChildParentReferences(childNodes, node); return(node); }
private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, TreeViewItem parent) { string path = AnimationUtility.CalculateTransformPath(gameObject.transform, this.state.activeRootGameObject.transform); TreeViewItem parentNode = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); List <TreeViewItem> visibleItems = new List <TreeViewItem>(); if (parent == null) { base.m_RootItem = parentNode; } EditorCurveBinding[] animatableBindings = AnimationUtility.GetAnimatableBindings(gameObject, this.state.activeRootGameObject); List <EditorCurveBinding> list2 = new List <EditorCurveBinding>(); for (int i = 0; i < animatableBindings.Length; i++) { EditorCurveBinding item = animatableBindings[i]; list2.Add(item); if (item.propertyName == "m_IsActive") { if (item.path != string.Empty) { TreeViewItem item2 = this.CreateNode(list2.ToArray(), parentNode); if (item2 != null) { visibleItems.Add(item2); } list2.Clear(); } else { list2.Clear(); } } else { bool flag = i == (animatableBindings.Length - 1); bool flag2 = false; if (!flag) { flag2 = animatableBindings[i + 1].type != item.type; } if (AnimationWindowUtility.IsCurveCreated(this.state.activeAnimationClip, item)) { list2.Remove(item); } if ((flag || flag2) && (list2.Count > 0)) { visibleItems.Add(this.AddAnimatableObjectToHierarchy(this.state.activeRootGameObject, list2.ToArray(), parentNode, path)); list2.Clear(); } } } if (showEntireHierarchy) { for (int j = 0; j < gameObject.transform.childCount; j++) { Transform child = gameObject.transform.GetChild(j); TreeViewItem item3 = this.AddGameObjectToHierarchy(child.gameObject, parentNode); if (item3 != null) { visibleItems.Add(item3); } } } TreeViewUtility.SetChildParentReferences(visibleItems, parentNode); return(parentNode); }
static bool SearchInChildProperties(SearchArg arg, Object suspect, bool scene, out EcsEntity entity) { if (IsTargetOrNested(arg, suspect)) { entity = default; return(false); } if (!suspect) { entity = default; return(false); } var so = new SerializedObject(suspect); _tmp.Clear(); var queue = _tmp; var propIterator = so.GetIterator(); var prefabInstance = false; if (scene && !string.IsNullOrEmpty(arg.FilePath) && PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(suspect) == arg.FilePath) { prefabInstance = true; while (propIterator.NextVisible(true)) { if (propIterator.propertyType != SerializedPropertyType.ObjectReference) { continue; } if (!IsTargetOrNested(arg, propIterator.objectReferenceValue)) { continue; } queue.Enqueue(propIterator.Copy()); } } else { while (propIterator.Next(true)) { if (propIterator.propertyType != SerializedPropertyType.ObjectReference) { continue; } if (!IsTargetOrNested(arg, propIterator.objectReferenceValue)) { continue; } queue.Enqueue(propIterator.Copy()); } } if (queue.Count == 0 && !prefabInstance) { entity = default; return(false); } entity = World.NewEntityWith(out Result data); var gui = entity.Set <SearchResultGui>(); gui.Properties = new List <SearchResultGui.PropertyData>(); gui.SerializedObject = so; gui.Label = new GUIContent(); // init header Texture2D miniTypeThumbnail = null; if (scene) { switch (suspect) { case Component component: data.RootGo = component.gameObject; gui.TransformPath = AnimationUtility.CalculateTransformPath(component.transform, null); gui.Label.image = AssetPreview.GetMiniThumbnail(data.RootGo); gui.Label.text = gui.TransformPath; break; case GameObject go: data.RootGo = go; gui.Label.image = AssetPreview.GetMiniThumbnail(data.RootGo); gui.TransformPath = AnimationUtility.CalculateTransformPath(go.transform, null); gui.Label.text = gui.TransformPath; break; default: throw new NotImplementedException(); } miniTypeThumbnail = data.RootGo.GetInstanceID() == suspect.GetInstanceID() ? null : AssetPreview.GetMiniThumbnail(suspect); } else { data.File = suspect; data.FilePath = AssetDatabase.GetAssetPath(data.File); data.MainFile = AssetDatabase.LoadMainAssetAtPath(data.FilePath); // todo var prefabInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(data.MainFile); switch (prefabInstanceStatus) { case PrefabInstanceStatus.Connected: case PrefabInstanceStatus.Disconnected: switch (data.File) { case Component comp: // transformPath = $"{AnimationUtility.CalculateTransformPath(comp.transform, null)}/".Replace("/", "/\n"); gui.TransformPath = $"{AnimationUtility.CalculateTransformPath(comp.transform, null)}"; break; case GameObject go: // transformPath = $"{AnimationUtility.CalculateTransformPath(go.transform, null)}/".Replace("/", "/\n"); gui.TransformPath = $"{AnimationUtility.CalculateTransformPath(go.transform, null)}"; break; default: // Assert.Fail("Not a component"); //todo break; } break; case PrefabInstanceStatus.NotAPrefab: case PrefabInstanceStatus.MissingAsset: if (!AssetDatabase.IsMainAsset(data.File)) { // {row.Main.name} gui.TransformPath = $"/{data.File.name}"; } break; } gui.Label.text = data.FilePath.Replace(AssetsRootPath, string.Empty); gui.Label.image = AssetDatabase.GetCachedIcon(data.FilePath); } gui.Label.tooltip = gui.TransformPath; // init properties (footer) while (queue.Count > 0) { var prop = queue.Dequeue(); var targetObject = prop.serializedObject.targetObject; var item = new SearchResultGui.PropertyData { Property = prop, Content = new GUIContent() }; item.Content.image = miniTypeThumbnail; item.Content.text = Nicify(prop, targetObject, gui.TransformPath); item.Content.tooltip = gui.TransformPath; var typeName = targetObject.GetType().Name; if (StringComparer.Ordinal.Equals(typeName, targetObject.name)) { item.Content.tooltip = $"{gui.TransformPath}.{prop.propertyPath}"; } else { item.Content.tooltip = $"{gui.TransformPath}({typeName}).{prop.propertyPath}"; } gui.Properties.Add(item: item); } return(true); }
void OnGUI() { if (GUILayout.Button("Add a Prefab")) { prefabOjects.Add(null); } EditorGUILayout.Space(); for (int i = 0; i < prefabOjects.Count; i++) { EditorGUILayout.BeginHorizontal(); prefabOjects[i] = EditorGUILayout.ObjectField(prefabOjects[i], typeof(GameObject), false) as GameObject; if (GUILayout.Button(" - ")) { prefabOjects.RemoveAt(i); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.Space(); resetLocalPosition = EditorGUILayout.Toggle("Inherit Parent Position", resetLocalPosition); resetLocalRotation = EditorGUILayout.Toggle("Inherit Parent Rotation", resetLocalRotation); removeRenderers = EditorGUILayout.Toggle("Remove Current Meshes", removeRenderers); pedestrians = EditorGUILayout.Toggle("Pedestrians", pedestrians); EditorGUILayout.Space(); if ((prefabOjects.Count == 0) || (Selection.activeTransform == null)) { EditorGUILayout.HelpBox("1. Add one or more prefabs above. \n2. Select an item in the hierarchy whose children you want to add the prefab(s) to.", MessageType.Warning); } else { if (GUILayout.Button("Add To Children")) { if ((prefabOjects == null) || (prefabOjects.Count == 0) || (Selection.activeTransform == null)) { EditorUtility.DisplayDialog("Uh oh", "You eiter forgot to select a parent object in the hierarchy or add a prefab to the list of prefabs!", "Oops!"); return; } else { for (int i = 0; i < prefabOjects.Count; i++) { if (prefabOjects[i] == null) { EditorUtility.DisplayDialog("Error", "One of the prefabs in the list are null!", "My bad, I'll remove it"); return; } } } //Remove current renderers and mesh filters on objects if (removeRenderers) { Renderer[] renderers = Selection.activeTransform.GetComponentsInChildren <Renderer>(); for (int i = 0; i < renderers.Length; i++) { DestroyImmediate(renderers[i], false); } MeshFilter[] meshFilters = Selection.activeTransform.GetComponentsInChildren <MeshFilter>(); for (int i = 0; i < meshFilters.Length; i++) { DestroyImmediate(meshFilters[i], false); } } //Add objects as prefabs to all children Transform[] selectionChildTransforms = Selection.activeTransform.GetComponentsInChildren <Transform>(); for (int i = 0; i < selectionChildTransforms.Length; i++) { if (selectionChildTransforms[i] == selectionChildTransforms[i].root) { continue; } GameObject newObject = PrefabUtility.InstantiatePrefab(prefabOjects[Random.Range(0, prefabOjects.Count)]) as GameObject; newObject.transform.parent = selectionChildTransforms[i]; if (resetLocalPosition) { newObject.transform.localPosition = Vector3.zero; } if (resetLocalRotation) { newObject.transform.localRotation = Quaternion.identity; } if (pedestrians) { PedestrianAnimationController pedestrianScript = newObject.AddComponent <PedestrianAnimationController>(); pedestrianScript.pedestrianAnimation = newObject.transform.GetComponentInChildren <Animation>(); newObject.transform.localRotation = Quaternion.Euler(90f, 0f, 0f); } } } } if (GUILayout.Button("Adjust Animations To Ground")) { //Safety check if (Selection.activeTransform == null) { EditorUtility.DisplayDialog("Error", "You didn't select a group of people!", "Oops!"); return; } //Get some references Transform rootTransform = Selection.activeTransform; Transform[] childTransforms = rootTransform.GetComponentsInChildren <Transform>(); //Duplicate the animation clip AnimationClip clipToChange = Instantiate(rootTransform.animation.clip) as AnimationClip; Ray ray; Vector3 raycastPoint; Vector3 localHitPoint; RaycastHit hitData = new RaycastHit(); string relativePathString; for (int i = 0; i < childTransforms.Length; i++) { //Show progress if ((i % 200) == 0) { EditorUtility.DisplayProgressBar("Progress", "Please wait, modifying animations...", 1.0f * ((float)i / (float)childTransforms.Length)); } if (childTransforms[i].animation == null) { //Calculate the relative path relativePathString = AnimationUtility.CalculateTransformPath(childTransforms[i], rootTransform); //Get the curves AnimationCurve xCurve = AnimationUtility.GetEditorCurve(clipToChange, relativePathString, typeof(Transform), "m_LocalPosition.x"); AnimationCurve yCurve = AnimationUtility.GetEditorCurve(clipToChange, relativePathString, typeof(Transform), "m_LocalPosition.y"); AnimationCurve zCurve = AnimationUtility.GetEditorCurve(clipToChange, relativePathString, typeof(Transform), "m_LocalPosition.z"); if (xCurve == null) { continue; } //Translate animation from local to global coordinates for (int j = 0; j < xCurve.keys.Length; j++) { raycastPoint = rootTransform.TransformPoint(new Vector3(xCurve.keys[j].value, 0f, zCurve.keys[j].value)); raycastPoint.y = 300f; ray = new Ray(raycastPoint, Vector3.down); if (Physics.Raycast(ray, out hitData, Mathf.Infinity)) { //Translate global hit point to local coordinates localHitPoint = rootTransform.InverseTransformPoint(hitData.point); //Replace the key in the curve yCurve.MoveKey(j, new Keyframe(yCurve.keys[j].time, localHitPoint.y)); yCurve.SmoothTangents(j, 0); //Move the actual object to the initial keyframe position if (j == 0) { childTransforms[i].localPosition = new Vector3(xCurve.keys[j].value, yCurve.keys[j].value, zCurve.keys[j].value); } } } //Set curves back to animation clipToChange.SetCurve(relativePathString, typeof(Transform), "m_LocalPosition.x", xCurve); clipToChange.SetCurve(relativePathString, typeof(Transform), "m_LocalPosition.y", yCurve); clipToChange.SetCurve(relativePathString, typeof(Transform), "m_LocalPosition.z", zCurve); //Remove scale curves to improve performance clipToChange.SetCurve(relativePathString, typeof(Transform), "m_LocalScale", null); childTransforms[i].localScale = Vector3.one; } } //Set the animation back to the object clipToChange.name = rootTransform.animation.clip.name; rootTransform.animation.RemoveClip(rootTransform.animation.clip); rootTransform.animation.clip = clipToChange; //Clear progress bar EditorUtility.ClearProgressBar(); } }
static ResultRow GenerateResultRowByObject(SearchTarget target, Object c, bool isScene = true) { if (target.Check(c)) { return(null); } if (target.Root == c) { return(null); } var so = new SerializedObject(c); var sp = so.GetIterator(); ResultRow row = null; while (sp.Next(true)) { string transformPath = string.Empty; if (sp.propertyType != SerializedPropertyType.ObjectReference || !target.Check(sp.objectReferenceValue)) { continue; } if (row == null) { row = new ResultRow { Root = c, Target = c, SerializedObject = so }; if (isScene) { var component = c as Component; if (component) { row.Main = component.gameObject; } else { var o = c as GameObject; if (o != null) { row.Main = o; } } var go = row.Main as GameObject; // Assert.NotNull(go); row.LabelContent.text = AnimationUtility.CalculateTransformPath(go.transform, null); row.LabelContent.image = AssetPreview.GetMiniThumbnail(go); } else { var path = AssetDatabase.GetAssetPath(c); row.Main = AssetDatabase.LoadMainAssetAtPath(path); var mainType = PrefabUtility.GetPrefabAssetType(row.Main); if (mainType != PrefabAssetType.NotAPrefab) { var comp = row.Target as Component; if (comp) { try { transformPath = string.Format("{0}/", AnimationUtility.CalculateTransformPath(comp.transform, null)).Replace("/", "/\n"); } catch { // ignored } } } row.LabelContent.text = path.Replace(AssetsRootPath, string.Empty); row.LabelContent.image = AssetDatabase.GetCachedIcon(path); } } Texture2D miniTypeThumbnail = row.Main == c ? null : AssetPreview.GetMiniThumbnail(c); row.Properties.Add(new ResultRow.PropertyData { Property = sp.Copy(), Content = new GUIContent { image = miniTypeThumbnail, text = Nicify(sp, sp.serializedObject.targetObject, row.Main, target), tooltip = string.Format("{2}{0}.{1}", sp.serializedObject.targetObject.GetType().Name, sp.propertyPath, transformPath) } }); } if (row == null) { so.Dispose(); } return(row); }
private static void SetAnimationCurvesForBody(Animator animator, GameObject rootObject, TransformTime[] transforms, AnimationClip animationClip, MoCapMecanimBone bone, bool setPosition, bool setRotation, bool setScale) { if (animator == null) { throw new Exception("Animator can not be null!"); } if (rootObject == null) { throw new Exception("Root object can not be null!"); } if (transforms == null || transforms.Length == 0) { throw new Exception("Transforms can not be empty!"); } if (animationClip == null) { throw new Exception("Animation clip can not be null!"); } if (!MoCapBoneMapper.IsValidMecanimBone(bone)) { throw new Exception("Invalid Mecanim bone!"); } var relativeTransform = animator.GetBoneTransform((HumanBodyBones)bone); var relativePath = AnimationUtility.CalculateTransformPath(relativeTransform, rootObject.transform); var keyframesTransformPositionX = new Keyframe[transforms.Length]; var keyframesTransformPositionY = new Keyframe[transforms.Length]; var keyframesTransformPositionZ = new Keyframe[transforms.Length]; var keyframesTransformRotationX = new Keyframe[transforms.Length]; var keyframesTransformRotationY = new Keyframe[transforms.Length]; var keyframesTransformRotationZ = new Keyframe[transforms.Length]; var keyframesTransformRotationW = new Keyframe[transforms.Length]; var keyframesTransformScaleX = new Keyframe[transforms.Length]; var keyframesTransformScaleY = new Keyframe[transforms.Length]; var keyframesTransformScaleZ = new Keyframe[transforms.Length]; for (var i = 0; i < transforms.Length; i++) { var transform = transforms[i]; keyframesTransformPositionX[i] = new Keyframe(transform.Time, transform.Position.X); keyframesTransformPositionY[i] = new Keyframe(transform.Time, transform.Position.Y); keyframesTransformPositionZ[i] = new Keyframe(transform.Time, transform.Position.Z); keyframesTransformRotationX[i] = new Keyframe(transform.Time, transform.Rotation.X); keyframesTransformRotationY[i] = new Keyframe(transform.Time, transform.Rotation.Y); keyframesTransformRotationZ[i] = new Keyframe(transform.Time, transform.Rotation.Z); keyframesTransformRotationW[i] = new Keyframe(transform.Time, transform.Rotation.W); keyframesTransformScaleX[i] = new Keyframe(transform.Time, transform.Scale.X); keyframesTransformScaleY[i] = new Keyframe(transform.Time, transform.Scale.Y); keyframesTransformScaleZ[i] = new Keyframe(transform.Time, transform.Scale.Z); } var animationCurvePositionX = new AnimationCurve(keyframesTransformPositionX); var animationCurvePositionY = new AnimationCurve(keyframesTransformPositionY); var animationCurvePositionZ = new AnimationCurve(keyframesTransformPositionZ); if (setPosition) { animationClip.SetCurve(relativePath, typeof(Transform), "localPosition.x", animationCurvePositionX); animationClip.SetCurve(relativePath, typeof(Transform), "localPosition.y", animationCurvePositionY); animationClip.SetCurve(relativePath, typeof(Transform), "localPosition.z", animationCurvePositionZ); } var animationCurveRotationX = new AnimationCurve(keyframesTransformRotationX); var animationCurveRotationY = new AnimationCurve(keyframesTransformRotationY); var animationCurveRotationZ = new AnimationCurve(keyframesTransformRotationZ); var animationCurveRotationW = new AnimationCurve(keyframesTransformRotationW); if (setRotation) { animationClip.SetCurve(relativePath, typeof(Transform), "localRotation.x", animationCurveRotationX); animationClip.SetCurve(relativePath, typeof(Transform), "localRotation.y", animationCurveRotationY); animationClip.SetCurve(relativePath, typeof(Transform), "localRotation.z", animationCurveRotationZ); animationClip.SetCurve(relativePath, typeof(Transform), "localRotation.w", animationCurveRotationW); } var animationCurveScaleX = new AnimationCurve(keyframesTransformScaleX); var animationCurveScaleY = new AnimationCurve(keyframesTransformScaleY); var animationCurveScaleZ = new AnimationCurve(keyframesTransformScaleZ); if (setScale) { animationClip.SetCurve(relativePath, typeof(Transform), "localScale.x", animationCurveScaleX); animationClip.SetCurve(relativePath, typeof(Transform), "localScale.y", animationCurveScaleY); animationClip.SetCurve(relativePath, typeof(Transform), "localScale.z", animationCurveScaleZ); } }
protected void finishRecording(ProgressBar progress) { string targetFolderPath = targetFolder.Path; if (targetFolderPath == null) { if (gameObject.scene.IsValid() && !string.IsNullOrEmpty(gameObject.scene.path)) { string sceneFolder = Path.GetDirectoryName(gameObject.scene.path); targetFolderPath = Path.Combine(sceneFolder, "Recordings"); } else { targetFolderPath = Path.Combine("Assets", "Recordings"); } } int folderSuffix = 1; string finalSubFolder; do { finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0')); folderSuffix++; } while (Directory.Exists(finalSubFolder)); string dataDirectory = Path.Combine(finalSubFolder, "_Data"); Directory.CreateDirectory(dataDirectory); Directory.CreateDirectory(finalSubFolder); AssetDatabase.Refresh(); progress.Begin(6, "Saving Recording", "", () => { if (!_isRecording) { return; } _isRecording = false; //Turn on auto-pushing for all auto-proxy components foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>()) { autoProxy.autoPushingEnabled = true; } progress.Begin(3, "", "Reverting Scene State", () => { //For all of our transform data, revert to the first piece recorded progress.Begin(_transformData.Count, "", "", () => { foreach (var pair in _transformData) { progress.Step(); var transform = pair.Key; var data = pair.Value; if (transform == null || data.Count == 0) { continue; } data[0].ApplyTo(transform); } }); //For all recorded curves, revert to start of curve progress.Begin(_curves.Count, "", "", () => { AnimationClip tempClip = new AnimationClip(); foreach (var data in _curves) { progress.Step(); AnimationUtility.SetEditorCurve(tempClip, data.binding, data.curve); } tempClip.SampleAnimation(gameObject, 0); }); //For all non-transform components, revert to original serialized values progress.Begin(_initialComponentData.Count, "", "", () => { foreach (var pair in _initialComponentData) { progress.Step(); var component = pair.Key; var sobj = pair.Value; if (component == null || component is Transform) { continue; } //We don't want to revert method recordings! if (component is MethodRecording || component is RecordedAudio) { continue; } var flags = sobj.FindProperty("m_ObjectHideFlags"); if (flags == null) { Debug.LogError("Could not find hide flags for " + component); continue; } //We have to dirty the serialized object somehow //apparently there is no api to do this //all objects have hide flags so we just touch them and revert them int originalFlags = flags.intValue; flags.intValue = ~originalFlags; flags.intValue = originalFlags; try { //Applies previous state of entire component sobj.ApplyModifiedProperties(); } catch (Exception e) { Debug.LogError("Exception when trying to apply properties to " + component); Debug.LogException(e); } } }); }); progress.Begin(1, "", "Patching Materials: ", () => { GetComponentsInChildren(true, _recorders); foreach (var recorder in _recorders) { DestroyImmediate(recorder); } //Patch up renderer references to materials var allMaterials = Resources.FindObjectsOfTypeAll <Material>(). Query(). Where(AssetDatabase.IsMainAsset). ToList(); var renderers = GetComponentsInChildren <Renderer>(includeInactive: true); progress.Begin(renderers.Length, "", "", () => { foreach (var renderer in renderers) { progress.Step(renderer.name); var materials = renderer.sharedMaterials; for (int i = 0; i < materials.Length; i++) { var material = materials[i]; if (material == null) { continue; } if (!AssetDatabase.IsMainAsset(material)) { var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) && material.shader == m.shader); if (matchingMaterial != null) { materials[i] = matchingMaterial; } } } renderer.sharedMaterials = materials; } }); }); progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => { foreach (var pair in _behaviourActivity) { var targetBehaviour = pair.Key; var activityData = pair.Value; if (targetBehaviour == null) { continue; } progress.Step(targetBehaviour.name); string path = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform); Type type = targetBehaviour.GetType(); string propertyName = "m_Enabled"; AnimationCurve curve = new AnimationCurve(); foreach (var dataPoint in activityData) { int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0); AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } if (curve.IsConstant()) { continue; } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Binding already existed?"); Debug.LogError(binding.path + " : " + binding.propertyName); continue; } _curves.Add(new CurveData() { binding = binding, curve = curve }); } }); progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => { foreach (var pair in _transformData) { var targetTransform = pair.Key; var targetData = pair.Value; progress.Step(targetTransform.name); string path = AnimationUtility.CalculateTransformPath(targetTransform, transform); bool isActivityConstant = true; bool isPositionConstant = true; bool isRotationConstant = true; bool isScaleConstant = true; { bool startEnabled = targetData[0].enabled; Vector3 startPosition = targetData[0].localPosition; Quaternion startRotation = targetData[0].localRotation; Vector3 startScale = targetData[0].localScale; for (int i = 1; i < targetData.Count; i++) { isActivityConstant &= targetData[i].enabled == startEnabled; isPositionConstant &= targetData[i].localPosition == startPosition; isRotationConstant &= targetData[i].localRotation == startRotation; isScaleConstant &= targetData[i].localScale == startScale; } } for (int i = 0; i < TransformData.CURVE_COUNT; i++) { string propertyName = TransformData.GetName(i); Type type = typeof(Transform); AnimationCurve curve = new AnimationCurve(); var dataType = TransformData.GetDataType(i); switch (dataType) { case TransformDataType.Position: if (isPositionConstant) { continue; } break; case TransformDataType.Rotation: if (isRotationConstant) { continue; } break; case TransformDataType.Scale: if (isScaleConstant) { continue; } break; case TransformDataType.Activity: if (isActivityConstant) { continue; } type = typeof(GameObject); break; } for (int j = 0; j < targetData.Count; j++) { int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i)); if (dataType == TransformDataType.Activity) { AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Duplicate object was created??"); Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName); } else { _curves.Add(new CurveData() { binding = binding, curve = curve }); } } } }); progress.Begin(_curves.Count, "", "Compressing Data: ", () => { _curves.Sort((a, b) => a.binding.propertyName.CompareTo(b.binding.propertyName)); foreach (var data in _curves) { using (new ProfilerSample("A")) { EditorCurveBinding binding = data.binding; AnimationCurve curve = data.curve; progress.Step(binding.propertyName); GameObject animationGameObject; { var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (animatedObj is GameObject) { animationGameObject = animatedObj as GameObject; } else { animationGameObject = (animatedObj as Component).gameObject; } } bool isMatBinding = binding.propertyName.StartsWith("material.") && binding.type.IsSubclassOf(typeof(Renderer)); //But if the curve is constant, just get rid of it! //Except for material curves, which we always need to keep if (curve.IsConstant() && !isMatBinding) { //Check to make sure there are no other matching curves that are //non constant. If X and Y are constant but Z is not, we need to //keep them all :( if (_curves.Query().Where(p => p.binding.path == binding.path && p.binding.type == binding.type && p.binding.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)). All(k => k.curve.IsConstant())) { continue; } } //First do a lossless compression using (new ProfilerSample("B")) { curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon, checkSteps: 3); } Transform targetTransform = null; var targetObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (targetObj is GameObject) { targetTransform = (targetObj as GameObject).transform; } else if (targetObj is Component) { targetTransform = (targetObj as Component).transform; } else { Debug.LogError("Target obj was of type " + targetObj.GetType().Name); } } } }); }); progress.Begin(4, "Finalizing Assets", "", () => { var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>(); GameObject myGameObject = gameObject; DestroyImmediate(this); //Create all the files for the method recording progress.Step("Creating Method Recording Files..."); var methodRecordings = myGameObject.GetComponentsInChildren <MethodRecording>(); for (int i = 0; i < methodRecordings.Length; i++) { var methodRecording = methodRecordings[i]; string fullPath = Path.Combine(finalSubFolder, "MethodRecording_" + i + ".asset"); methodRecording.ExitRecordingMode(fullPath); } postProcessComponent.dataFolder = new AssetFolder(dataDirectory); //Create the asset that holds all of the curve data progress.Begin(_curves.Count, "", "", () => { string curveFile = Path.Combine(dataDirectory, "Curves.data"); using (var writer = File.CreateText(curveFile)) { foreach (var data in _curves) { progress.Step(data.binding.propertyName); var bindingData = new EditorCurveBindingData() { path = data.binding.path, propertyName = data.binding.propertyName, typeName = data.binding.type.Name, curve = data.curve }; writer.WriteLine(JsonUtility.ToJson(bindingData)); } } }); //Create the asset that holds all of the leap data if (_leapData.Count > 0) { progress.Begin(_leapData.Count, "", "", () => { string leapFile = Path.Combine(dataDirectory, "Frames.data"); using (var writer = File.CreateText(leapFile)) { for (int i = 0; i < _leapData.Count; i++) { progress.Step("Frame " + i); writer.WriteLine(JsonUtility.ToJson(_leapData[i])); } } }); } progress.Step("Creating Final Prefab..."); //Init the post process component postProcessComponent.recordingName = recordingName; postProcessComponent.assetFolder = new AssetFolder(finalSubFolder); string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab"); PrefabUtility.SaveAsPrefabAsset(myGameObject, prefabPath.Replace('\\', '/')); AssetDatabase.Refresh(); EditorApplication.isPlaying = false; }); }
// unity event handlers #endregion "unity event handlers" #region "public method" // public method public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); // Draw label position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); // Don't make child fields be indented var indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; // Calculate rects var btnRect = new Rect(position.x, position.y, 25, LINEHEIGHT); var trPathRect = new Rect(position.x + 27, position.y, position.width - 27, LINEHEIGHT); // Draw fields - pass GUIContent.none to each so they are drawn without labels if (GUI.Button(btnRect, "C")) { m_bSelectingTransform = !m_bSelectingTransform; } if (property.FindPropertyRelative(F_VALID).boolValue) { EditorGUI.PropertyField(trPathRect, property.FindPropertyRelative(F_TRPATH), GUIContent.none); } else { EditorGUI.LabelField(trPathRect, "NULL"); } if (m_bSelectingTransform) { var objSelectRect = new Rect(position.x, position.y + LINEHEIGHT, position.width, LINEHEIGHT); Transform selfTr = ((MonoBehaviour)(property.serializedObject.targetObject)).transform; Transform tr = EditorGUI.ObjectField(objSelectRect, selfTr, typeof(Transform), true) as Transform; if (tr != selfTr) { if (tr == null) { _SetTrPath(property, null); } else { Transform ccroot = _FindCCRoot(tr); if (ccroot == null) { string trPath = CCTrPath.SceneRoot + AnimationUtility.CalculateTransformPath(tr, null); _SetTrPath(property, trPath); EUtil.ShowNotification("TrPath: " + trPath, 4.0f); } else { string trPath = AnimationUtility.CalculateTransformPath(tr, ccroot); _SetTrPath(property, trPath); EUtil.ShowNotification("TrPath: " + trPath, 4.0f); } } m_bSelectingTransform = false; } } // Set indent back to what it was EditorGUI.indentLevel = indent; EditorGUI.EndProperty(); }