public override void WriteDataXML(XElement ele, ElderScrollsPlugin master)
        {
            XElement subEle;

            if (EditorID != null)
            {
                ele.TryPathTo("EditorID", true, out subEle);
                EditorID.WriteXML(subEle, master);
            }
            if (Version != null)
            {
                ele.TryPathTo("Version", true, out subEle);
                Version.WriteXML(subEle, master);
            }
            if (GeneralData != null)
            {
                ele.TryPathTo("GeneralData", true, out subEle);
                GeneralData.WriteXML(subEle, master);
            }
            if (ActorBase != null)
            {
                ele.TryPathTo("ActorBase", true, out subEle);
                ActorBase.WriteXML(subEle, master);
            }
            if (BodyPartData != null)
            {
                ele.TryPathTo("BodyPartData", true, out subEle);
                BodyPartData.WriteXML(subEle, master);
            }
            if (FeedbackData != null)
            {
                ele.TryPathTo("FeedbackData", true, out subEle);
                FeedbackData.WriteXML(subEle, master);
            }
            if (DynamicBones != null)
            {
                ele.TryPathTo("DynamicBones", true, out subEle);
                DynamicBones.WriteXML(subEle, master);
            }
            if (PoseMatchingData != null)
            {
                ele.TryPathTo("PoseMatchingData", true, out subEle);
                PoseMatchingData.WriteXML(subEle, master);
            }
            if (DeathPose != null)
            {
                ele.TryPathTo("DeathPose", true, out subEle);
                DeathPose.WriteXML(subEle, master);
            }
        }
 public override void WriteData(ESPWriter writer)
 {
     if (EditorID != null)
     {
         EditorID.WriteBinary(writer);
     }
     if (Version != null)
     {
         Version.WriteBinary(writer);
     }
     if (GeneralData != null)
     {
         GeneralData.WriteBinary(writer);
     }
     if (ActorBase != null)
     {
         ActorBase.WriteBinary(writer);
     }
     if (BodyPartData != null)
     {
         BodyPartData.WriteBinary(writer);
     }
     if (FeedbackData != null)
     {
         FeedbackData.WriteBinary(writer);
     }
     if (DynamicBones != null)
     {
         DynamicBones.WriteBinary(writer);
     }
     if (PoseMatchingData != null)
     {
         PoseMatchingData.WriteBinary(writer);
     }
     if (DeathPose != null)
     {
         DeathPose.WriteBinary(writer);
     }
 }
        public override void ReadData(ESPReader reader, long dataEnd)
        {
            while (reader.BaseStream.Position < dataEnd)
            {
                string subTag = reader.PeekTag();

                switch (subTag)
                {
                case "EDID":
                    if (EditorID == null)
                    {
                        EditorID = new SimpleSubrecord <String>();
                    }

                    EditorID.ReadBinary(reader);
                    break;

                case "NVER":
                    if (Version == null)
                    {
                        Version = new SimpleSubrecord <UInt32>();
                    }

                    Version.ReadBinary(reader);
                    break;

                case "DATA":
                    if (GeneralData == null)
                    {
                        GeneralData = new RagdollData();
                    }

                    GeneralData.ReadBinary(reader);
                    break;

                case "XNAM":
                    if (ActorBase == null)
                    {
                        ActorBase = new RecordReference();
                    }

                    ActorBase.ReadBinary(reader);
                    break;

                case "TNAM":
                    if (BodyPartData == null)
                    {
                        BodyPartData = new RecordReference();
                    }

                    BodyPartData.ReadBinary(reader);
                    break;

                case "RAFD":
                    if (FeedbackData == null)
                    {
                        FeedbackData = new RagdollFeedbackData();
                    }

                    FeedbackData.ReadBinary(reader);
                    break;

                case "RAFB":
                    if (DynamicBones == null)
                    {
                        DynamicBones = new RagdollDynamicBones();
                    }

                    DynamicBones.ReadBinary(reader);
                    break;

                case "RAPS":
                    if (PoseMatchingData == null)
                    {
                        PoseMatchingData = new RagdollPoseMatching();
                    }

                    PoseMatchingData.ReadBinary(reader);
                    break;

                case "ANAM":
                    if (DeathPose == null)
                    {
                        DeathPose = new SimpleSubrecord <String>();
                    }

                    DeathPose.ReadBinary(reader);
                    break;

                default:
                    throw new Exception();
                }
            }
        }
        public override void ReadDataXML(XElement ele, ElderScrollsPlugin master)
        {
            XElement subEle;

            if (ele.TryPathTo("EditorID", false, out subEle))
            {
                if (EditorID == null)
                {
                    EditorID = new SimpleSubrecord <String>();
                }

                EditorID.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("Version", false, out subEle))
            {
                if (Version == null)
                {
                    Version = new SimpleSubrecord <UInt32>();
                }

                Version.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("GeneralData", false, out subEle))
            {
                if (GeneralData == null)
                {
                    GeneralData = new RagdollData();
                }

                GeneralData.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("ActorBase", false, out subEle))
            {
                if (ActorBase == null)
                {
                    ActorBase = new RecordReference();
                }

                ActorBase.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("BodyPartData", false, out subEle))
            {
                if (BodyPartData == null)
                {
                    BodyPartData = new RecordReference();
                }

                BodyPartData.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("FeedbackData", false, out subEle))
            {
                if (FeedbackData == null)
                {
                    FeedbackData = new RagdollFeedbackData();
                }

                FeedbackData.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("DynamicBones", false, out subEle))
            {
                if (DynamicBones == null)
                {
                    DynamicBones = new RagdollDynamicBones();
                }

                DynamicBones.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("PoseMatchingData", false, out subEle))
            {
                if (PoseMatchingData == null)
                {
                    PoseMatchingData = new RagdollPoseMatching();
                }

                PoseMatchingData.ReadXML(subEle, master);
            }
            if (ele.TryPathTo("DeathPose", false, out subEle))
            {
                if (DeathPose == null)
                {
                    DeathPose = new SimpleSubrecord <String>();
                }

                DeathPose.ReadXML(subEle, master);
            }
        }
        /// <summary>
        /// VRChatアバターインスタンスからVRMインスタンスへ変換します。
        /// </summary>
        /// <param name="instance">ヒエラルキー上のGameObject。</param>
        /// <param name="presetVRChatBindingPairs">各表情への割り当て。</param>
        internal static void Convert(
            string outputPath,
            GameObject instance,
            VRMMetaObject meta,
            IDictionary <ExpressionPreset, VRChatExpressionBinding> presetVRChatBindingPairs
            )
        {
            GameObject clone = null, normalized = null;

            try
            {
                var rootObjectName = instance.name;
                clone = Object.Instantiate(instance);

                // 非表示のオブジェクト・コンポーネントを削除
                // TODO: アクティブ・非アクティブの切り替えをシェイプキーに変換する
                VRChatToVRMConverter.RemoveInactiveObjectsAndDisabledComponents(clone);


                // 表情とシェイプキー名の組み合わせを取得
                var presetShapeKeyNameWeightPairsPairs = presetVRChatBindingPairs.ToDictionary(
                    presetVRChatBindingPair => presetVRChatBindingPair.Key,
                    presetVRChatBindingPair => VRChatExpressionsReplacer.ExtractShapeKeyNames(presetVRChatBindingPair.Value)
                    );

                // VRM設定1
                var temporaryFolder = UnityPath.FromUnityPath(VRChatToVRMConverter.TemporaryFolderPath);
                temporaryFolder.EnsureFolder();
                var temporaryPrefabPath = temporaryFolder.Child(VRChatToVRMConverter.TemporaryPrefabFileName).Value;
                VRMInitializer.Initialize(temporaryPrefabPath, clone);
                VRChatToVRMConverter.SetFirstPersonOffset(clone);
                VRChatToVRMConverter.SetLookAtBoneApplyer(clone);
                var sourceAndDestination = clone.GetComponent <Animator>();
                if (DynamicBones.IsImported())
                {
                    DynamicBonesToVRMSpringBonesConverter.Convert(
                        source: sourceAndDestination,
                        destination: sourceAndDestination
                        );
                    VRChatToVRMConverter.RemoveUnusedColliderGroups(clone);
                }

                // 正規化
                normalized = VRMBoneNormalizer.Execute(clone, forceTPose: true);

                // 全メッシュ結合
                var combinedRenderer = CombineMeshesAndSubMeshes.Combine(
                    normalized,
                    notCombineRendererObjectNames: new List <string>(),
                    destinationObjectName: "vrm-mesh",
                    savingAsAsset: false
                    );

                // 使用していないシェイプキーの削除
                SkinnedMeshUtility.CleanUpShapeKeys(combinedRenderer.sharedMesh, presetShapeKeyNameWeightPairsPairs
                                                    .SelectMany(presetShapeKeyNameWeightPairsPair => presetShapeKeyNameWeightPairsPair.Value.Keys)
                                                    .Distinct());

                // シェイプキーの分離
                Utilities.MeshUtility.SeparationProcessing(normalized);

                // マテリアルの設定・アセットとして保存
                VRChatToVRMConverter.ReplaceShaders(normalized, temporaryPrefabPath);

                // GameObject・メッシュなどをアセットとして保存 (アセットとして存在しないと正常にエクスポートできない)
                normalized.name = rootObjectName;
                var animator = normalized.GetComponent <Animator>();
                animator.avatar = Duplicator.CreateObjectToFolder(animator.avatar, temporaryPrefabPath);
                meta.name       = "Meta";
                normalized.GetComponent <VRMMeta>().Meta = Duplicator.CreateObjectToFolder(meta, temporaryPrefabPath);
                foreach (var renderer in normalized.GetComponentsInChildren <SkinnedMeshRenderer>())
                {
                    renderer.sharedMesh.name = renderer.name;
                    renderer.sharedMesh      = Duplicator.CreateObjectToFolder(renderer.sharedMesh, temporaryPrefabPath);
                }

                // VRM設定2
                VRChatToVRMConverter.SetFirstPersonRenderers(normalized);

                // 表情の設定
                VRChatExpressionsReplacer.SetExpressions(normalized, presetShapeKeyNameWeightPairsPairs);

                var prefab = PrefabUtility
                             .SaveAsPrefabAssetAndConnect(normalized, temporaryPrefabPath, InteractionMode.AutomatedAction);

                // エクスポート
                AssetDatabase.SaveAssets();
                File.WriteAllBytes(
                    outputPath,
                    VRMEditorExporter.Export(prefab, meta: null, ScriptableObject.CreateInstance <VRMExportSettings>())
                    );
            }
            catch (Exception exception)
            {
                ErrorDialog.Open(exception);
                throw;
            }
            finally
            {
                if (clone != null)
                {
                    Object.DestroyImmediate(clone);
                }
                if (normalized != null)
                {
                    Object.DestroyImmediate(normalized);
                }
                AssetDatabase.DeleteAsset("Assets/VRMConverterTemporary");
            }
        }