public void SelectGUI() { if (m_avatar != null && m_avatar.Clips != null) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Select BlendShapeClip", EditorStyles.boldLabel); var array = m_avatar.Clips .Select(x => x != null ? BlendShapeKey.CreateFromClip(x).ToString() : "null" ).ToArray(); SelectedIndex = GUILayout.SelectionGrid(SelectedIndex, array, 4); } if (GUILayout.Button("Create BlendShapeClip")) { var dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(m_avatar)); var path = EditorUtility.SaveFilePanel( "Create BlendShapeClip", dir, string.Format("BlendShapeClip#{0}.asset", m_avatar.Clips.Count), "asset"); if (!string.IsNullOrEmpty(path)) { var clip = BlendShapeAvatar.CreateBlendShapeClip(path.ToUnityRelativePath()); //clip.Prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GetAssetPath(target)); m_avatar.Clips.Add(clip); // save clips EditorUtility.SetDirty(m_avatar); } } }
void LoadBlendShapeMaster() { BlendShapeAvatar = ScriptableObject.CreateInstance <BlendShapeAvatar>(); BlendShapeAvatar.name = "BlendShape"; var transformMeshTable = new Dictionary <Mesh, Transform>(); foreach (var transform in Root.transform.Traverse()) { if (transform.GetSharedMesh() != null) { transformMeshTable.Add(transform.GetSharedMesh(), transform); } } var blendShapeList = GLTF.extensions.VRM.blendShapeMaster.blendShapeGroups; if (blendShapeList != null && blendShapeList.Count > 0) { foreach (var x in blendShapeList) { BlendShapeAvatar.Clips.Add(LoadBlendShapeBind(x, transformMeshTable)); } } var proxy = Root.AddComponent <VRMBlendShapeProxy>(); BlendShapeAvatar.CreateDefaultPreset(); proxy.BlendShapeAvatar = BlendShapeAvatar; }
/// <summary> /// 使用されない BlendShape を間引いた Mesh を作成して置き換える /// </summary> /// <param name="mesh"></param> /// <returns></returns> static void ReplaceMesh(GameObject target, SkinnedMeshRenderer smr, BlendShapeAvatar copyBlendShapeAvatar) { Mesh mesh = smr.sharedMesh; if (mesh == null) { return; } if (mesh.blendShapeCount == 0) { return; } // Mesh から BlendShapeClip からの参照がある blendShape の index を集める var usedBlendshapeIndexArray = copyBlendShapeAvatar.Clips .SelectMany(clip => clip.Values) .Where(val => target.transform.Find(val.RelativePath) == smr.transform) .Select(val => val.Index) .Distinct() .ToArray(); var copyMesh = MeshUtility.MeshExtensions.Copy(mesh, copyBlendShape: false); // 使われている BlendShape だけをコピーする foreach (var i in usedBlendshapeIndexArray) { var name = mesh.GetBlendShapeName(i); var vCount = mesh.vertexCount; var vertices = new Vector3[vCount]; var normals = new Vector3[vCount]; var tangents = new Vector3[vCount]; mesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents); copyMesh.AddBlendShapeFrame(name, 100f, vertices, normals, tangents); } // BlendShapeClip の BlendShapeIndex を更新する(前に詰める) var indexMapper = usedBlendshapeIndexArray .Select((x, i) => new { x, i }) .ToDictionary(pair => pair.x, pair => pair.i); foreach (var clip in copyBlendShapeAvatar.Clips) { for (var i = 0; i < clip.Values.Length; ++i) { var value = clip.Values[i]; if (target.transform.Find(value.RelativePath) != smr.transform) { continue; } value.Index = indexMapper[value.Index]; clip.Values[i] = value; } } // mesh を置き換える smr.sharedMesh = copyMesh; }
protected override void OnEnable() { PrefabChanged += OnPrefabChanged; base.OnEnable(); m_target = (BlendShapeAvatar)target; CurrentClip = m_target.Clips[0]; }
public BlendShapeClipSelector(BlendShapeAvatar avatar, Action <BlendShapeClip> onSelected) { avatar.RemoveNullClip(); m_avatar = avatar; m_onSelected = onSelected; onSelected(Selected); }
protected override void OnEnable() { m_selector = new BlendShapeClipSelector((BlendShapeAvatar)target, OnSelected); var prop = serializedObject.FindProperty("Clips"); m_clipList = new ReorderableList(serializedObject, prop); m_clipList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, "BlendShapeClips"); m_clipList.elementHeight = BlendShapeClipDrawer.Height; m_clipList.drawElementCallback = (rect, index, isActive, isFocused) => { var element = prop.GetArrayElementAtIndex(index); rect.height -= 4; rect.y += 2; EditorGUI.PropertyField(rect, element); }; m_clipList.onAddCallback += (list) => { // Add slot prop.arraySize++; // select last item list.index = prop.arraySize - 1; // get last item var element = prop.GetArrayElementAtIndex(list.index); element.objectReferenceValue = null; var dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(target)); var path = EditorUtility.SaveFilePanel( "Create BlendShapeClip", dir, string.Format("BlendShapeClip#{0}.asset", list.count), "asset"); if (!string.IsNullOrEmpty(path)) { var clip = BlendShapeAvatar.CreateBlendShapeClip(path.ToUnityRelativePath()); //clip.Prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GetAssetPath(target)); element.objectReferenceValue = clip; } }; m_clipList.onSelectCallback += (list) => { var a = list.serializedProperty; var selected = a.GetArrayElementAtIndex(list.index); OnSelected((BlendShapeClip)selected.objectReferenceValue); }; //m_clipList.onCanRemoveCallback += list => true; base.OnEnable(); OnSelected(m_selector.Selected); }
/// <summary> /// DeepCopy /// </summary> /// <param name="src"></param> /// <returns></returns> static BlendShapeAvatar CopyBlendShapeAvatar(BlendShapeAvatar src, bool removeUnknown) { var avatar = GameObject.Instantiate(src); avatar.Clips = new List <BlendShapeClip>(); foreach (var clip in src.Clips) { if (removeUnknown && clip.Preset == BlendShapePreset.Unknown) { continue; } avatar.Clips.Add(GameObject.Instantiate(clip)); } return(avatar); }
protected override void OnEnable() { PrefabChanged += OnPrefabChanged; base.OnEnable(); m_target = (BlendShapeAvatar)target; // remove missing values foreach (var x in m_target.Clips.Select((x, i) => new { i, x }).Where(x => x.x == null).Reverse()) { m_target.Clips.RemoveAt(x.i); } CurrentClip = m_target.Clips[0]; }
void LoadBlendShapeMaster() { BlendShapeAvatar = ScriptableObject.CreateInstance <BlendShapeAvatar>(); BlendShapeAvatar.name = "BlendShape"; var blendShapeList = GLTF.extensions.VRM.blendShapeMaster.blendShapeGroups; if (blendShapeList != null && blendShapeList.Count > 0) { foreach (var x in blendShapeList) { BlendShapeAvatar.Clips.Add(LoadBlendShapeBind(x)); } } var proxy = Root.AddComponent <VRMBlendShapeProxy>(); BlendShapeAvatar.CreateDefaultPreset(); proxy.BlendShapeAvatar = BlendShapeAvatar; }