//=========================================================================================
        public override int GetDataHash()
        {
            int hash = base.GetDataHash();

            hash += virtualDeformer.GetDataHash();
            hash += centerTransform.GetDataHash();
            hash += SpringData.GetDataHash();
            return(hash);
        }
        //=========================================================================================
        /// <summary>
        /// データ作成
        /// </summary>
        void CreateData()
        {
            MagicaMeshSpring scr = target as MagicaMeshSpring;

            Debug.Log("Started creating. [" + scr.name + "]");

            // センタートランスフォーム
            if (scr.CenterTransform == null)
            {
                serializedObject.FindProperty("centerTransform").objectReferenceValue = scr.transform;
            }

            // デフォーマーリスト整理
            //scr.VerifyDeformer();

            // 共有データオブジェクト作成
            SpringData sdata = ShareDataObject.CreateShareData <SpringData>("SpringData_" + scr.name);

            serializedObject.ApplyModifiedProperties();
            CreateClothData(scr, sdata, scr.GetDeformer(0));

            // データ検証
            sdata.CreateVerifyData();

            // 新しいデータを設定
            serializedObject.FindProperty("springData").objectReferenceValue = sdata;
            serializedObject.ApplyModifiedProperties();

            // 仮想デフォーマーのハッシュを設定
            //var property = serializedObject.FindProperty("virtualDeformerHash");
            //property.intValue = scr.VirtualDeformerHash;
            //serializedObject.ApplyModifiedProperties();

            // データ検証
            scr.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(sdata);

            if (scr.VerifyData() == Define.Error.None)
            {
                Debug.Log("Creation completed. [" + scr.name + "]");
            }
            else
            {
                Debug.LogError("Creation failed.");
            }
        }
        //=========================================================================================
        /// <summary>
        /// スプリング頂点追加
        /// </summary>
        /// <param name="group"></param>
        /// <param name="vertexIndex">自身のメッシュ頂点インデックス</param>
        /// <param name="particleIndex">対象のパーティクルインデックス</param>
        /// <param name="weight">比重(0.0-1.0)</param>
        /// <returns></returns>
        public void Add(int group, int vertexIndex, int particleIndex, float weight)
        {
            var data = new SpringData()
            {
                particleIndex = particleIndex,
                weight        = math.saturate(weight)
            };

            springMap.Add(vertexIndex, data);
            springVertexList.Add(vertexIndex);

            if (groupIndexDict.ContainsKey(group) == false)
            {
                groupIndexDict.Add(group, new List <int>());
            }
            groupIndexDict[group].Add(vertexIndex);
        }
        /// <summary>
        /// sourceの共有データを複製して再セットする
        /// 再セットした共有データを返す
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public override ShareDataObject DuplicateShareDataObject(ShareDataObject source)
        {
            var sdata = base.DuplicateShareDataObject(source);

            if (sdata != null)
            {
                return(sdata);
            }

            if (SpringData == source)
            {
                //springData = Instantiate(SpringData);
                springData = ShareDataObject.Clone(SpringData);
                return(springData);
            }

            return(null);
        }
        void CreateClothData(MagicaMeshSpring scr, SpringData sdata, BaseMeshDeformer deformer)
        {
            SpringData.DeformerData data = new SpringData.DeformerData();

            // 中心位置と方向
            var spos = scr.CenterTransform.position;
            var sdir = scr.CenterTransformDirection;
            var srot = scr.CenterTransform.rotation;
            var sscl = scr.Params.SpringRadiusScale;

            // 半径
            float sradius = scr.Params.SpringRadius;

            // マトリックス
            var mat  = Matrix4x4.TRS(spos, srot, sscl);
            var imat = mat.inverse;

            // メッシュデータ
            List <Vector3> wposList;
            List <Vector3> wnorList;
            List <Vector3> wtanList;
            int            vcnt = deformer.GetEditorPositionNormalTangent(out wposList, out wnorList, out wtanList);

            // 使用頂点とウエイト
            List <int>   selectionList      = Enumerable.Repeat(SelectionData.Invalid, vcnt).ToList(); // 仮のセレクションデータ
            List <int>   useVertexIndexList = new List <int>();
            List <float> weightList         = new List <float>();

            for (int i = 0; i < vcnt; i++)
            {
                // 範囲チェック
                var lpos = imat.MultiplyPoint(wposList[i]);
                var dist = lpos.magnitude;
                if (dist <= sradius)
                {
                    // 距離割合
                    var dratio = Mathf.InverseLerp(0.0f, sradius, dist);
                    var dpower = scr.Params.GetSpringDistanceAtten(dratio);

                    // 方向割合
                    var dir    = wposList[i] - spos;
                    var ang    = Vector3.Angle(sdir, dir);
                    var aratio = Mathf.InverseLerp(0.0f, 180.0f, ang);
                    var apower = scr.Params.GetSpringDirectionAtten(aratio);

                    // ウエイト算出
                    float weight = Mathf.Clamp01(dpower * apower * scr.Params.SpringIntensity);

                    // 登録
                    useVertexIndexList.Add(i);
                    weightList.Add(weight);

                    selectionList[i] = SelectionData.Move;
                }
            }

            // 利用頂点とトライアングル接続する頂点をウエイト0でマークする
            // クロスデータ用にセレクションデータを拡張する
            // (1)無効頂点の隣接が移動/固定頂点なら拡張に変更する
            selectionList = deformer.MeshData.ExtendSelection(selectionList, true, false);
            // 拡張となった頂点を固定としてウエイト0でマークする
            for (int i = 0; i < vcnt; i++)
            {
                if (selectionList[i] == SelectionData.Extend)
                {
                    useVertexIndexList.Add(i);
                    weightList.Add(0.0f);
                }
            }

            // デフォーマーデータ登録
            data.deformerDataHash   = deformer.GetDataHash();
            data.vertexCount        = deformer.MeshData.VertexCount;
            data.useVertexIndexList = useVertexIndexList.ToArray();
            data.weightList         = weightList.ToArray();

            sdata.deformerData = data;

            // 設計時スケール
            Transform influenceTarget = scr.Params.GetInfluenceTarget() ? scr.Params.GetInfluenceTarget() : scr.transform;

            sdata.initScale = influenceTarget.lossyScale;
        }