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;
        }
Example #3
0
        /// <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);
        }
Example #6
0
        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);
        }
Example #7
0
        /// <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];
        }
Example #9
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;
        }