// Magica Cloth.
// Copyright (c) MagicaSoft, 2020-2022.
// https://magicasoft.jp
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace MagicaCloth
{
///
/// ボーンクロスのエディタ拡張
///
[CustomEditor(typeof(MagicaBoneCloth))]
public class MagicaBoneClothInspector : ClothEditor
{
protected override void OnEnable()
{
base.OnEnable();
}
public override void OnInspectorGUI()
{
MagicaBoneCloth scr = target as MagicaBoneCloth;
// データ状態
EditorInspectorUtility.DispVersionStatus(scr);
EditorInspectorUtility.DispDataStatus(scr);
serializedObject.Update();
Undo.RecordObject(scr, "CreateBoneCloth");
// データ検証
if (EditorApplication.isPlaying == false)
VerifyData();
// モニターボタン
EditorInspectorUtility.MonitorButtonInspector();
// メイン
MainInspector();
// コライダー
ColliderInspector();
// スキニング
SkinningInspector();
// パラメータ
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorPresetUtility.DrawPresetButton(scr, scr.Params);
{
var cparam = serializedObject.FindProperty("clothParams");
if (EditorInspectorUtility.AlgorithmInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.Algorithm), ConvertToLatestAlgorithmParameters))
scr.Params.SetChangeParam(ClothParams.ParamType.Algorithm);
if (EditorInspectorUtility.RadiusInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.Radius);
if (EditorInspectorUtility.MassInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.Mass);
if (EditorInspectorUtility.GravityInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.Gravity);
if (EditorInspectorUtility.ExternalForceInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.ExternalForce);
if (EditorInspectorUtility.DragInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.Drag);
if (EditorInspectorUtility.MaxVelocityInspector(cparam))
scr.Params.SetChangeParam(ClothParams.ParamType.MaxVelocity);
if (EditorInspectorUtility.WorldInfluenceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.WorldInfluence)))
scr.Params.SetChangeParam(ClothParams.ParamType.WorldInfluence);
if (EditorInspectorUtility.DistanceDisableInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.DistanceDisable)))
scr.Params.SetChangeParam(ClothParams.ParamType.DistanceDisable);
if (EditorInspectorUtility.ClampDistanceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ClampDistance)))
scr.Params.SetChangeParam(ClothParams.ParamType.ClampDistance);
if (EditorInspectorUtility.ClampPositionInspector(cparam, true, scr.HasChangedParam(ClothParams.ParamType.ClampPosition)))
scr.Params.SetChangeParam(ClothParams.ParamType.ClampPosition);
if (EditorInspectorUtility.ClampRotationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ClampRotation), scr.ClothData))
scr.Params.SetChangeParam(ClothParams.ParamType.ClampRotation);
if (EditorInspectorUtility.RestoreDistanceInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RestoreDistance)))
scr.Params.SetChangeParam(ClothParams.ParamType.RestoreDistance);
if (EditorInspectorUtility.RestoreRotationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RestoreRotation), scr.ClothData))
scr.Params.SetChangeParam(ClothParams.ParamType.RestoreRotation);
if (scr.ClothTarget.IsMeshConnection)
{
if (EditorInspectorUtility.TriangleBendInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.TriangleBend), scr.ClothData))
scr.Params.SetChangeParam(ClothParams.ParamType.TriangleBend);
}
if (EditorInspectorUtility.CollisionInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.ColliderCollision)))
scr.Params.SetChangeParam(ClothParams.ParamType.ColliderCollision);
if (EditorInspectorUtility.PenetrationInspector(serializedObject, cparam, scr.HasChangedParam(ClothParams.ParamType.Penetration)))
scr.Params.SetChangeParam(ClothParams.ParamType.Penetration);
//if (EditorInspectorUtility.BaseSkinningInspector(serializedObject, cparam))
// scr.Params.SetChangeParam(ClothParams.ParamType.BaseSkinning);
if (EditorInspectorUtility.RotationInterpolationInspector(cparam, scr.HasChangedParam(ClothParams.ParamType.RotationInterpolation)))
scr.Params.SetChangeParam(ClothParams.ParamType.RotationInterpolation);
}
serializedObject.ApplyModifiedProperties();
// データ作成
if (EditorApplication.isPlaying == false)
{
EditorGUI.BeginDisabledGroup(CheckCreate() == false);
EditorGUILayout.Space();
EditorGUILayout.Space();
GUI.backgroundColor = Color.red;
if (GUILayout.Button("Create"))
{
Undo.RecordObject(scr, "CreateBoneCloth");
// 共有選択データが存在しない場合は作成する
if (scr.ClothSelection == null)
InitSelectorData();
BuildManager.CreateComponent(scr);
}
GUI.backgroundColor = Color.white;
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUILayout.Space();
EditorGUILayout.Space();
GUI.backgroundColor = Color.blue;
if (GUILayout.Button("Reset Position"))
{
scr.ResetCloth();
}
GUI.backgroundColor = Color.white;
}
EditorGUILayout.Space();
}
//=========================================================================================
///
/// 作成を実行できるか判定する
///
///
protected override bool CheckCreate()
{
if (PointSelector.EditEnable)
return false;
return true;
}
///
/// データ検証
///
private void VerifyData()
{
MagicaBoneCloth scr = target as MagicaBoneCloth;
if (scr.VerifyData() != Define.Error.None)
{
// 検証エラー
serializedObject.ApplyModifiedProperties();
}
}
//=========================================================================================
void MainInspector()
{
MagicaBoneCloth scr = target as MagicaBoneCloth;
EditorGUILayout.LabelField("Main Setup", EditorStyles.boldLabel);
// ルートリスト
EditorInspectorUtility.DrawObjectList(
serializedObject.FindProperty("clothTarget.rootList"),
scr.gameObject,
false, true,
() => scr.gameObject.transform.root.GetComponentsInChildren()
);
//EditorGUILayout.Space();
// 接続モード
EditorGUILayout.PropertyField(serializedObject.FindProperty("clothTarget.connection"), new GUIContent("Connection Mode"));
if (scr.ClothTarget.IsMeshConnection)
EditorGUILayout.PropertyField(serializedObject.FindProperty("clothTarget.sameSurfaceAngle"), new GUIContent("Same Surface Angle"));
if (scr.ClothTarget.Connection == BoneClothTarget.ConnectionMode.MeshSequentialLoop || scr.ClothTarget.Connection == BoneClothTarget.ConnectionMode.MeshSequentialNoLoop)
{
// 警告
EditorGUILayout.HelpBox("RootList must be registered in the order of connection for sequential connection.", MessageType.Info);
}
// チーム項目
TeamBasicInspector();
// アニメーション連動
//scr.ClothTarget.IsAnimationBone = EditorGUILayout.Toggle("Is Animation Bones", scr.ClothTarget.IsAnimationBone);
//scr.ClothTarget.IsAnimationPosition = EditorGUILayout.Toggle("Is Animation Position", scr.ClothTarget.IsAnimationPosition);
//scr.ClothTarget.IsAnimationRotation = EditorGUILayout.Toggle("Is Animation Rotation", scr.ClothTarget.IsAnimationRotation);
// ポイント選択
DrawInspectorGUI(scr);
EditorGUILayout.Space();
// カリング
CullingInspector();
}
//=========================================================================================
///
/// 選択データの初期化
/// 配列はすでに頂点数分が確保されゼロクリアされています。
///
///
protected override void OnResetSelector(List selectorData)
{
// ルートトランスフォームのみ固定で初期化する
MagicaBoneCloth scr = target as MagicaBoneCloth;
// 現在の頂点選択データをコピー
// また新規データの場合はボーン階層のルートを固定化する
if (scr.ClothSelection != null)
{
// 既存
var sel = scr.ClothSelection.GetSelectionData(scr.MeshData, null);
for (int i = 0; i < selectorData.Count; i++)
{
if (i < sel.Count)
selectorData[i] = sel[i];
}
}
else
{
// 新規
var tlist = scr.GetTransformList();
for (int i = 0; i < tlist.Count; i++)
{
var t = tlist[i];
int data = 0;
if (scr.ClothTarget.GetRootIndex(t) >= 0)
{
// 固定
data = SelectionData.Fixed;
}
else
{
// 移動
data = SelectionData.Move;
}
selectorData[i] = data;
}
}
}
///
/// 選択データの決定
///
///
protected override void OnFinishSelector(List selectorData)
{
MagicaBoneCloth scr = target as MagicaBoneCloth;
// 必ず新規データを作成する(ヒエラルキーでのコピー対策)
var sel = CreateSelection(scr, "clothSelection");
// 選択データコピー
sel.SetSelectionData(scr.MeshData, selectorData, null);
// 現在のデータと比較し差異がない場合は抜ける
if (scr.ClothSelection != null && scr.ClothSelection.Compare(sel))
return;
//if (scr.ClothSelection != null)
// Undo.RecordObject(scr.ClothSelection, "Set Selector");
// 保存
var cdata = serializedObject.FindProperty("clothSelection");
cdata.objectReferenceValue = sel;
serializedObject.ApplyModifiedProperties();
}
}
}