private static void ProcessAnimation(AnimationClip clip, MouthModel mouthModel, Transform animationRoot, Transform jawRoot) { var bindings = AnimationUtility.GetCurveBindings(clip); var uBinding = bindings.FirstOrDefault(binding => binding.propertyName == "material._MainTex_mouth_ST.z"); var vBinding = bindings.FirstOrDefault(binding => binding.propertyName == "material._MainTex_mouth_ST.w"); if (uBinding.path == null || vBinding.path == null) { Debug.LogWarning("Couldn't find animation binding for clip " + clip.name); return; } var uCurve = AnimationUtility.GetEditorCurve(clip, uBinding); var vCurve = AnimationUtility.GetEditorCurve(clip, vBinding); var snapshotsAtPath = new Dictionary<string, AnimationSnapshotData>(); for (int i = 0; i < uCurve.keys.Length; i++) { // We can assume that that the curves for the U and V value have the same keyframes Vector2 uvValue = new Vector2(uCurve.keys[i].value, vCurve.keys[i].value); mouthModel.CurrentPoseIndex = RtdxTextureToMouthType.ContainsKey(uvValue) ? RtdxTextureToMouthType[uvValue] : 0; TraverseRig(jawRoot, snapshotsAtPath, GetRelativePath(jawRoot, animationRoot), uCurve.keys[i].time); } foreach (var snapshot in snapshotsAtPath) { snapshot.Value.ApplyToClip(clip); clip.EnsureQuaternionContinuity(); } AnimationHelpers.SetAnimationTangentsToConstant(clip); }
private static UnityEngine.AnimationClip ProcessClip(AssetStudio.AnimationClip animationClip, string savePath, string bundleName, string materialAttributeName, CoordinateAttributeSet attributeSet, UnityEngine.SkinnedMeshRenderer[] skinnedMeshRenderers) { var uCurve = new UnityEngine.AnimationCurve(); var vCurve = new UnityEngine.AnimationCurve(); var clip = animationClip.m_MuscleClip.m_Clip; var streamedFrames = clip.m_StreamedClip.ReadData(); var clipBindingConstant = animationClip.m_ClipBindingConstant; for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++) { StreamedClip.StreamedCurveKey uCoordKey = null, vCoordKey = null; foreach (var key in streamedFrames[frameIndex].keyList) { var binding = clipBindingConstant.FindBinding(key.index); if (binding.attribute == attributeSet.UAttribute) { uCoordKey = key; } else if (binding.attribute == attributeSet.VAttribute) { vCoordKey = key; } } if (uCoordKey == null || vCoordKey == null) { continue; } // Round to 0.25 steps since the input UVs might not match perfectly var roundedUv = new Vector2(Mathf.Round(uCoordKey.value * 4) / 4, Mathf.Round(vCoordKey.value * 4) / 4); var value = RtdxTextureTo2x4Mappings[roundedUv]; uCurve.AddKey(streamedFrames[frameIndex].time, value.x); vCurve.AddKey(streamedFrames[frameIndex].time, value.y); } var newClip = new UnityEngine.AnimationClip { frameRate = animationClip.m_SampleRate }; foreach (var skinnedMeshRenderer in skinnedMeshRenderers) { AnimationUtility.SetEditorCurve(newClip, new EditorCurveBinding { path = skinnedMeshRenderer.gameObject.name, type = typeof(UnityEngine.SkinnedMeshRenderer), propertyName = $"material.{materialAttributeName}.z" }, uCurve); AnimationUtility.SetEditorCurve(newClip, new EditorCurveBinding { path = skinnedMeshRenderer.gameObject.name, type = typeof(UnityEngine.SkinnedMeshRenderer), propertyName = $"material.{materialAttributeName}.w" }, vCurve); } // We need to use this stupid workaround instead of doing it when adding the key because // apparently it glitches if the curve wasn't added to an animation AnimationHelpers.SetAnimationTangentsToConstant(newClip); string animationPath = $"{savePath}/{animationClip.m_Name}.anim"; AssetDatabase.CreateAsset(newClip, animationPath); AssetImporter.GetAtPath(animationPath).assetBundleName = bundleName; return(newClip); }