public static void SetToDefaultFaceEmotion(VRCAvatar editAvatar, VRCAvatar originalAvatar) { var defaultFaceEmotion = GetAvatarFaceParamaters(editAvatar.SkinnedMeshList); editAvatar.DefaultFaceEmotion = defaultFaceEmotion; ApplyAnimationProperties(defaultFaceEmotion, originalAvatar); }
public static void ResetToDefaultFaceEmotion(VRCAvatar avatar) { if (avatar == null) { return; } ApplyAnimationProperties(avatar.DefaultFaceEmotion, avatar); }
/// <summary> /// 選択したblendshapeのプロパティを反映する /// </summary> /// <param name="animProperties"></param> /// <param name="skinnedMeshes"></param> public static void ApplyAnimationProperties(List <AnimParam> animProperties, VRCAvatar avatar) { for (int skinnedMeshIndex = 0; skinnedMeshIndex < avatar.SkinnedMeshList.Count; skinnedMeshIndex++) { IFaceEmotionSkinnedMesh skinnedMesh = avatar.SkinnedMeshList[skinnedMeshIndex]; if (skinnedMesh.BlendShapeCount <= 0) { continue; } var mesh = skinnedMesh.Mesh; var renderer = skinnedMesh.Renderer; var blendshapes = skinnedMesh.Blendshapes; if (renderer == null) { continue; } // 一旦すべてリセットする for (int i = 0; i < avatar.DefaultFaceEmotion.Count; i++) { var defaultAnimProperty = avatar.DefaultFaceEmotion[i]; var index = mesh.GetBlendShapeIndex(defaultAnimProperty.BlendShapeName); if (index < 0) { continue; } renderer.SetBlendShapeWeight(index, defaultAnimProperty.Value); blendshapes[index].IsContains = false; } // アニメーションファイルに含まれるものだけ値を変更して // 適用させるチェックマークにチェックをいれる foreach (var animProperty in animProperties) { var index = mesh.GetBlendShapeIndex(animProperty.BlendShapeName); if (index >= 0) { renderer.SetBlendShapeWeight(index, animProperty.Value); blendshapes[index].IsContains = true; } } } }
/// <summary> /// BlendShapeの値をすべてリセットする /// </summary> public static void ResetAllBlendShapeValues(VRCAvatar avatar) { foreach (var skinnedMesh in avatar.SkinnedMeshList) { if (!skinnedMesh.IsOpenBlendShapes || skinnedMesh.BlendShapeCount <= 0) { continue; } foreach (var blendshape in skinnedMesh.Blendshapes) { if (blendshape.IsContains) { SetBlendShapeMinValue(skinnedMesh.Renderer, blendshape.Id); } } } }
/// <summary> /// 指定したBlendShapeのアニメーションファイルを作成する /// </summary> public static AnimationClip CreateBlendShapeAnimationClip(string fileName, string saveFolderPath, VRCAvatar avatar, bool addKeyTo0FrameOnly = false) { AnimationClip animClip = new AnimationClip(); if (fileName == "") { fileName = "face_emotion"; } foreach (IFaceEmotionSkinnedMesh skinnedMesh in avatar.SkinnedMeshList) { if (!skinnedMesh.IsOpenBlendShapes || skinnedMesh.BlendShapeCount <= 0) { continue; } string path = AnimationUtility.CalculateTransformPath(skinnedMesh.Renderer.transform, avatar.Animator.transform); foreach (var blendshape in skinnedMesh.Blendshapes) { float keyValue; AnimationCurve curve = new AnimationCurve(); if (!blendshape.IsExclusion && blendshape.IsContains) { keyValue = skinnedMesh.Renderer.GetBlendShapeWeight(blendshape.Id); curve.keys = null; curve.AddKey(0, keyValue); if (!addKeyTo0FrameOnly) { curve.AddKey(1 / 60.0f, keyValue); } animClip.SetCurve(path, typeof(SkinnedMeshRenderer), "blendShape." + blendshape.Name, curve); } } } AssetDatabase.CreateAsset(animClip, AssetDatabase.GenerateUniqueAssetPath(saveFolderPath + fileName + ".anim")); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); return(animClip); }
public static void ApplyAnimationProperties(AnimationClip clip, VRCAvatar avatar) { var paramList = GetAnimationParamaters(clip); ApplyAnimationProperties(paramList, avatar); }