// 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);
}
}
}