Ejemplo n.º 1
0
        public static List <MeshUtility.MeshIntegrationResult> Integrate(GameObject prefab)
        {
            Undo.RecordObject(prefab, "Mesh Integration");
            var instance = SkinnedMeshUtility.InstantiatePrefab(prefab);


            var clips = new List <BlendShapeClip>();
            var proxy = instance.GetComponent <VRMBlendShapeProxy>();

            if (proxy != null && proxy.BlendShapeAvatar != null)
            {
                clips = proxy.BlendShapeAvatar.Clips;
            }
            foreach (var clip in clips)
            {
                Undo.RecordObject(clip, "Mesh Integration");
            }

            // Backup Exists
            BackupVrmPrefab(prefab);

            // Execute
            var results = VRMMeshIntegratorUtility.Integrate(instance, clips);

            foreach (var res in results)
            {
                if (res.IntegratedRenderer == null)
                {
                    continue;
                }

                SaveMeshAsset(res.IntegratedRenderer.sharedMesh, instance, res.IntegratedRenderer.gameObject.name);
                Undo.RegisterCreatedObjectUndo(res.IntegratedRenderer.gameObject, "Integrate Renderers");
            }

            // destroy source renderers
            foreach (var res in results)
            {
                foreach (var renderer in res.SourceSkinnedMeshRenderers)
                {
                    Undo.RecordObject(renderer.gameObject, "Deactivate old renderer");
                    renderer.gameObject.SetActive(false);
                }

                foreach (var renderer in res.SourceMeshRenderers)
                {
                    Undo.RecordObject(renderer.gameObject, "Deactivate old renderer");
                    renderer.gameObject.SetActive(false);
                }
            }

            // Apply to Prefab
            SkinnedMeshUtility.ApplyChangesToPrefab(instance);
            Object.DestroyImmediate(instance);

            return(results);
        }
Ejemplo n.º 2
0
        /// 2022.05 仕様変更
        ///
        /// * prefab 専用
        /// * backup するのではなく 変更した copy を作成する。元は変えない
        ///   * copy 先の統合前の renderer を disable で残さず destroy する
        /// * 実行すると mesh, blendshape, blendShape を新規に作成する
        /// * 新しいヒエラルキーを prefab に保存してから削除して終了する
        ///
        void Integrate()
        {
            if (m_root.GetGameObjectType() != GameObjectType.AssetPrefab)
            {
                throw new Exception("for prefab only");
            }

            String folder = "Assets";
            var    prefab = m_root.GetPrefab();

            if (prefab != null)
            {
                folder = AssetDatabase.GetAssetPath(prefab);
                Debug.Log(folder);
            }

            // 新規で作成されるアセットはすべてこのフォルダの中に作る。上書きチェックはしない
            var assetFolder = EditorUtility.SaveFolderPanel("select asset save folder", Path.GetDirectoryName(folder), "VrmIntegrated");
            var unityPath   = UniGLTF.UnityPath.FromFullpath(assetFolder);

            if (!unityPath.IsUnderAssetsFolder)
            {
                EditorUtility.DisplayDialog("asset folder", "Target folder must be in the `Assets` folder", "cancel");
                return;
            }
            assetFolder = unityPath.Value;

            var copy = GameObject.Instantiate(m_root);

            // 統合
            var excludes = m_excludes.Where(x => x.Exclude).Select(x => x.Mesh);
            var results  = Integrate(copy, excludes, m_separateByBlendShape);

            // write mesh asset
            foreach (var result in results)
            {
                var childAssetPath = $"{assetFolder}/{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}";
                Debug.LogFormat("CreateAsset: {0}", childAssetPath);
                AssetDatabase.CreateAsset(result.IntegratedRenderer.sharedMesh, childAssetPath);
            }

            // 統合した結果をヒエラルキーに追加する
            foreach (var result in results)
            {
                if (result.IntegratedRenderer != null)
                {
                    result.IntegratedRenderer.transform.SetParent(copy.transform, false);
                }
            }

            // 統合した結果を反映した BlendShapeClip を作成して置き換える
            var clips = VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder);

            // 用が済んだ 統合前 の renderer を削除する
            foreach (var result in results)
            {
                foreach (var renderer in result.SourceMeshRenderers)
                {
                    GameObject.DestroyImmediate(renderer);
                }
                foreach (var renderer in result.SourceSkinnedMeshRenderers)
                {
                    GameObject.DestroyImmediate(renderer);
                }
            }

            // reset firstperson
            var firstperson = copy.GetComponent <VRMFirstPerson>();

            if (firstperson != null)
            {
                firstperson.Reset();
            }

            // prefab
            var prefabPath = $"{assetFolder}/VrmIntegrated.prefab";

            Debug.Log(prefabPath);
            PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success);
            if (!success)
            {
                throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}");
            }

            // destroy scene
            UnityEngine.Object.DestroyImmediate(copy);

            var prefabReference = AssetDatabase.LoadAssetAtPath <GameObject>(prefabPath);

            foreach (var clip in clips)
            {
                var so = new SerializedObject(clip);
                so.Update();
                // clip.Prefab = copy;
                var prop = so.FindProperty("m_prefab");
                prop.objectReferenceValue = prefabReference;
                so.ApplyModifiedProperties();
            }
        }