// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace MagicaCloth { public static partial class BuildManager { /// /// 共有データの作成 /// /// /// /// 共有データ保存先プレハブパス.null=保存しない /// static T CreateShareData(string dataName, string savePrefabPath) where T : ShareDataObject { // 共有データ作成 var sdata = ShareDataObject.CreateShareData(dataName); // 同時にプレハブにデータを保存するか判定 // (データをアセットデータベースで直接作成する場合) if (string.IsNullOrEmpty(savePrefabPath) == false) { SaveShareDataSubAsset(sdata, savePrefabPath); } return sdata; } /// /// 共有データを指定プレハブのサブアセットとして保存する /// /// /// /// static bool SaveShareDataSubAsset(ShareDataObject sdata, string savePrefabPath) { // 保存先プレハブアセット var savePrefab = AssetDatabase.LoadAssetAtPath(savePrefabPath); if (savePrefab == null) return false; // 編集不可のプレハブならば保存できないため処理を行わない if (PrefabUtility.IsPartOfImmutablePrefab(savePrefab)) { return false; } // サブアセットとしてプレハブに保存する AssetDatabase.AddObjectToAsset(sdata, savePrefab); return true; } /// /// 指定コンポーネントの共有データが外部にアセットとして保存されているか判定する /// /// /// static bool IsExternalShareDataObject(CoreComponent core) { Debug.Assert(core); bool ret = false; try { if (core is BaseCloth) { var cloth = core as BaseCloth; if (cloth.ClothData != null) ret = AssetDatabase.IsForeignAsset(cloth.ClothData) ? true : ret; if (cloth is MagicaMeshSpring) ret = AssetDatabase.IsForeignAsset((cloth as MagicaMeshSpring).SpringData) ? true : ret; } else if (core is MagicaRenderDeformer) { ret = AssetDatabase.IsForeignAsset((core as MagicaRenderDeformer).Deformer.MeshData) ? true : ret; } else if (core is MagicaVirtualDeformer) { ret = AssetDatabase.IsForeignAsset((core as MagicaVirtualDeformer).Deformer.MeshData) ? true : ret; } } catch (Exception) { // Reference is missing! ret = false; } return ret; } /// /// データが未作成か判定する /// /// /// static bool IsNotCreated(CoreComponent core) { Debug.Assert(core); return Define.IsError(core.VerifyData()); } /// /// データが古いフォーマットか判定する /// /// /// static bool IsOldFormat(CoreComponent core) { Debug.Assert(core); return core.IsOldDataVertion(); } /// /// 古いアルゴリズムを使用しているか判定する /// /// /// static bool IsOldAlgorithm(CoreComponent core) { Debug.Assert(core); if (core is BaseCloth) { var cloth = core as BaseCloth; // パラメータの設定が古いアルゴリズムを指している if (cloth.Params.AlgorithmType != ClothParams.Algorithm.Algorithm_2) return true; // すでに作成されたデータのアルゴリズムが古い if (cloth.ClothData != null && Define.IsError(cloth.VerifyAlgorithmVersion())) return true; } return false; } /// /// 指定ゲームオブジェクトからビルドに必要なコンポーネントを検索しリストに追加する /// /// /// /// /// static void GetBuildComponents(GameObject gobj, BuildOptions options, List coreComponents) { if (gobj == null) return; // シーンに配置されているか bool isScene = gobj.scene.IsValid(); // 全コンポーネント取得 var components = new List( gobj.GetComponentsInChildren(options.includeInactive) // コンバートコンポーネントの選別 .Where(x => x is MagicaBoneCloth && options.buildBoneCloth || x is MagicaBoneSpring && options.buildBoneSpring || x is MagicaMeshCloth && options.buildMeshCloth || x is MagicaMeshSpring && options.buildMeshSpring || x is MagicaRenderDeformer && options.buildRenderDeformer || x is MagicaVirtualDeformer && options.buildVirtualDeformer ) // シーン配置の場合は共有データが外部に保存されているなら無効とする .Where(x => isScene == false || IsExternalShareDataObject(x) == false) // ビルド条件 .Where(x => options.forceBuild || options.verificationOnly || options.notCreated && IsNotCreated(x) || options.upgradeFormatAndAlgorithm && (IsOldFormat(x) || IsOldAlgorithm(x)) ) ); coreComponents.AddRange(components); } /// /// コンポーネントリストをビルド順番にソートする /// /// static void SortCoreComponents(List coreComponents) { // RenderDeformer > VirtualDeformer > ClothComponent の順でソートする // この順でデータを作成しないと駄目! coreComponents.Sort((a, b) => a.GetComponentType() < b.GetComponentType() ? -1 : 1); } /// /// データを保存するアセットパスを取得する /// プレハブかつシーンに配置されていない場合のみ有効なパスが帰る /// /// /// static string GetAssetSavePath(CoreComponent core) { if (core == null) return null; return EditorUtility.IsPersistent(core) ? PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(core) : null; } /// /// 指定オブジェクト(プレハブ)にMissingスクリプトが含まれているかチェックする /// /// /// static bool CheckMissingScripts(GameObject go) { return go.GetComponentsInChildren().Contains(null); } } }