From 4cee6d967600bc3861ca61b17386e481de479ee2 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 16:08:57 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/TabBoneMeshRemover.cs | 68 +++++++------------ 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index c0dc39b59..73435718f 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -9,7 +9,7 @@ namespace UniGLTF.MeshUtility { public static class TabBoneMeshRemover { - public static bool OnGUI(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) + public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -18,7 +18,7 @@ namespace UniGLTF.MeshUtility GUILayout.FlexibleSpace(); if (GUILayout.Button("Process", GUILayout.MinWidth(100))) { - _isInvokeSuccess = TabBoneMeshRemover.Execute(_exportTarget, _cSkinnedMesh, _eraseBones); + _isInvokeSuccess = TabBoneMeshRemover.Execute(root, smr, eraseBones); } GUILayout.EndHorizontal(); } @@ -26,38 +26,37 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - public static bool Execute(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) + private static bool Execute(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) { - if (_exportTarget == null) + if (root == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); return false; } - var go = _exportTarget; - if (_cSkinnedMesh == null) + if (smr == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok"); return false; } - BoneMeshRemove(go, _cSkinnedMesh, _eraseBones); - return true; - } + var bones = smr.bones; + + var meshNode = new GameObject(BoneMeshEraserWizard.BONE_MESH_ERASER_NAME); + meshNode.transform.SetParent(root.transform, false); + + var erased = meshNode.AddComponent(); + erased.sharedMesh = BoneMeshEraser.CreateErasedMesh(smr.sharedMesh, eraseBones + .Where(x => x.Erase) + .Select(x => Array.IndexOf(bones, x.Bone)) + .ToArray()); + erased.sharedMaterials = smr.sharedMaterials; + erased.bones = smr.bones; - private static void BoneMeshRemove(GameObject go, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) - { - var renderer = Remove(go, _cSkinnedMesh, _eraseBones); - var outputObject = GameObject.Instantiate(go); - outputObject.name = outputObject.name + "_bone_mesh_erase"; - if (renderer == null) - { - return; - } // save mesh to Assets - var assetPath = string.Format("{0}{1}", go.name, MeshUtility.ASSET_SUFFIX); - var prefab = MeshUtility.GetPrefab(go); + var assetPath = string.Format("{0}{1}", root.name, MeshUtility.ASSET_SUFFIX); + var prefab = MeshUtility.GetPrefab(root); if (prefab != null) { var prefabPath = AssetDatabase.GetAssetPath(prefab); @@ -67,45 +66,30 @@ namespace UniGLTF.MeshUtility MeshUtility.ASSET_SUFFIX ); } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(renderer.sharedMesh, assetPath); + AssetDatabase.CreateAsset(erased.sharedMesh, assetPath); // destroy BoneMeshEraser in the source - foreach (var skinnedMesh in go.GetComponentsInChildren()) + foreach (var skinnedMesh in root.GetComponentsInChildren()) { if (skinnedMesh.gameObject.name == BoneMeshEraserWizard.BONE_MESH_ERASER_NAME) { GameObject.DestroyImmediate(skinnedMesh.gameObject); } } + // destroy the original mesh in the copied GameObject + var outputObject = GameObject.Instantiate(root); + outputObject.name = outputObject.name + "_bone_mesh_erase"; foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) { - if (skinnedMesh.sharedMesh == _cSkinnedMesh.sharedMesh) + if (skinnedMesh.sharedMesh == smr.sharedMesh) { GameObject.DestroyImmediate(skinnedMesh); } } - } - private static SkinnedMeshRenderer Remove(GameObject go, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) - { - var bones = _cSkinnedMesh.bones; - var eraseBones = _eraseBones - .Where(x => x.Erase) - .Select(x => Array.IndexOf(bones, x.Bone)) - .ToArray(); - - var meshNode = new GameObject(BoneMeshEraserWizard.BONE_MESH_ERASER_NAME); - meshNode.transform.SetParent(go.transform, false); - - var erased = meshNode.AddComponent(); - erased.sharedMesh = BoneMeshEraser.CreateErasedMesh(_cSkinnedMesh.sharedMesh, eraseBones); - erased.sharedMaterials = _cSkinnedMesh.sharedMaterials; - erased.bones = _cSkinnedMesh.bones; - - return erased; + return true; } } } \ No newline at end of file From 89b9fe4fed50e50f9db84779db6438cca488f93f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 16:09:18 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=E8=AA=A4=E5=AD=97=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E3=80=82=E4=B8=8D=E8=A6=81=E3=81=AA=E3=82=B3=E3=83=A1=E3=83=B3?= =?UTF-8?q?=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs | 2 +- Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs index 3fe4dcfdb..b30c05c8e 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs @@ -20,7 +20,7 @@ namespace UniGLTF.MeshUtility ")] MESH_SEPARATOR, - [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュをを統合します。BlendShape の有無で2つ作成されます。 + [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュを統合します。BlendShape の有無で2つ作成されます。 * Asset: Assets/MeshIntegrated.mesh が作成されます(上書きされるので注意してください)。 * Scene: コピーされたヒエラルキーでは、統合された Mesh は除去されます。新しく MeshIntegrator ノードが追加されます。 diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs index fd45864d8..6a930654c 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs @@ -267,7 +267,6 @@ namespace UniGLTF.MeshUtility /// /// from dialog /// - /// public static void IntegrateSelected(GameObject go) { var meshWithMaterials = StaticMeshIntegrator.Integrate(go.transform); From 05f41f2aac35dee74a9ff28e52350ed7b6e033ae Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 16:10:20 +0900 Subject: [PATCH 3/8] fix var name --- .../Editor/MeshUtility/TabMeshIntegrator.cs | 19 +++++++++---------- .../Editor/MeshUtility/TabMeshSeparator.cs | 13 ++++++------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 839d425a8..5f2ee0343 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -6,7 +6,7 @@ namespace UniGLTF.MeshUtility { public static class TabMeshIntegrator { - public static bool OnGUI(GameObject _exportTarget) + public static bool OnGUI(GameObject root) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -15,7 +15,7 @@ namespace UniGLTF.MeshUtility GUILayout.FlexibleSpace(); if (GUILayout.Button("Process", GUILayout.MinWidth(100))) { - _isInvokeSuccess = TabMeshIntegrator.Execute(_exportTarget); + _isInvokeSuccess = TabMeshIntegrator.Execute(root); } GUILayout.EndHorizontal(); } @@ -24,9 +24,9 @@ namespace UniGLTF.MeshUtility } static string VRM_META = "VRMMeta"; - static bool HasVrm(GameObject go) + static bool HasVrm(GameObject root) { - var allComponents = go.GetComponents(typeof(Component)); + var allComponents = root.GetComponents(typeof(Component)); foreach (var component in allComponents) { if (component == null) continue; @@ -39,28 +39,27 @@ namespace UniGLTF.MeshUtility return false; } - static bool Execute(GameObject _exportTarget) + static bool Execute(GameObject root) { - if (_exportTarget == null) + if (root == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); return false; } - var go = _exportTarget; - if (HasVrm(go)) + if (HasVrm(root)) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); return false; } - if (go.GetComponentsInChildren().Length == 0 && go.GetComponentsInChildren().Length == 0) + if (root.GetComponentsInChildren().Length == 0 && root.GetComponentsInChildren().Length == 0) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok"); return false; } - MeshUtility.MeshIntegrator(go); + MeshUtility.MeshIntegrator(root); return true; } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs index bef557520..51017dfcd 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs @@ -9,7 +9,7 @@ namespace UniGLTF.MeshUtility /// public static class TabMeshSeparator { - public static bool OnGUI(GameObject _exportTarget) + public static bool OnGUI(GameObject root) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -18,7 +18,7 @@ namespace UniGLTF.MeshUtility GUILayout.FlexibleSpace(); if (GUILayout.Button("Process", GUILayout.MinWidth(100))) { - _isInvokeSuccess = TabMeshSeparator.Execute(_exportTarget); + _isInvokeSuccess = TabMeshSeparator.Execute(root); } GUILayout.EndHorizontal(); } @@ -26,23 +26,22 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - static bool Execute(GameObject _exportTarget) + static bool Execute(GameObject root) { - if (_exportTarget == null) + if (root == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); return false; } - var go = _exportTarget; - if (go.GetComponentsInChildren().Length == 0) + if (root.GetComponentsInChildren().Length == 0) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok"); return false; } // copy - var outputObject = GameObject.Instantiate(go); + var outputObject = GameObject.Instantiate(root); outputObject.name = outputObject.name + "_mesh_separation"; // 改変と asset の作成 From 95e6c6d65cc7e6b0258fb3d39a276ab4f4e3d1c1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 16:11:55 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/MeshProcessDialog.cs | 7 --- .../MeshUtility/TabStaticMeshIntegrator.cs | 45 ------------------- .../TabStaticMeshIntegrator.cs.meta | 11 ----- 3 files changed, 63 deletions(-) delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index d7c352b6c..4aeaf41f8 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -13,7 +13,6 @@ namespace UniGLTF.MeshUtility { MeshSeparator, MeshIntegrator, - // StaticMeshIntegrator, BoneMeshEraser, } private Tabs _tab; @@ -89,12 +88,6 @@ namespace UniGLTF.MeshUtility processed = TabMeshIntegrator.OnGUI(_exportTarget); break; - // MeshIntegrator と機能が重複しているのと正常に動作しなかった - // case Tabs.StaticMeshIntegrator: - // EditorGUILayout.HelpBox(MeshProcessingMessages.STATIC_MESH_INTEGRATOR.Msg(), MessageType.Info); - // processed = TabStaticMeshIntegrator.OnGUI(_exportTarget); - // break; - case Tabs.BoneMeshEraser: EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); if (_boneMeshEraserEditor) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs deleted file mode 100644 index 9cdfd3e3f..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs +++ /dev/null @@ -1,45 +0,0 @@ -using UniGLTF.M17N; -using UnityEditor; -using UnityEngine; - -namespace UniGLTF.MeshUtility -{ - public static class TabStaticMeshIntegrator - { - public static bool OnGUI(GameObject _exportTarget) - { - var _isInvokeSuccess = false; - GUILayout.BeginVertical(); - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Process", GUILayout.MinWidth(100))) - { - _isInvokeSuccess = TabStaticMeshIntegrator.Execute(_exportTarget); - } - GUILayout.EndHorizontal(); - } - GUILayout.EndVertical(); - return _isInvokeSuccess; - } - - static bool Execute(GameObject _exportTarget) - { - if (_exportTarget == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); - return false; - } - var go = _exportTarget; - - if (go.GetComponentsInChildren().Length == 0) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_STATIC_MESH.Msg(), "ok"); - return false; - } - - MeshUtility.IntegrateSelected(go); - return true; - } - } -} diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta deleted file mode 100644 index 4c0e30384..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9701e1f6aaed8d14283243a7a50be2df -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From 1f7cdc9e9b247aa6b4507f165783291d6e0d3bff Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 16:53:21 +0900 Subject: [PATCH 5/8] =?UTF-8?q?static=20=E9=96=A2=E6=95=B0=E7=BD=AE?= =?UTF-8?q?=E3=81=8D=E5=A0=B4=20MeshUtility=20=E3=82=92=E5=88=86=E9=85=8D?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MeshUtility/BoneMeshEraserWizard.cs | 11 +- .../Editor/MeshUtility/MeshProcessDialog.cs | 7 +- .../UniGLTF/Editor/MeshUtility/MeshUtility.cs | 418 ------------------ .../Editor/MeshUtility/MeshUtility.cs.meta | 11 - .../Editor/MeshUtility/TabBoneMeshRemover.cs | 17 +- .../Editor/MeshUtility/TabMeshIntegrator.cs | 79 +++- .../Editor/MeshUtility/TabMeshSeparator.cs | 268 ++++++++++- 7 files changed, 373 insertions(+), 438 deletions(-) delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs index a3650f74a..4e0c71201 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs @@ -138,6 +138,15 @@ namespace UniGLTF.MeshUtility return erased; } + public static UnityEngine.Object GetPrefab(GameObject instance) + { +#if UNITY_2018_2_OR_NEWER + return PrefabUtility.GetCorrespondingObjectFromSource(instance); +#else + return PrefabUtility.GetPrefabParent(go); +#endif + } + void Erase() { var go = Selection.activeGameObject; @@ -149,7 +158,7 @@ namespace UniGLTF.MeshUtility // save mesh to Assets var assetPath = string.Format("{0}{1}", go.name, ASSET_SUFFIX); - var prefab = MeshUtility.GetPrefab(go); + var prefab = GetPrefab(go); if (prefab != null) { var prefabPath = AssetDatabase.GetAssetPath(prefab); diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 4aeaf41f8..2183e0180 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -55,6 +55,11 @@ namespace UniGLTF.MeshUtility } } + static bool IsGameObjectSelected() + { + return Selection.activeObject != null && Selection.activeObject is GameObject; + } + private void OnGUI() { _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); @@ -67,7 +72,7 @@ namespace UniGLTF.MeshUtility EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); EditorGUILayout.EndHorizontal(); - if (_exportTarget == null && MeshUtility.IsGameObjectSelected()) + if (_exportTarget == null && IsGameObjectSelected()) { _exportTarget = Selection.activeObject as GameObject; } diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs deleted file mode 100644 index 6a930654c..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs +++ /dev/null @@ -1,418 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; -using UnityEditor; - -namespace UniGLTF.MeshUtility -{ - public class MeshUtility - { - public const string ASSET_SUFFIX = ".mesh.asset"; - private static readonly Vector3 ZERO_MOVEMENT = Vector3.zero; - - public static Object GetPrefab(GameObject instance) - { -#if UNITY_2018_2_OR_NEWER - return PrefabUtility.GetCorrespondingObjectFromSource(instance); -#else - return PrefabUtility.GetPrefabParent(go); -#endif - } - - public enum BlendShapeLogic - { - WithBlendShape, - WithoutBlendShape, - } - - /// - /// 対象のヒエラルキーに含まれるすべての SkinnedMeshRenderer に対して、 - /// BlendShape を含む Mesh と 含まない Mesh への分割を実施する。 - /// - /// 各 SkinnedMeshRenderer(smr) は、 - /// - /// smr - mesh(with blendshape) - /// + smr(without) - mesh(without blendshape) - /// - /// のように変化する。 - /// - /// - /// (Mesh 分割前, Mesh BlendShape有り、Mesh BlendShape無し)のリストを返す - public static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go) - { - var list = new List<(Mesh Src, Mesh With, Mesh Without)>(); - var skinnedMeshRenderers = go.GetComponentsInChildren(); - foreach (var skinnedMeshRenderer in skinnedMeshRenderers) - { - if (skinnedMeshRenderer.sharedMesh.blendShapeCount > 0) - { - var (mesh, with, without) = SeparatePolyWithBlendShape(skinnedMeshRenderer); - if (mesh != null) - { - list.Add((mesh, with, without)); - } - } - } - return list; - } - - private static (Mesh mesh, Mesh With, Mesh Without) SeparatePolyWithBlendShape(SkinnedMeshRenderer skinnedMeshRendererInput) - { - var indicesUsedByBlendShape = new Dictionary(); - var mesh = skinnedMeshRendererInput.sharedMesh; - - // retrieve the original BlendShape data - for (int i = 0; i < mesh.blendShapeCount; ++i) - { - var deltaVertices = new Vector3[mesh.vertexCount]; - var deltaNormals = new Vector3[mesh.vertexCount]; - var deltaTangents = new Vector3[mesh.vertexCount]; - mesh.GetBlendShapeFrameVertices(i, 0, deltaVertices, deltaNormals, deltaTangents); - - for (int j = 0; j < deltaVertices.Length; j++) - { - if (!deltaVertices[j].Equals(ZERO_MOVEMENT)) - { - if (!indicesUsedByBlendShape.Values.Contains(j)) - { - indicesUsedByBlendShape.Add(indicesUsedByBlendShape.Count, j); - } - } - } - } - - var subMeshCount = mesh.subMeshCount; - var submeshesWithBlendShape = new Dictionary(); - var submeshesWithoutBlendShape = new Dictionary(); - var vertexIndexWithBlendShape = new Dictionary(); - var vertexCounterWithBlendShape = 0; - var vertexIndexWithoutBlendShape = new Dictionary(); - var vertexCounterWithoutBlendShape = 0; - - // check blendshape's vertex index from submesh - for (int i = 0; i < subMeshCount; i++) - { - var triangle = mesh.GetTriangles(i); - var submeshWithBlendShape = new List(); - var submeshWithoutBlendShape = new List(); - - for (int j = 0; j < triangle.Length; j += 3) - { - if (indicesUsedByBlendShape.Values.Contains(triangle[j]) || - indicesUsedByBlendShape.Values.Contains(triangle[j + 1]) || - indicesUsedByBlendShape.Values.Contains(triangle[j + 2])) - { - BuildNewTriangleList(vertexIndexWithBlendShape, triangle, j, submeshWithBlendShape, ref vertexCounterWithBlendShape); - } - else - { - BuildNewTriangleList(vertexIndexWithoutBlendShape, triangle, j, submeshWithoutBlendShape, ref vertexCounterWithoutBlendShape); - } - } - if (submeshWithBlendShape.Count > 0) - submeshesWithBlendShape.Add(i, submeshWithBlendShape.ToArray()); - if (submeshWithoutBlendShape.Count > 0) - submeshesWithoutBlendShape.Add(i, submeshWithoutBlendShape.ToArray()); ; - } - - // check if any BlendShape exists - if (submeshesWithoutBlendShape.Count > 0) - { - // put the mesh without BlendShape in a new SkinnedMeshRenderer - var srcGameObject = skinnedMeshRendererInput.gameObject; - var srcTransform = skinnedMeshRendererInput.transform.parent; - var targetObjectForMeshWithoutBS = GameObject.Instantiate(srcGameObject); - targetObjectForMeshWithoutBS.name = srcGameObject.name + "_WithoutBlendShape"; - targetObjectForMeshWithoutBS.transform.SetParent(srcTransform); - var skinnedMeshRendererWithoutBS = targetObjectForMeshWithoutBS.GetComponent(); - - // build meshes with/without BlendShape - var with = BuildNewMesh(skinnedMeshRendererInput, vertexIndexWithBlendShape, submeshesWithBlendShape, BlendShapeLogic.WithBlendShape); - var without = BuildNewMesh(skinnedMeshRendererWithoutBS, vertexIndexWithoutBlendShape, submeshesWithoutBlendShape, BlendShapeLogic.WithoutBlendShape); - return (mesh, with, without); - } - else - { - return default; - } - } - - private static void BuildNewTriangleList(Dictionary newVerticesListLookUp, int[] triangleList, int index, - List newTriangleList, ref int vertexCounter) - { - // build new vertex list and triangle list - // vertex 1 - if (!newVerticesListLookUp.Keys.Contains(triangleList[index])) - { - newVerticesListLookUp.Add(triangleList[index], vertexCounter); - newTriangleList.Add(vertexCounter); - vertexCounter++; - } - else - { - var newVertexIndex = newVerticesListLookUp[triangleList[index]]; - newTriangleList.Add(newVertexIndex); - } - // vertex 2 - if (!newVerticesListLookUp.Keys.Contains(triangleList[index + 1])) - { - newVerticesListLookUp.Add(triangleList[index + 1], vertexCounter); - newTriangleList.Add(vertexCounter); - vertexCounter++; - } - else - { - var newVertexIndex = newVerticesListLookUp[triangleList[index + 1]]; - newTriangleList.Add(newVertexIndex); - } - // vertex 3 - if (!newVerticesListLookUp.Keys.Contains(triangleList[index + 2])) - { - newVerticesListLookUp.Add(triangleList[index + 2], vertexCounter); - newTriangleList.Add(vertexCounter); - vertexCounter++; - } - else - { - var newVertexIndex = newVerticesListLookUp[triangleList[index + 2]]; - newTriangleList.Add(newVertexIndex); - } - } - - private static Mesh BuildNewMesh(SkinnedMeshRenderer skinnedMeshRenderer, Dictionary newIndexLookUpDict, - Dictionary subMeshes, BlendShapeLogic blendShapeLabel) - { - // get original mesh data - var materialList = new List(); - skinnedMeshRenderer.GetSharedMaterials(materialList); - var mesh = skinnedMeshRenderer.sharedMesh; - var meshVertices = mesh.vertices; - var meshNormals = mesh.normals; - var meshTangents = mesh.tangents; - var meshColors = mesh.colors; - var meshBoneWeights = mesh.boneWeights; - var meshUVs = mesh.uv; - - // build new mesh - var materialListNew = new List(); - var newMesh = new Mesh(); - - if (mesh.vertexCount > ushort.MaxValue) - { -#if UNITY_2017_3_OR_NEWER - Debug.LogFormat("exceed 65535 vertices: {0}", mesh.vertexCount); - newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; -#else - throw new NotImplementedException(String.Format("exceed 65535 vertices: {0}", integrator.Positions.Count.ToString())); -#endif - } - - var newDataLength = newIndexLookUpDict.Count; - var newIndexLookUp = newIndexLookUpDict.Keys.ToArray(); - - newMesh.vertices = newIndexLookUp.Select(x => meshVertices[x]).ToArray(); - if (meshNormals.Length > 0) newMesh.normals = newIndexLookUp.Select(x => meshNormals[x]).ToArray(); - if (meshTangents.Length > 0) newMesh.tangents = newIndexLookUp.Select(x => meshTangents[x]).ToArray(); - if (meshColors.Length > 0) newMesh.colors = newIndexLookUp.Select(x => meshColors[x]).ToArray(); - if (meshBoneWeights.Length > 0) newMesh.boneWeights = newIndexLookUp.Select(x => meshBoneWeights[x]).ToArray(); - if (meshUVs.Length > 0) newMesh.uv = newIndexLookUp.Select(x => meshUVs[x]).ToArray(); - newMesh.bindposes = mesh.bindposes; - - // add BlendShape data - if (blendShapeLabel == BlendShapeLogic.WithBlendShape) - { - for (int i = 0; i < mesh.blendShapeCount; i++) - { - // get original BlendShape data - var srcVertices = new Vector3[mesh.vertexCount]; - var srcNormals = new Vector3[mesh.vertexCount]; - var srcTangents = new Vector3[mesh.vertexCount]; - mesh.GetBlendShapeFrameVertices(i, 0, srcVertices, srcNormals, srcTangents); - - // declare the size for the destination array - var dstVertices = new Vector3[newDataLength]; - var dstNormals = new Vector3[newDataLength]; - var dstTangents = new Vector3[newDataLength]; - - dstVertices = newIndexLookUp.Select(x => srcVertices[x]).ToArray(); - dstNormals = newIndexLookUp.Select(x => srcNormals[x]).ToArray(); - dstTangents = newIndexLookUp.Select(x => srcTangents[x]).ToArray(); - newMesh.AddBlendShapeFrame(mesh.GetBlendShapeName(i), mesh.GetBlendShapeFrameWeight(i, 0), - dstVertices, dstNormals, dstTangents); - } - } - - newMesh.subMeshCount = subMeshes.Count; - var cosMaterialIndex = subMeshes.Keys.ToArray(); - - // build material list - for (int i = 0; i < subMeshes.Count; i++) - { - newMesh.SetTriangles(subMeshes[cosMaterialIndex[i]], i); - materialListNew.Add(materialList[cosMaterialIndex[i]]); - } - skinnedMeshRenderer.sharedMaterials = materialListNew.ToArray(); - skinnedMeshRenderer.sharedMesh = newMesh; - - return newMesh; - } - -#if UNITY_EDITOR - public static bool IsGameObjectSelected() - { - return Selection.activeObject != null && Selection.activeObject is GameObject; - } - - /// - /// from dialog - /// - public static void IntegrateSelected(GameObject go) - { - var meshWithMaterials = StaticMeshIntegrator.Integrate(go.transform); - - // save as asset - var assetPath = ""; -#if UNITY_2018_2_OR_NEWER - var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go); -#else - var prefab = PrefabUtility.GetPrefabParent(go); -#endif - if (prefab != null) - { - var prefabPath = AssetDatabase.GetAssetPath(prefab); - assetPath = string.Format("{0}/{1}_{2}{3}", - Path.GetDirectoryName(prefabPath), - Path.GetFileNameWithoutExtension(prefabPath), - go.name, - ASSET_SUFFIX - ); - } - else - { - var path = EditorUtility.SaveFilePanel( - "Save mesh", - "Assets", - go.name + ".asset", - "asset"); - if (string.IsNullOrEmpty(path)) - { - return; - } - assetPath = UnityPath.FromFullpath(path).Value; - } - - assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(meshWithMaterials.Mesh, assetPath); - - // add component - var meshObject = new GameObject(go.name + ".static_meshes_integrated"); - if (go.transform.parent != null) - { - meshObject.transform.SetParent(go.transform.parent, false); - } - meshObject.transform.localPosition = go.transform.localPosition; - meshObject.transform.localRotation = go.transform.localRotation; - meshObject.transform.localScale = go.transform.localScale; - - var filter = meshObject.AddComponent(); - filter.sharedMesh = meshWithMaterials.Mesh; - var renderer = meshObject.AddComponent(); - renderer.sharedMaterials = meshWithMaterials.Materials; - } -#endif - - /// - /// from dialog - /// - /// - public static void MeshIntegrator(GameObject go) - { - MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: true); - MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: false); - - var outputObject = GameObject.Instantiate(go); - outputObject.name = outputObject.name + "_mesh_integration"; - var skinnedMeshes = outputObject.GetComponentsInChildren(); - var normalMeshes = outputObject.GetComponentsInChildren(); - - // destroy integrated meshes in the source - // ? - foreach (var skinnedMesh in go.GetComponentsInChildren()) - { - if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - } - foreach (var skinnedMesh in skinnedMeshes) - { - // destroy original meshes in the copied GameObject - if (!(skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)) - { - GameObject.DestroyImmediate(skinnedMesh); - } - // check if the integrated mesh is empty - else if (skinnedMesh.sharedMesh.subMeshCount == 0) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - // save mesh data - else if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - SaveMeshData(skinnedMesh.sharedMesh); - } - } - foreach (var normalMesh in normalMeshes) - { - if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) - { - if (normalMesh.gameObject.GetComponent()) - { - GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); - } - GameObject.DestroyImmediate(normalMesh); - } - } - } - - public static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel) - { - // save mesh as asset - var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - Debug.Log(assetPath); - if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) - { - var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); - assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX); - } - else - { - assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX); - } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(newMesh, assetPath); - } - - private static void SaveMeshData(Mesh mesh) - { - var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - Debug.Log(assetPath); - if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) - { - var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); - assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - else - { - assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(mesh, assetPath); - } - } -} \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs.meta deleted file mode 100644 index 2fb0aadd1..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c1bbe850b95e44740bbbb44064e17d25 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index 73435718f..812fd8a52 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -9,6 +9,8 @@ namespace UniGLTF.MeshUtility { public static class TabBoneMeshRemover { + const string ASSET_SUFFIX = ".mesh.asset"; + public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) { var _isInvokeSuccess = false; @@ -55,15 +57,15 @@ namespace UniGLTF.MeshUtility // save mesh to Assets - var assetPath = string.Format("{0}{1}", root.name, MeshUtility.ASSET_SUFFIX); - var prefab = MeshUtility.GetPrefab(root); + var assetPath = string.Format("{0}{1}", root.name, ASSET_SUFFIX); + var prefab = GetPrefab(root); if (prefab != null) { var prefabPath = AssetDatabase.GetAssetPath(prefab); assetPath = string.Format("{0}/{1}{2}", Path.GetDirectoryName(prefabPath), Path.GetFileNameWithoutExtension(prefabPath), - MeshUtility.ASSET_SUFFIX + ASSET_SUFFIX ); } Debug.LogFormat("CreateAsset: {0}", assetPath); @@ -91,5 +93,14 @@ namespace UniGLTF.MeshUtility return true; } + + public static UnityEngine.Object GetPrefab(GameObject instance) + { +#if UNITY_2018_2_OR_NEWER + return PrefabUtility.GetCorrespondingObjectFromSource(instance); +#else + return PrefabUtility.GetPrefabParent(go); +#endif + } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 5f2ee0343..758d77a8b 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -1,3 +1,4 @@ +using System.IO; using UniGLTF.M17N; using UnityEditor; using UnityEngine; @@ -6,6 +7,8 @@ namespace UniGLTF.MeshUtility { public static class TabMeshIntegrator { + const string ASSET_SUFFIX = ".mesh.asset"; + public static bool OnGUI(GameObject root) { var _isInvokeSuccess = false; @@ -59,8 +62,82 @@ namespace UniGLTF.MeshUtility return false; } - MeshUtility.MeshIntegrator(root); + MeshIntegrator(root); return true; } + + /// + /// from dialog + /// + /// + public static void MeshIntegrator(GameObject go) + { + MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: true); + MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: false); + + var outputObject = GameObject.Instantiate(go); + outputObject.name = outputObject.name + "_mesh_integration"; + var skinnedMeshes = outputObject.GetComponentsInChildren(); + var normalMeshes = outputObject.GetComponentsInChildren(); + + // destroy integrated meshes in the source + // ? + foreach (var skinnedMesh in go.GetComponentsInChildren()) + { + if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || + skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) + { + GameObject.DestroyImmediate(skinnedMesh.gameObject); + } + } + foreach (var skinnedMesh in skinnedMeshes) + { + // destroy original meshes in the copied GameObject + if (!(skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || + skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)) + { + GameObject.DestroyImmediate(skinnedMesh); + } + // check if the integrated mesh is empty + else if (skinnedMesh.sharedMesh.subMeshCount == 0) + { + GameObject.DestroyImmediate(skinnedMesh.gameObject); + } + // save mesh data + else if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || + skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) + { + SaveMeshData(skinnedMesh.sharedMesh); + } + } + foreach (var normalMesh in normalMeshes) + { + if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) + { + if (normalMesh.gameObject.GetComponent()) + { + GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); + } + GameObject.DestroyImmediate(normalMesh); + } + } + } + + static void SaveMeshData(Mesh mesh) + { + var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + Debug.Log(assetPath); + if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) + { + var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); + assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + else + { + assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(mesh, assetPath); + } } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs index 51017dfcd..6e8caf398 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; using UniGLTF.M17N; using UnityEditor; using UnityEngine; @@ -9,6 +12,15 @@ namespace UniGLTF.MeshUtility /// public static class TabMeshSeparator { + private static readonly Vector3 ZERO_MOVEMENT = Vector3.zero; + const string ASSET_SUFFIX = ".mesh.asset"; + + enum BlendShapeLogic + { + WithBlendShape, + WithoutBlendShape, + } + public static bool OnGUI(GameObject root) { var _isInvokeSuccess = false; @@ -45,14 +57,264 @@ namespace UniGLTF.MeshUtility outputObject.name = outputObject.name + "_mesh_separation"; // 改変と asset の作成 - var list = MeshUtility.SeparationProcessing(outputObject); + var list = SeparationProcessing(outputObject); foreach (var (src, with, without) in list) { // asset の永続化 - MeshUtility.SaveMesh(src, with, MeshUtility.BlendShapeLogic.WithBlendShape); - MeshUtility.SaveMesh(src, without, MeshUtility.BlendShapeLogic.WithoutBlendShape); + SaveMesh(src, with, BlendShapeLogic.WithBlendShape); + SaveMesh(src, without, BlendShapeLogic.WithoutBlendShape); } return true; } + + static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel) + { + // save mesh as asset + var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + Debug.Log(assetPath); + if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) + { + var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); + assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX); + } + else + { + assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name) + "_" + blendShapeLabel.ToString(), ASSET_SUFFIX); + } + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(newMesh, assetPath); + } + + /// + /// 対象のヒエラルキーに含まれるすべての SkinnedMeshRenderer に対して、 + /// BlendShape を含む Mesh と 含まない Mesh への分割を実施する。 + /// + /// 各 SkinnedMeshRenderer(smr) は、 + /// + /// smr - mesh(with blendshape) + /// + smr(without) - mesh(without blendshape) + /// + /// のように変化する。 + /// + /// + /// (Mesh 分割前, Mesh BlendShape有り、Mesh BlendShape無し)のリストを返す + public static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go) + { + var list = new List<(Mesh Src, Mesh With, Mesh Without)>(); + var skinnedMeshRenderers = go.GetComponentsInChildren(); + foreach (var skinnedMeshRenderer in skinnedMeshRenderers) + { + if (skinnedMeshRenderer.sharedMesh.blendShapeCount > 0) + { + var (mesh, with, without) = SeparatePolyWithBlendShape(skinnedMeshRenderer); + if (mesh != null) + { + list.Add((mesh, with, without)); + } + } + } + return list; + } + + private static (Mesh mesh, Mesh With, Mesh Without) SeparatePolyWithBlendShape(SkinnedMeshRenderer skinnedMeshRendererInput) + { + var indicesUsedByBlendShape = new Dictionary(); + var mesh = skinnedMeshRendererInput.sharedMesh; + + // retrieve the original BlendShape data + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + var deltaVertices = new Vector3[mesh.vertexCount]; + var deltaNormals = new Vector3[mesh.vertexCount]; + var deltaTangents = new Vector3[mesh.vertexCount]; + mesh.GetBlendShapeFrameVertices(i, 0, deltaVertices, deltaNormals, deltaTangents); + + for (int j = 0; j < deltaVertices.Length; j++) + { + if (!deltaVertices[j].Equals(ZERO_MOVEMENT)) + { + if (!indicesUsedByBlendShape.Values.Contains(j)) + { + indicesUsedByBlendShape.Add(indicesUsedByBlendShape.Count, j); + } + } + } + } + + var subMeshCount = mesh.subMeshCount; + var submeshesWithBlendShape = new Dictionary(); + var submeshesWithoutBlendShape = new Dictionary(); + var vertexIndexWithBlendShape = new Dictionary(); + var vertexCounterWithBlendShape = 0; + var vertexIndexWithoutBlendShape = new Dictionary(); + var vertexCounterWithoutBlendShape = 0; + + // check blendshape's vertex index from submesh + for (int i = 0; i < subMeshCount; i++) + { + var triangle = mesh.GetTriangles(i); + var submeshWithBlendShape = new List(); + var submeshWithoutBlendShape = new List(); + + for (int j = 0; j < triangle.Length; j += 3) + { + if (indicesUsedByBlendShape.Values.Contains(triangle[j]) || + indicesUsedByBlendShape.Values.Contains(triangle[j + 1]) || + indicesUsedByBlendShape.Values.Contains(triangle[j + 2])) + { + BuildNewTriangleList(vertexIndexWithBlendShape, triangle, j, submeshWithBlendShape, ref vertexCounterWithBlendShape); + } + else + { + BuildNewTriangleList(vertexIndexWithoutBlendShape, triangle, j, submeshWithoutBlendShape, ref vertexCounterWithoutBlendShape); + } + } + if (submeshWithBlendShape.Count > 0) + submeshesWithBlendShape.Add(i, submeshWithBlendShape.ToArray()); + if (submeshWithoutBlendShape.Count > 0) + submeshesWithoutBlendShape.Add(i, submeshWithoutBlendShape.ToArray()); ; + } + + // check if any BlendShape exists + if (submeshesWithoutBlendShape.Count > 0) + { + // put the mesh without BlendShape in a new SkinnedMeshRenderer + var srcGameObject = skinnedMeshRendererInput.gameObject; + var srcTransform = skinnedMeshRendererInput.transform.parent; + var targetObjectForMeshWithoutBS = GameObject.Instantiate(srcGameObject); + targetObjectForMeshWithoutBS.name = srcGameObject.name + "_WithoutBlendShape"; + targetObjectForMeshWithoutBS.transform.SetParent(srcTransform); + var skinnedMeshRendererWithoutBS = targetObjectForMeshWithoutBS.GetComponent(); + + // build meshes with/without BlendShape + var with = BuildNewMesh(skinnedMeshRendererInput, vertexIndexWithBlendShape, submeshesWithBlendShape, BlendShapeLogic.WithBlendShape); + var without = BuildNewMesh(skinnedMeshRendererWithoutBS, vertexIndexWithoutBlendShape, submeshesWithoutBlendShape, BlendShapeLogic.WithoutBlendShape); + return (mesh, with, without); + } + else + { + return default; + } + } + + private static void BuildNewTriangleList(Dictionary newVerticesListLookUp, int[] triangleList, int index, + List newTriangleList, ref int vertexCounter) + { + // build new vertex list and triangle list + // vertex 1 + if (!newVerticesListLookUp.Keys.Contains(triangleList[index])) + { + newVerticesListLookUp.Add(triangleList[index], vertexCounter); + newTriangleList.Add(vertexCounter); + vertexCounter++; + } + else + { + var newVertexIndex = newVerticesListLookUp[triangleList[index]]; + newTriangleList.Add(newVertexIndex); + } + // vertex 2 + if (!newVerticesListLookUp.Keys.Contains(triangleList[index + 1])) + { + newVerticesListLookUp.Add(triangleList[index + 1], vertexCounter); + newTriangleList.Add(vertexCounter); + vertexCounter++; + } + else + { + var newVertexIndex = newVerticesListLookUp[triangleList[index + 1]]; + newTriangleList.Add(newVertexIndex); + } + // vertex 3 + if (!newVerticesListLookUp.Keys.Contains(triangleList[index + 2])) + { + newVerticesListLookUp.Add(triangleList[index + 2], vertexCounter); + newTriangleList.Add(vertexCounter); + vertexCounter++; + } + else + { + var newVertexIndex = newVerticesListLookUp[triangleList[index + 2]]; + newTriangleList.Add(newVertexIndex); + } + } + + private static Mesh BuildNewMesh(SkinnedMeshRenderer skinnedMeshRenderer, Dictionary newIndexLookUpDict, + Dictionary subMeshes, BlendShapeLogic blendShapeLabel) + { + // get original mesh data + var materialList = new List(); + skinnedMeshRenderer.GetSharedMaterials(materialList); + var mesh = skinnedMeshRenderer.sharedMesh; + var meshVertices = mesh.vertices; + var meshNormals = mesh.normals; + var meshTangents = mesh.tangents; + var meshColors = mesh.colors; + var meshBoneWeights = mesh.boneWeights; + var meshUVs = mesh.uv; + + // build new mesh + var materialListNew = new List(); + var newMesh = new Mesh(); + + if (mesh.vertexCount > ushort.MaxValue) + { +#if UNITY_2017_3_OR_NEWER + Debug.LogFormat("exceed 65535 vertices: {0}", mesh.vertexCount); + newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; +#else + throw new NotImplementedException(String.Format("exceed 65535 vertices: {0}", integrator.Positions.Count.ToString())); +#endif + } + + var newDataLength = newIndexLookUpDict.Count; + var newIndexLookUp = newIndexLookUpDict.Keys.ToArray(); + + newMesh.vertices = newIndexLookUp.Select(x => meshVertices[x]).ToArray(); + if (meshNormals.Length > 0) newMesh.normals = newIndexLookUp.Select(x => meshNormals[x]).ToArray(); + if (meshTangents.Length > 0) newMesh.tangents = newIndexLookUp.Select(x => meshTangents[x]).ToArray(); + if (meshColors.Length > 0) newMesh.colors = newIndexLookUp.Select(x => meshColors[x]).ToArray(); + if (meshBoneWeights.Length > 0) newMesh.boneWeights = newIndexLookUp.Select(x => meshBoneWeights[x]).ToArray(); + if (meshUVs.Length > 0) newMesh.uv = newIndexLookUp.Select(x => meshUVs[x]).ToArray(); + newMesh.bindposes = mesh.bindposes; + + // add BlendShape data + if (blendShapeLabel == BlendShapeLogic.WithBlendShape) + { + for (int i = 0; i < mesh.blendShapeCount; i++) + { + // get original BlendShape data + var srcVertices = new Vector3[mesh.vertexCount]; + var srcNormals = new Vector3[mesh.vertexCount]; + var srcTangents = new Vector3[mesh.vertexCount]; + mesh.GetBlendShapeFrameVertices(i, 0, srcVertices, srcNormals, srcTangents); + + // declare the size for the destination array + var dstVertices = new Vector3[newDataLength]; + var dstNormals = new Vector3[newDataLength]; + var dstTangents = new Vector3[newDataLength]; + + dstVertices = newIndexLookUp.Select(x => srcVertices[x]).ToArray(); + dstNormals = newIndexLookUp.Select(x => srcNormals[x]).ToArray(); + dstTangents = newIndexLookUp.Select(x => srcTangents[x]).ToArray(); + newMesh.AddBlendShapeFrame(mesh.GetBlendShapeName(i), mesh.GetBlendShapeFrameWeight(i, 0), + dstVertices, dstNormals, dstTangents); + } + } + + newMesh.subMeshCount = subMeshes.Count; + var cosMaterialIndex = subMeshes.Keys.ToArray(); + + // build material list + for (int i = 0; i < subMeshes.Count; i++) + { + newMesh.SetTriangles(subMeshes[cosMaterialIndex[i]], i); + materialListNew.Add(materialList[cosMaterialIndex[i]]); + } + skinnedMeshRenderer.sharedMaterials = materialListNew.ToArray(); + skinnedMeshRenderer.sharedMesh = newMesh; + + return newMesh; + } } } From 9855686ec3ef7f488d1a51c993ca257dea5bdbcd Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 17:10:44 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/TabMeshIntegrator.cs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 758d77a8b..209437698 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -26,7 +26,7 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - static string VRM_META = "VRMMeta"; + const string VRM_META = "VRMMeta"; static bool HasVrm(GameObject root) { var allComponents = root.GetComponents(typeof(Component)); @@ -62,27 +62,23 @@ namespace UniGLTF.MeshUtility return false; } - MeshIntegrator(root); + MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: true); + MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: false); + + CopyAndSaveAssetEtc(root); + return true; } - /// - /// from dialog - /// - /// - public static void MeshIntegrator(GameObject go) + static void CopyAndSaveAssetEtc(GameObject root) { - MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: true); - MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: false); - - var outputObject = GameObject.Instantiate(go); + // copy hierarchy + var outputObject = GameObject.Instantiate(root); outputObject.name = outputObject.name + "_mesh_integration"; var skinnedMeshes = outputObject.GetComponentsInChildren(); - var normalMeshes = outputObject.GetComponentsInChildren(); // destroy integrated meshes in the source - // ? - foreach (var skinnedMesh in go.GetComponentsInChildren()) + foreach (var skinnedMesh in root.GetComponentsInChildren()) { if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) @@ -110,6 +106,8 @@ namespace UniGLTF.MeshUtility SaveMeshData(skinnedMesh.sharedMesh); } } + + var normalMeshes = outputObject.GetComponentsInChildren(); foreach (var normalMesh in normalMeshes) { if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) From 6c62b188d4322f6308897fc4bb98eba15be9bb4b Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 11 May 2022 18:56:37 +0900 Subject: [PATCH 7/8] =?UTF-8?q?BlendShape=E3=81=AE=E6=9C=89=E7=84=A1?= =?UTF-8?q?=E3=82=92=E5=8C=BA=E5=88=A5=E3=81=97=E3=81=AA=E3=81=84=E3=82=AA?= =?UTF-8?q?=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/MeshesIntegrated.mesh.asset | 507 ++++++++++++++++++ Assets/MeshesIntegrated.mesh.asset.meta | 8 + .../Editor/MeshUtility/BoneMeshEraserGUI.cs | 19 - .../Editor/MeshUtility/MeshProcessDialog.cs | 25 +- .../MeshUtility/MeshProcessDialogEditor.cs | 36 ++ ...s.meta => MeshProcessDialogEditor.cs.meta} | 2 +- .../MeshUtility/MeshProcessingMessages.cs | 13 +- .../Editor/MeshUtility/TabMeshIntegrator.cs | 17 +- Assets/UniGLTF/Editor/MeshUtility/Tabs.cs | 9 + .../UniGLTF/Editor/MeshUtility/Tabs.cs.meta | 11 + .../MeshUtility/MeshEnumerateOption.cs | 9 + .../MeshUtility/MeshEnumerateOption.cs.meta | 11 + .../Runtime/MeshUtility/MeshIntegrator.cs | 40 +- .../MeshUtility/MeshIntegratorUtility.cs | 115 ++-- .../MeshIntegratorWizard.cs | 2 +- .../VRMMeshIntegratorUtility.cs | 4 +- 16 files changed, 742 insertions(+), 86 deletions(-) create mode 100644 Assets/MeshesIntegrated.mesh.asset create mode 100644 Assets/MeshesIntegrated.mesh.asset.meta delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs rename Assets/UniGLTF/Editor/MeshUtility/{BoneMeshEraserGUI.cs.meta => MeshProcessDialogEditor.cs.meta} (83%) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/Tabs.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta create mode 100644 Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs create mode 100644 Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs.meta diff --git a/Assets/MeshesIntegrated.mesh.asset b/Assets/MeshesIntegrated.mesh.asset new file mode 100644 index 000000000..512a17b1f --- /dev/null +++ b/Assets/MeshesIntegrated.mesh.asset @@ -0,0 +1,507 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!43 &4300000 +Mesh: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: MeshesIntegrated.mesh + serializedVersion: 10 + m_SubMeshes: + - serializedVersion: 2 + firstByte: 0 + indexCount: 768 + topology: 0 + baseVertex: 0 + firstVertex: 0 + vertexCount: 453 + localAABB: + m_Center: {x: 0.00000020861626, y: 0.7249603, z: 0.032029606} + m_Extent: {x: 0.58946085, y: 0.7249602, z: 0.1629476} + m_Shapes: + vertices: [] + shapes: [] + channels: [] + fullWeights: [] + m_BindPose: + - e00: 0.99998313 + e01: -0.0058136694 + e02: 0.00044683862 + e03: 0.003988234 + e10: 0.005830814 + e11: 0.99710566 + e12: -0.0758053 + e13: -0.6840148 + e20: -0.000004838265 + e21: 0.07580492 + e22: 0.99714476 + e23: -0.0520032 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 1.0000001 + e01: -0.00000041014468 + e02: 0.000022655031 + e03: 0.0000006004789 + e10: 0.00000009841655 + e11: 0.9999053 + e12: 0.013758672 + e13: -0.8567405 + e20: -0.00002265803 + e21: -0.013758366 + e22: 0.9999275 + e23: 0.02479167 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 1.0000001 + e01: -0.000000010809315 + e02: -0.0000027871315 + e03: -0.00000025579496 + e10: 0.0000005673888 + e11: 0.979841 + e12: 0.19978324 + e13: -1.0513293 + e20: 0.0000027287256 + e21: -0.19977877 + e22: 0.97986287 + e23: 0.22455975 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 1.0000001 + e01: -0.00000012436698 + e02: 0.0000054645266 + e03: 0.0000000549877 + e10: 0.0000000833747 + e11: 0.99997187 + e12: 0.0075012175 + e13: -1.1264704 + e20: -0.0000054651855 + e21: -0.0075010513 + e22: 0.99999404 + e23: 0.007969917 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -1.0000001 + e01: 0.00000006111686 + e02: 0.0000015178592 + e03: 0.0000000021680735 + e10: 0.00000005557859 + e11: 0.99999356 + e12: -0.0036486278 + e13: -1.1929911 + e20: -0.0000015180384 + e21: -0.0036485475 + e22: -1.0000156 + e23: 0.005353814 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.062392827 + e01: 0.005693435 + e02: 0.99805737 + e03: -0.0016267168 + e10: -0.8915193 + e11: -0.4498517 + e12: -0.053168807 + e13: 0.40415704 + e20: 0.44866517 + e21: -0.89308506 + e22: 0.03314401 + e23: 0.9989868 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.5302006 + e01: -0.0017470117 + e02: 0.8478889 + e03: 0.18342696 + e10: -0.760035 + e11: -0.44421852 + e12: 0.4743695 + e13: 0.20656405 + e20: 0.37581098 + e21: -0.8959166 + e22: -0.23685805 + e23: 0.97321355 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.6314424 + e01: 0.0041904435 + e02: 0.7754282 + e03: 0.22815786 + e10: -0.64927876 + e11: -0.5438431 + e12: 0.53167975 + e13: 0.15465824 + e20: 0.42393002 + e21: -0.83917594 + e22: -0.34069243 + e23: 0.9514504 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.11570896 + e01: 0.09731569 + e02: 0.9885267 + e03: -0.10564935 + e10: 0.86856437 + e11: -0.49271676 + e12: -0.053163834 + e13: 0.45235664 + e20: 0.4818793 + e21: 0.86473095 + e22: -0.14153978 + e23: -0.978427 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.0705073 + e01: -0.78196716 + e02: -0.61933315 + e03: 0.76114917 + e10: 0.76003367 + e11: -0.4442222 + e12: 0.47436923 + e13: 0.20656744 + e20: -0.6460482 + e21: -0.43725756 + e22: 0.6256562 + e23: 0.63359594 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.11137952 + e01: -0.6235332 + e02: -0.7738399 + e03: 0.55021447 + e10: 0.64928055 + e11: -0.5438397 + e12: 0.5316826 + e13: 0.15465552 + e20: -0.7523496 + e21: -0.561645 + e22: 0.3442828 + e23: 0.8090615 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.8304809 + e01: -0.09163624 + e02: -0.549484 + e03: 0.00030874347 + e10: -0.033970688 + e11: -0.97621197 + e12: 0.21415916 + e13: 0.59686774 + e20: -0.55601645 + e21: 0.1965135 + e22: 0.8076394 + e23: -0.15930209 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.99973345 + e01: 0.0000712631 + e02: 0.023235448 + e03: -0.07843342 + e10: -0.0051243966 + e11: -0.97604984 + e12: -0.21750544 + e13: 0.35795337 + e20: 0.022662591 + e21: -0.21755776 + e22: 0.9758227 + e23: 0.022222105 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.9993303 + e01: 0.00000014435534 + e02: 0.036683597 + e03: -0.07836859 + e10: 0.02870476 + e11: -0.622619 + e12: 0.7820302 + e13: 0.05673951 + e20: 0.022839148 + e21: 0.78252804 + e22: 0.62222296 + e23: -0.06347845 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.9940157 + e01: -0.00042184885 + e02: 0.10927121 + e03: 0.07555784 + e10: 0.10925592 + e11: 0.018802257 + e12: -0.9938745 + e13: 0.04058164 + e20: -0.0016352328 + e21: 0.99982494 + e22: 0.018736433 + e23: -0.022736017 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.9946902 + e01: -0.012200378 + e02: 0.10219161 + e03: 0.0750665 + e10: 0.03397443 + e11: -0.97620946 + e12: 0.21415551 + e13: 0.59686655 + e20: 0.09714545 + e21: 0.2164853 + e22: 0.9714627 + e23: -0.14050381 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.99817085 + e01: 0.00810431 + e02: -0.059908763 + e03: 0.07754238 + e10: 0.0051283613 + e11: -0.9760492 + e12: -0.21749379 + e13: 0.3579512 + e20: -0.060235165 + e21: -0.21739827 + e22: 0.9742449 + e23: 0.025155144 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: -0.99932635 + e01: -0.035765577 + e02: 0.008291565 + e03: 0.08149831 + e10: 0.02874168 + e11: -0.62159574 + e12: 0.7828291 + e13: 0.052144762 + e20: -0.022843808 + e21: 0.7825217 + e22: 0.62221843 + e23: -0.06347658 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + - e00: 0.99401116 + e01: -0.00048218702 + e02: -0.109282345 + e03: -0.07553721 + e10: -0.10925147 + e11: 0.018809272 + e12: -0.9938595 + e13: 0.040580485 + e20: 0.0025346808 + e21: 0.9998237 + e22: 0.018644353 + e23: -0.02280339 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_BoneNameHashes: + m_RootBoneNameHash: 0 + m_BonesAABB: + - m_Min: {x: -0.12132926, y: -0.3321573, z: -0.10399473} + m_Max: {x: 0.12293162, y: 0.3478911, z: 0.11866063} + - m_Min: {x: -0.09366471, y: 0.16117442, z: -0.08289033} + m_Max: {x: 0.093665116, y: 0.27041388, z: 0.10442592} + - m_Min: {x: -0.13091865, y: -0.07128954, z: -0.19338548} + m_Max: {x: 0.13091813, y: 0.34320712, z: 0.11548869} + - m_Min: {x: -0.13091889, y: -0.106496334, z: -0.13382383} + m_Max: {x: 0.13091865, y: 0.32439137, z: 0.12997614} + - m_Min: {x: -0.13091815, y: -0.0053960085, z: -0.13085672} + m_Max: {x: 0.13091832, y: 0.25739765, z: 0.13193926} + - m_Min: {x: -0.09514809, y: -0.143085, z: -0.08232039} + m_Max: {x: 0.1019532, y: 0.24670334, z: 0.1275838} + - m_Min: {x: -0.053297207, y: -0.027800113, z: -0.050008178} + m_Max: {x: 0.065450795, y: 0.22947535, z: 0.048172534} + - m_Min: {x: -0.05853103, y: -0.17048313, z: -0.055241168} + m_Max: {x: 0.064517915, y: 0.19430375, z: 0.040798068} + - m_Min: {x: -0.104298025, y: -0.13671392, z: -0.036469102} + m_Max: {x: 0.105109304, y: 0.24834424, z: 0.13055974} + - m_Min: {x: -0.066080034, y: -0.027800724, z: -0.060244143} + m_Max: {x: 0.0595662, y: 0.22947536, z: 0.06067574} + - m_Min: {x: -0.06880224, y: -0.1704818, z: -0.058241367} + m_Max: {x: 0.05276963, y: 0.19430572, z: 0.0751766} + - m_Min: {x: -0.12889893, y: -0.050486565, z: -0.15093169} + m_Max: {x: 0.09793951, y: 0.50948244, z: 0.115712374} + - m_Min: {x: -0.055570632, y: -0.25439042, z: -0.2010099} + m_Max: {x: 0.04680603, y: 0.34948346, z: 0.06299932} + - m_Min: {x: -0.040597796, y: -0.045691475, z: -0.117564246} + m_Max: {x: 0.06031075, y: 0.19206639, z: 0.078671955} + - m_Min: {x: -0.04586801, y: -0.1506767, z: -0.024211802} + m_Max: {x: 0.042569388, y: 0.11740069, z: 0.08117606} + - m_Min: {x: -0.06396452, y: -0.05048579, z: -0.1550012} + m_Max: {x: 0.09857974, y: 0.50948185, z: 0.10985528} + - m_Min: {x: -0.04842049, y: -0.25439093, z: -0.20234244} + m_Max: {x: 0.0558579, y: 0.34948236, z: 0.06440397} + - m_Min: {x: -0.049950972, y: -0.04355136, z: -0.11756235} + m_Max: {x: 0.042991817, y: 0.19521084, z: 0.07867251} + - m_Min: {x: -0.042641893, y: -0.15067479, z: -0.024212375} + m_Max: {x: 0.04581874, y: 0.11739859, z: 0.081212334} + m_VariableBoneCountWeights: + m_Data: + m_MeshCompression: 0 + m_IsReadable: 1 + m_KeepVertices: 0 + m_KeepIndices: 0 + m_IndexFormat: 0 + m_IndexBuffer: 0200010000000500040003000900080006000e000d000b001400120011001900170016001c001b001a001f001e001d002300220020002700250024002b002a0029002f002e002d0034003200310034002c0023003800370035003c0024003a003f003e0024004000430042004600450044004900480047004c004b004a004c004e004d00510050004f005400530052005300560055005100580057005b005a0059005a005b005c005f005e005d005e006100600064006300620063006400650046006700660049006900680071006d006b006f00740073007b00790075007e007d00770086008300800085008a00890092008f008c008e009500930099009800960097009b009a00a200a1009d009f00a600a400a900a800a700a800ab00aa00b200b000ac00b600b400af00bd00ba00b800be00c100c000c800c600c200cb00ca00c300cf00ce00cd00d100d000cd00d400d300d200d400d600d500d800d400d700d800d900d600db00da002100dd00d800dc00e000df00de00e300e200e100e600e500e400e800e700d900ea00e9002600ee00ec00eb00f000ef00da00f000f200f100f500f400f300f400f700f600e000f900f800fb00fa00f800fd00fc00e200fd00ff00fe00020101010001e60003010001060105010401e700e80005010901080107010901ea000a010d010c010b010d01ee000e0110010f016600130112011101150114014d001601550056001801170168001b011a0119011d011c0157001e016000610020011f0110012201210112012301140115012501160124012801270126012901170118012b012a011a012d012c011d012f011e012e013201310130013301f100f2003401f600f70036013501fa0038013701fe003a01020139013d013c013b0140013f013e01420141010b0144013301430146014501350148014701370150014d014a0152013a015101540153013f015601420155015c015b0157015f015e015401440161016001640163015901680166014c0169013a0152016b016a0146016e016d016c01710170016f017401730172017701760175017a01790178017d017c017b010a0007007e010f000c007f01130010008001180015008101840183018201870186018501230020003200270024003e002c00280023008a0189018801330030008b01340023003200390036008c013d003b008d013f0024003c003f0041003e00460044006700490047008e014c004a008f014c004d004b0051004f005800540052009001530055005200510057001c015b00590091015a005c0011015f005d0092015e0060005d00640062009301630065001901460066000f0149006800480070006a0094016e0072006c007c00760095017f0078007a0087008200960184008800810091008b009701900094008d009b019a0198019d019c019901a3009e009e01a000a5009c00a900a7009f01a800aa00a700b300ae00a001b500ad00b100bb00b700a101bc00bf00b900c900c400a201cc00c500c700cf00cd00a301d100cd00ce00d400d200d700d400d500d300d800d700dc00d800d600d400db002100a401dd00dc00f500e000de00a501e300e100ed00e600e4000301e800d900d800ea0026000a01ee00eb000e01f000da00db00f000f100ef00f500f300dd00f400f600f300e000f800df00fb00f800f900fd00e200e300fd00fe00fc00020100013901e60000010101060104013b01e70005010601090107013e0109010a0108010d010b0141010d010e010c0110016600a601130111015c0015014d004e001601560024011801680069001b01190165001d015700a7011e0161002e0120011001a60122011201130123011501a80125012401a901ac01ab01aa0129011801ad012b011a011b012d011d01a7012f012e01ae01b101b001af013301f20043013401f700b2013601fa00fb003801fe00ff003a01390151013d013b01040140013e01070142010b01550144014301b3014601350136014801370138014f014901b40152015101b50154013f01400156015501b6015d01580162015f015401400144016001330165015a01b70167014b014e0169015201b8016b0146013601bb01ba01b901be01bd01bc01c101c001bf01c401c301c201 + m_VertexData: + serializedVersion: 3 + m_VertexCount: 453 + m_Channels: + - stream: 0 + offset: 0 + format: 0 + dimension: 3 + - stream: 0 + offset: 12 + format: 0 + dimension: 3 + - stream: 0 + offset: 24 + format: 0 + dimension: 4 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 1 + offset: 0 + format: 0 + dimension: 2 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 0 + offset: 0 + format: 0 + dimension: 0 + - stream: 2 + offset: 0 + format: 0 + dimension: 4 + - stream: 2 + offset: 16 + format: 10 + dimension: 4 + m_DataSize: 36256 + _typelessdata: 80a8bb3dc720903f7ba8bbbda3768b360000803f474410b4dc2f1d2b474410340000803f0000803f7ca8bb3dc620903f8aa8bb3da3768b360000803f474410b4dc2f1d2b474410340000803f0000803f9e272c3dc820903fb0272c3da3768b360000803f474410b4dc2f1d2b474410340000803f0000803f80a8bbbdc620903f7ba8bbbd4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9d272cbdc820903f91272cbd4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9e272cbdc820903fb2272c3d4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9e272cbdc820903fb2272c3d000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9e272cbdc820903fb2272c3d000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9d272cbdc820903f91272cbd000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9d272cbd0413983f90272cbd000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9d272cbd0413983f90272cbd000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9e272c3dc820903fb0272c3d0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9e272c3dc820903fb0272c3d0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf9f272c3d0513983fb2272c3d0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9f272c3d0413983f93272cbd0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9f272c3d0413983f93272cbd0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf610f06befe96b93f560f06be000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f610f06befe96b93f560f06be000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf600f06beff96b93f6c0f063e000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf5f0f06be0613983f670f063e000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f5f0f06be0613983f670f063e000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf600f063efe96b93f560f06be0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf600f063efe96b93f560f06be0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f5f0f063e0513983f5e0f06be0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f5e0f063e0513983f670f063e0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf5e0f063e0513983f670f063e0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f9d272cbd0413983f90272cbdcc1bf1b5000080bf47441034f1df872a474410340000803f000080bf5f0f06be0513983f5d0f06becc1bf1b5000080bf47441034f1df872a474410340000803f000080bf5f0f06be0613983f670f063ecc1bf1b5000080bf47441034f1df872a474410340000803f000080bf9f272c3d0513983fb2272c3d00000080000080bf546ec9340000803f00000000000000000000803f5e0f063e0513983f670f063e00000080000080bf546ec9340000803f00000000000000000000803f5f0f063e0513983f5e0f06be00000080000080bf546ec9340000803f00000000000000000000803f1deef8bd9818243ff194ce3dd7f37fbf02ce9d3c56f480b636ee80b63dfb9e330000803f0000803f1deef8bd9818243ff194ce3dd8f37fbfe7c69d3c77ec5ab612e25ab61ded86330000803f0000803f1ceef8bd9718243fe294cebd79f37fbf2d29a03ce13e7736c832773611af9ab30000803f0000803f44d2bfbd6d78823f43d2bfbdbab87fbfebfa3e3dd623dfb5b6e5deb54f77a6330000803f0000803f47d2bf3d6e78823f42d2bfbdb9b87f3f52fb3e3dabe9b1b522b8b13516ba84330000803f000080bf1deef83d9618243fe294cebd79f37f3f0329a03c37ee783609e278b6c3bc9bb30000803f000080bf1deef83d9718243ff294ce3dd8f37f3f94c79d3c15825ab6b5775a3620ac86330000803f000080bf1deef83d9718243ff294ce3dd7f37f3fddcd9d3c7aac7cb679a07c36f7c09b330000803f000080bf80a8bbbdc620903f7ba8bbbd1cf47fbfc50a9c3c5758ccb6d94eccb6db1cf9330000803f0000803f80a8bbbdc620903f7ba8bbbd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f5ffebbbdf7068f3fb360aabd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f647cbfbd3b92833facdeadbd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f647cbfbd3b92833facdeadbd1ef47fbf30059c3c39fc52b66ef252b6f99580330000803f0000803f80a8bbbdc620903f7ba8bbbd1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f80a8bbbdc720903f8aa8bb3d1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f80a8bbbdc720903f8aa8bb3d1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f80a8bbbdc720903f8aa8bb3d1cf47fbf230b9c3c418e3835af8538356efd60b20000803f0000803f48d2bfbd6f78823f4bd2bf3db9b87fbf09fc3e3d854e5034851450345b671bb20000803f0000803f687cbfbd3c92833f2089e43c1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f687cbfbd3c92833f2089e43c1ef47fbfc2029c3c36b4a53385aca53334f7c9b00000803f0000803f80a8bb3dc720903f7ba8bbbd1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf80a8bb3dc720903f7ba8bbbd1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf5efebb3df8068f3fb260aabd1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf5efebb3df8068f3f5f91d63c1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf5efebb3df8068f3f5f91d63c1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf80a8bb3dc720903f7ba8bbbd1cf47f3ffc0a9c3c4bafb0b616a7b036cd64d7330000803f000080bf80a8bb3dc720903f7ba8bbbd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf677cbf3d3c92833faadeadbd1df47f3f53079c3ca2722db6946a2d36a26d53330000803f000080bf677cbf3d3c92833faadeadbd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf48d2bf3d6e78823f49d2bf3db9b87f3f38fc3e3db7699f34543d9fb40adb6db20000803f000080bf677cbf3d3c92833f2289e43c1ef47f3ff0029c3cc14d37343f4537b4f86a5fb10000803f000080bf677cbf3d3c92833f2289e43c1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf7ca8bb3dc620903f8aa8bb3d1df47f3ffa0b9c3c02b74335ecad43b55a996eb20000803f000080bf7ca8bb3dc620903f8aa8bb3d1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf5efebb3df8068f3f5f91d63c1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf5ffebbbdf7068f3fb360aabdb6afe4be880b653f931301b40e9c66b3a6f8e6330000803f0000803f5ffebbbdf7068f3f5e91d63cb8afe4be890b653f931301b4109c66b3a7f8e6330000803f0000803f98bba5be6a35803f121f913c340dffbe7df95d3f08802e3bb1daad3aba4e17bbc5ff7f3f0000803f5efebb3df8068f3fb260aabdb2afe43e8b0b653ff60802b473526833c2afe8330000803f0000803f9ebba53e6a35803f2a0499bde4f1f63e6c41603fb32f59b50d81d1343d413e350000803f0000803f9dbba53e6b35803f261f913c370dff3e7cf95d3f8b762e3b3fd1adba7f4617bbc5ff7f3f0000803f647cbfbd3b92833facdeadbd289de23e388f65bf9c503934ed0aa4b3c82c26340000803f000080bf2fe593be17756e3f95f79bbd3cfde23e7c7765bfdf14823434aee6b3c43269340000803f000080bf30e593be15756e3f90ec9c3c3b5ee33ef25e65bf4724783be963dcbae4545e3b88ff7f3f000080bfcfafe4be17695a3fac51223d1384f23e406f61bfa8935b3ca507d0bba560413c1dfa7f3f000080bfe8e7d4be1bf35e3f8e4cc13d3c7af23ec36b61bf7f02983c4a0110bc15e0853cb8f47f3f000080bf677cbf3d3c92833faadeadbd1e9de2be398f65bfca5d0134640865338c02e8330000803f000080bf677cbf3d3c92833f2289e43c1c9de2be3a8f65bfca5d0134620865338d02e8330000803f000080bf32e5933e17756e3fa4ec9c3c4c5ee3beed5e65bfe12c783b9e6bdc3a955c5e3b88ff7f3f000080bf9abba5be6a35803f2c0499bdfe418bbe62fbe6bdb2a674bf2de9fcbcd95d7e3fe228debd0000803f2fe593be17756e3f95f79bbddb6d8dbe0f66f7bd9d1674bf7faf09bd11207e3f9da0edbd0000803f647cbfbd3b92833facdeadbdf5983cbdedcd853cbfb17fbf162d453a43f77f3f97a9853c0000803fc78bf3be3a9a673febb5253d95f69cbe37f91cbe0e7e70bf89cb42bd66f97c3f773a15be0000803fcfafe4be17695a3fac51223d4f979bbe40361cbe05bf70bf0b2240bdf2007d3fcea414be0000803fd7afe43e16695a3fcd51223d3484f2be356f61bf849c5b3c2710d03b6968413c1dfa7f3f000080bf32e5933e16756e3f93f79bbd51fde2be767765bf66500134df51653386d2e7330000803f000080bf687cbfbd3c92833f2089e43cf6983cbd72cc853cbfb17f3fe72a453a43f77f3f1da885bc000080bf30e593be15756e3f90ec9c3cf0253f3e3b85ee3d0fba793f2551b3bc03427e3f1245eabd000080bf98bba5be6a35803f121f913cbbe3363e2b3fe43d45437a3fa315a4bcba677e3fc187e0bd000080bfe93de4be1e016c3fa79abf3d5223173f9200b53edebf393f767964be24786f3ff4658cbe000080bf9dbba53e6b35803f261f913cc9e336be4a3fe43d44437a3fc715a43cba677e3fdf87e0bd000080bf32e5933e17756e3fa4ec9c3cec253fbe4585ee3d0fba793f2951b33c03427e3f1c45eabd000080bf677cbf3d3c92833f2289e43cc8983c3d69cc853cbfb17f3faa2a45ba43f77f3f14a885bc000080bff03de43e1f016c3fb69abf3d482317bf7e00b53eebbf393f4979643e28786f3feb658cbe000080bff1e7d43e1cf35e3f9d4cc13d010917bfeb3cb93e61c9383fcb746a3e7fa86e3fc06c8fbe000080bf677cbf3d3c92833faadeadbddf983c3dbbcd853cbfb17fbfb52c45ba43f77f3f65a9853c0000803f32e5933e16756e3f93f79bbdde6d8d3e2f66f7bd9c1674bf95af093d11207e3fbba0edbd0000803f9ebba53e6a35803f2a0499bd06428b3e88fbe6bdb1a674bf67e9fc3cd95d7e3f0629debd0000803fd18bf33e3a9a673f08b6253d81f69c3e4cf91cbe117e70bf8bcb423d66f97c3f8d3a15be0000803fc78bf3be3a9a673febb5253dcec404bf40dc5a3f04a43b3ceaa4c23bcd6d20bcb4fb7f3f0000803f9abba5be6a35803f2c0499bde0f1f6be6e41603f0f1cf3b3a9826ab3b0f6d4330000803f0000803fd18bf33e3a9a673f08b6253dd3c4043f3ddc5a3f14ae3b3c62afc2bb657620bcb4fb7f3f0000803ff03de43e1f016c3fb69abf3d66ca043f0ed55a3f0ac9783c2a1001bc86b054bc72f87f3f0000803f9e272cbdc820903fb2272c3d000000800000803ffbfec9350000803f0000000000000000000080bf9e272cbdc820903fb2272c3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bfe0c89030c920903fb2272c3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bfe0c89030c920903fb2272c3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bf80f2cbb0c720903f8aa8bb3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bf80f2cbb0c720903f8aa8bb3d899dae350000803f474410b45fce442a474410340000803f0000803f80f2cbb0c720903f8aa8bb3d000000800000803ffbfec9350000803f0000000000000000000080bf80f2cbb0c720903f8aa8bb3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bf9e272c3dc820903fb0272c3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bf9e272c3dc820903fb0272c3d899dae350000803f474410b45fce442a474410340000803f0000803f7ca8bb3dc620903f8aa8bb3d899dae350000803f474410b45fce442a474410340000803f0000803f006a0631c620903f7aa8bbbd25573e360000803f474410b49187d62a474410340000803f0000803f006a0631c620903f7aa8bbbd000000800000803fa489e0b60000803f0000000000000000000080bf006a0631c620903f7aa8bbbd859daeb50000803f474410b45ace44aa474410340000803f0000803f006a0631c620903f7aa8bbbd21573eb60000803f474410b48d87d6aa474410340000803f0000803fa4d83d31c720903f90272cbd25573e360000803f474410b49187d62a474410340000803f0000803fa4d83d31c720903f90272cbd21573eb60000803f474410b48d87d6aa474410340000803f0000803f9d272cbdc820903f91272cbd25573e360000803f474410b49187d62a474410340000803f0000803f9d272cbdc820903f91272cbd000000800000803fa489e0b60000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbd859daeb50000803f474410b45ace44aa474410340000803f0000803f9e272c3dc820903f92272cbd859daeb50000803f474410b45ace44aa474410340000803f0000803f9e272c3dc820903f92272cbd21573eb60000803f474410b48d87d6aa474410340000803f0000803f2b2a26310513983fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bf2b2a26310513983fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803f2b2a26310513983fb2272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bfe0c89030c920903fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bfe0c89030c920903fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803fe0c89030c920903fb2272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803f9e272cbdc820903fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bf9e272cbdc820903fb2272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bf9f272c3d0513983fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803f9f272c3d0513983fb2272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803f9e272c3dc820903fb0272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803fa4d83d31c720903f90272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803fa4d83d31c720903f90272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bfa4d83d31c720903f90272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f4cb688310413983f93272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf4cb688310413983f93272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bf4cb688310413983f93272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f9d272cbd0413983f90272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803f9d272cbd0413983f90272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bf9e272c3dc820903f92272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf9e272c3dc820903f92272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f9f272c3d0413983f93272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf1a7e8c30ff96b93f6c0f063e00000080e2bc8db40000803f0000803f00000000000000000000803f00da51300613983f670f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f00da51300613983f670f063e00000080e2bc8db40000803f0000803f00000000000000000000803f5f0f06be0613983f670f063e00000080e2bc8db40000803f0000803f00000000000000000000803f610f063eff96b93f6b0f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f5e0f063e0513983f670f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f86f4c1310613983f5e0f06be000000809865e934000080bf0000803f0000000000000000000080bf86f4c1310613983f5e0f06be00000080a065e934000080bf0000803f0000000000000000000080bf86f4c1310613983f5e0f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf1299cd31fe96b93f560f06be000000807c65e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be000000809865e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be00000080a065e934000080bf0000803f0000000000000000000080bf610f06befe96b93f560f06be00000080a065e934000080bf0000803f0000000000000000000080bf610f06befe96b93f560f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf5f0f063e0513983f5e0f06be000000807c65e934000080bf0000803f0000000000000000000080bf5f0f063e0513983f5e0f06be000000809865e934000080bf0000803f0000000000000000000080bf600f063efe96b93f560f06be000000807c65e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf1a7e8c30ff96b93f6c0f063e000000800000803f474410b40000803f0000000000000000000080bf600f06beff96b93f6c0f063e000000800000803f474410b40000803f0000000000000000000080bf600f063efe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf610f063eff96b93f6b0f063e000000800000803f474410b40000803f0000000000000000000080bf00da51300613983f670f063e1f573e36000080bf474410348b87d6aa474410340000803f000080bf00da51300613983f670f063e00000080000080bf474410340000803f00000000000000000000803f00da51300613983f670f063e00000080000080bfeee5bd350000803f00000000000000000000803f00da51300613983f670f063e836d74b5000080bf47441034cbbe092a474410340000803f000080bf2b2a26310513983fb2272c3d1f573e36000080bf474410348b87d6aa474410340000803f000080bf2b2a26310513983fb2272c3d00000080000080bf474410340000803f00000000000000000000803f9d272cbd0413983faf272c3d1f573e36000080bf474410348b87d6aa474410340000803f000080bf9d272cbd0413983faf272c3d00000080000080bfeee5bd350000803f00000000000000000000803f5e0f063e0513983f670f063e836d74b5000080bf47441034cbbe092a474410340000803f000080bf9f272c3d0513983fb2272c3d00000080000080bf474410340000803f00000000000000000000803f9f272c3d0513983fb2272c3d836d74b5000080bf47441034cbbe092a474410340000803f000080bf9d272cbd0413983f90272cbd7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f9d272cbd0413983f90272cbd96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f4cb688310413983f93272cbd00000080000080bfa5a2f9b50000803f00000000000000000000803f4cb688310413983f93272cbd96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f86f4c1310613983f5e0f06be7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f86f4c1310613983f5e0f06be00000080000080bfa5a2f9b50000803f00000000000000000000803f86f4c1310613983f5e0f06be96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f86f4c1310613983f5e0f06be836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803f9f272c3d0413983f93272cbd00000080000080bfa5a2f9b50000803f00000000000000000000803f9f272c3d0413983f93272cbd836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803f5f0f063e0513983f5e0f06be836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803fd0bdd6316e78823f42d2bfbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bfd0bdd6316e78823f42d2bfbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bfd0bdd6316e78823f42d2bfbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bfd0bdd6316e78823f42d2bfbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bf006a0631c620903f7aa8bbbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bf006a0631c620903f7aa8bbbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bf80a8bbbdc620903f7ba8bbbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bf80a8bbbdc620903f7ba8bbbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bf47d2bf3d6e78823f42d2bfbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bfa8318bb09718243fe194cebdbc8cb036bed6bebddae27ebf0000803f8c9c033515c8af36000080bfd0bdd6316e78823f42d2bfbdbc1be133780a9c3c1df47fbf0000803f1b3609b14811e133000080bf44d2bfbd6d78823f43d2bfbd3bd135347b0a9c3c1cf47fbf0000803fe3a55db1c9c83534000080bf1deef83d9618243fe294cebdff131cb759c5f6bd84227ebf0000803f897396b5e2f01ab7000080bf47d2bf3d6e78823f42d2bfbddacf05b3760a9c3c1cf47fbf0000803f41202330a3c905b3000080bf80a8bbbdc720903f8aa8bb3d00000080f6099c3c1df47f3f0000803f00000000000000000000803f80f2cbb0c720903f8aa8bb3d00000080db099c3c1cf47f3f0000803f00000000000000000000803f78cbd6306e78823f4ad2bf3d0b7761334eaa193dded17f3f0000803f235607b16a4e61b30000803f7ca8bb3dc620903f8aa8bb3d00000080cd099c3c1df47f3f0000803f00000000000000000000803f48d2bf3d6e78823f49d2bf3db97d3a3c3154103d0ed37f3fc1fb7f3f974bd2b912603abc0000803f48d2bfbd6f78823f4bd2bf3d4e7d3abc3d54103d0fd37f3fc1fb7f3f304bd239a85f3a3c0000803f441459b19818243ffa40eb3de06221b3834e9fbd6f397f3f0000803fd0db48b1b2e520330000803f1deef83d9718243ff294ce3d6e23eb3d1cf9e4bdfab07c3f0ea4533c1e657e3f8f70e33d000080bfc29bf5bd04bb1a3f74dcbb3dd1f17fbf029aa9bc272c07bbbd2407bb081b33b8ddff7f3f0000803fc49bf5bd05bb1a3fccd3babd57eb7fbfd7aecdbc949bb2322a8db23291800f300000803f0000803f1deef8bd9818243ff194ce3d6623ebbde0f8e4bdfab07c3fcfa353bc1f657e3f5370e33d000080bf4549a7bc05bb1a3feaeed33d2cadebbd7d69f9bd88617c3fa04c7e3faa2567bc0ce6e93d0000803fa8318bb09718243fe194cebdc8885f3f038cf9be549c3f348e4f27b4d9c7ba330000803f000080bf4349a7bc04bb1a3fcbd3babd096a723f9e93a4bedfbd0e349c2a07b4e48737330000803f000080bf4549a7bc05bb1a3feaeed33d5bd3743f639d95be56ba063be7d800bba77a1d3addff7f3f000080bf1ceef8bd9718243fe294cebd00c0cfb5efc2f6bd8e227ebf0000803fb14048b48b3cceb5000080bfc49bf5bd05bb1a3fccd3babdfd0d17b47c839fbe434273bf0000803f8b3e3cb360890fb4000080bf4349a7bc04bb1a3fcbd3babd32b0aab391759bbe05ea73bf0000803f234ecfb248a1a2b3000080bfa8318bb09718243fe194cebdc2885fbf168cf9be6130cf33d3e9b4336ff749330000803f0000803f441459b19818243ffa40eb3dc4885fbf138cf9be3aca9134179a7e34781d0e340000803f0000803f3e49a73c05bb1a3feaeed33d5cd374bf619d95be61bb063be7d9003bdd7b1d3addff7f3f0000803fc59bf53d05bb1a3f75dcbb3d1470eb3d4dc1d0bddef57c3f2dfe403ca7aa7e3f435bcf3d000080bf3e49a73c05bb1a3feaeed33d0badeb3d9369f9bd89617c3fa04c7e3f9d25673cece5e9bd0000803f1deef83d9618243fe294cebd7bf37f3f8923a03ce21253368f0853b61a0984b30000803f000080bfc59bf53d04bb1a3fccd3babd57eb7f3fd9aecdbce7c82231c4bb22b110ca822e0000803f000080bf1deef83d9618243fe294cebd8e9da6350cc3f6bd8d227ebf0000803f589a2034d066a535000080bfa8318bb09718243fe194cebdff7fbb36afd3bebde3e27ebf0000803f0ac40b352cafba36000080bfa8318bb09718243fe194cebd90a4bbb628d4bebde2e27ebf0000803fa4df0bb594d3bab6000080bf4249a73c05bb1a3fcbd3babd61196db483759bbe08ea73bf0000803f34fb8fb3d8e761b4000080bfe690fbbdce17b53e4e99d43de1f37fbf65620a3b019a9cbced5b0a3bdbff7f3f844e2938000080bf59cff7bd6958b53e011b023cb2f57fbfd102f8392d3791bcd7f8f739feff7f3f0eaf0c37000080bfbe3af5bdecd3d23d56ed2c3d84ca7fbf86906cbabc6725bd1f5f6cbaf9ff7f3f06d918b8000080bf2697edbda5dbd33d19b635bde2c67fbf4d54fa3b9a1528bd521efa3b17fe7f3fad5da439000080bf380910bdce17b53e70dde63db336d2bd6b6fd7bd4e387d3fdba57e3fe6d731bcf008d13d0000803fe690fbbdce17b53e4e99d43dd7e4bcbdc55ddcbd856a7d3fa6e87e3f0b4c23bcadc9bb3d0000803fc29bf5bd04bb1a3f74dcbb3d1d70ebbd09c1d0bde0f57c3ff4fd40bca8aa7e3fff5acf3d000080bf932c1bbd0d93d13dbaa3303dc61fabbc616a00be38ec7d3fb3f17f3f96b72bbbc9c5a93c0000803fbe3af5bdecd3d23d56ed2c3dbb0e43bc5467fbbdaa0b7e3f5bfb7f3fa691bfba0495413c0000803f888608bd6a58b53e051b023c22cf7f3f3ef817bd46342f3c65152fbc8106d03941fc7f3f000080bf380910bdce17b53e70dde63d87c57f3f96cf1dbd99bc8d3ca6a18dbce3c52e3a31f67f3f000080bfd56721bdd0f9d13d97d92abd0ff27f3f764d3cbce64c8cbc64463c3cacfb7f3f56694eb90000803f932c1bbd0d93d13dbaa3303d8bf27f3f586874bc1ebd60bcb8b6603c079556b9d6f97f3f000080bf59cff7bd6958b53e011b023c1d319a33bf9cb2bd4a067fbf0000803f1e29d731b69a9933000080bf888608bd6a58b53e051b023ccb2c623b6096bfbd38e07ebf9cff7f3f8944a939e22e613b000080bf2697edbda5dbd33d19b635bdb005063d6468853ed90377bfe9dc7f3f5fc20bbc3d63013d000080bfd56721bdd0f9d13d97d92abd4d93153d53a7843eeb1477bf4ad47f3feb1d1bbc0376103d000080bf8e86083d6b58b53efc1a023c21cf7fbf52f817bd04342f3c23152f3c4e06d03941fc7f3f0000803f3d09103dcc17b53e70dde63d87c57fbfa3cf1dbd6dbc8d3c7aa18d3cbbc52e3a31f67f3f0000803f992c1b3d0893d13db7a3303d8bf27fbf426874bcfbbc60bc95b660bcd29456b9d6f97f3f0000803f4249a73c05bb1a3fcbd3babd056a72bfb293a4be82690133aa16f532826426320000803f0000803f992c1b3d0893d13db7a3303d901fab3c5f6a00be38ec7d3fb3f17f3f5db72b3b94c5a9bc0000803f3d09103dcc17b53e70dde63d9236d23d6f6fd7bd50387d3fdba57e3fccd7313cd008d1bd0000803feb90fb3dcc17b53e5099d43dbfe4bc3dc95ddcbd856a7d3fa6e87e3ff94b233c95c9bbbd0000803fc53af53de6d3d23d57ed2c3d84ca7f3fadb46cba9b6725bd3f836c3af9ff7f3f44f018b80000803feb90fb3dcc17b53e5099d43de1f37f3f3a630a3b2d999cbcc25c0abbdbff7f3fa34e29380000803f63cff73d6b58b53e051b023cb2f57f3ff70ef839953691bcfd04f8b9feff7f3f5eb50c370000803fc59bf53d05bb1a3f75dcbb3dd1f17f3f6a99a9bc1e2c07bbb424073b5b1a33b8ddff7f3f000080bf2e97ed3d9ddbd33d1cb635bd900506bd6568853ed90377bfe9dc7f3f3fc20b3c1f6301bd000080bf63cff73d6b58b53e051b023ce6b6e333da9cb2bd49067fbf0000803fb1e01e32c6d8e233000080bf8e86083d6b58b53efc1a023c192b62bb6f96bfbd37e07ebf9cff7f3f5143a9b9312d61bb000080bfc59bf53d04bb1a3fccd3babd6b0489b486839fbe404273bf0000803f47c0aab3a73282b4000080bfe93de4be1e016c3fa79abf3d3fca04bf26d55a3f0ac2783c620c013ca2aa54bc72f87f3f0000803fedb2eebe20e1683f4241093ecf741fbf04a7463f4a7acb3d44be7e3d54ae9ebdbcbb7e3f0000803fe8e7d4be1bf35e3f8e4cc13df208173fde3cb93e72c9383fa1746abe80a86e3fc16c8fbe000080bfe35edfbea4055c3f41b00a3ed2240d3f30ceb13e4831423f6b1351be3a11703f0ed48fbe000080bfedb2eebe20e1683f4241093e6552153f8941ba3e76eb393fa24369bec3756e3fcb3791be000080bf80a5f9bef476543fac53353d8d2e0b3f6bad56bf70560dbdb5c6993c2830edbcf8d87f3f000080bfe35edfbea4055c3f41b00a3ee02d0b3fe4ad56bf9c490dbdfeb7993c211bedbc00d97f3f000080bf7c1504bfdf8d613f1c103b3d907bb0be3e132ebe7e566cbf048e73bd1e467c3f341423be0000803f8115043fdf8d613f42103b3d18771f3fdda4463f118ecb3decda7ebd2fbc9ebd7ebb7e3f0000803ff3b2ee3e1ee1683f4c41093ed7741f3ff9a6463fe07acb3d0dbf7ebdc1ae9ebdbabb7e3f0000803fd7afe43e16695a3fcd51223d37979b3e48361cbe0abf70bff721403df2007d3fd9a414be0000803f8aa5f93ef276543fd253353d128bc43e8a3e43bed94a67bf17b3983db74d7b3f74b233be0000803f8115043fdf8d613f42103b3d907bb03e43132ebe7e566cbf0a8e733d1e467c3f391423be0000803ff1e7d43e1cf35e3f9d4cc13dab7af2bea46b61bf4806983c2205103c58e3853cb7f47f3f000080bfeb5edf3ea2055c3f4bb00a3ef22d0bbfd7ad56bf84490dbdf7b799bcea1aedbc00d97f3f000080bff3b2ee3e1ee1683f4c41093e665215bf7241ba3e7beb393f8243693ec8756e3fba3791be000080bf71c510bf212c4b3f0ca8473e2dc433bf17e5303f11a62f3e8365fa3d9c65f6bda9347c3f0000803fe5e616bf4fa5473fa6171c3e23c433bf18e5303f9ba62f3e4066fa3d6566f6bda3347c3f0000803f13670cbfda48463f2918453e02aaab3edbb9363e08d16c3f4b0e79bd28e47b3f61ca2bbe000080bf71c510bf212c4b3f0ca8473ee494a93ea0d13e3eefca6c3f47a880bd14847b3f12a633be000080bf5eb812bf92a6423fc433183ec6ca143fdea94fbfc32084bd47e9193de3ce56bd77777f3f000080bf80a5f9bef476543fac53353d058bc4be923e43bedc4a67bf14b398bdb64d7b3f7eb233be0000803fe5e616bf4fa5473fa6171c3ec8ce18bfaffab1bed01c39bfef9a62befb08703f764189be0000803f13670cbfda48463f2918453e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bf5eb812bf92a6423fc433183e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bfe5e616bf4fa5473fa6171c3e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bfece6163f4ba5473fb6171c3e20c4333f27e5303fefa52f3e4065fabd8365f6bdac347c3f000080bf66b8123f8ea6423fd333183e57ba173f53feb5be660639bfaccd663e0a486f3f17ba8cbe0000803fece6163f4ba5473fb6171c3ee1ce183f4dfab1bed11c39bf889a623e0e09703f214189be0000803f18670c3fd748463f3918453ebaca14bfdea94fbf282484bd33ed19bd6fd456bd71777f3f000080bf66b8123f8ea6423fd333183ebfca14bfe0a94fbf442184bdd6e919bdb7cf56bd76777f3f000080bfeb5edf3ea2055c3f4bb00a3ed7240dbf2cceb13e4431423f6d13513e3b11703f07d48fbe000080bf78c5103f1d2c4b3f1ba8473ea094a9bec2d13e3ef9ca6c3f2aa8803d12847b3f3aa633be000080bfece6163f4ba5473fb6171c3e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bf66b8123f8ea6423fd333183e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bf18670c3fd748463f3918453e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bfd1bdf5bd24959d3d967b2c3d8aa07fbf9be0303cc48758bd49a1303c2ffc7f3f8d9d153a000080bf65331cbd72549c3de931303d34e535bce84685bb6bfb7f3f52653db875ff7f3fcd44853b000080bf986e22bd73c19c3db98f4fbd93a07d3f10c4ccbdd44fbcbd345cbb3de24317bc5fea7e3f000080bf65331cbd72549c3de931303dc5df7f3f961b1cbcedbdf43cbf091c3c07fd7f3fd83f95390000803fbf1aeebd2ba39e3d2b6c5abdc278e23cb7a8b43ef46d6fbff4e67f3fcfe11fbcbde4d33c000080bf986e22bd73c19c3db98f4fbdaae1153d854fb63e9e096fbf1cd47f3f9b9e55bc520b0c3d000080bfda67213dcbf9d13d9cd92abd0ff27fbfa84c3cbcc14c8cbc96453cbcacfb7f3f3e684eb9000080bf6a331c3d6d549c3de731303dc5df7fbf071c1cbc1bbef43c300a1cbc07fd7f3f60409539000080bfc53af53de6d3d23d57ed2c3d8e0e433c6167fbbdaa0b7e3f5bfb7f3f8491bf3ad79441bc0000803fd8bdf53d1f959d3d967b2c3d7be2353c2f3985bb6bfb7f3ffc4e3d3876ff7f3f1537853b000080bf6a331c3d6d549c3de731303dbde4353c304685bb6cfb7f3fd2633d3876ff7f3f1744853b000080bf2e97ed3d9ddbd33d1cb635bde2c67f3fbe56fa3b8e1528bdc120fabb16fe7f3f3b5fa4390000803fc61aee3d25a39e3d2d6c5abd27cd7e3f25a331bd49e8b0bdd9f8303d57c27f3fe0bd75bb0000803fd8bdf53d1f959d3d967b2c3d8aa07f3f14df303cd98758bdc39f30bc2ffc7f3f509c153a0000803fda67213dcbf9d13d9cd92abd209315bd4da7843eeb1477bf4ad47f3fb51d1b3cd77510bd000080bf9b6e223d6dc19c3dbe8f4fbd82e115bd844fb63e9f096fbf1cd47f3f619e553c2d0b0cbd000080bfbf1aeebd2ba39e3d2b6c5abd27cd7ebf76a331bd40e8b0bd2af930bd57c27f3f44be75bb000080bf1348f7bd24a4a9341f262b3dd4f97ebf81e5afbceda4b1bdb63bafbce4f07f3f692cf4ba000080bf828486bd25b996341d15adbd277f733f737a70be512c4dbe0a31473eeeb844bd07cf7a3f000080bf93471fbd9a1b9d3472dc2e3dab737f3f68547ebdb866a83c7f13a8bc7e56a73a26f27f3f000080bf9021cebd5d859734a640aabd625c17bdbf6ab43e92646fbf3dd37f3f787d553c7aa30dbd000080bf828486bd25b996341d15adbde56464bbed38be3e9eac6dbf9aff7f3fefb5a93abd0b54bb000080bf1348f7bd24a4a9341f262b3d288609b3000080bf724b8e340000803f288609b3e3e118280000803f1348f7bd24a4a9341f262b3d6a079ab4000080bf274725342ee34629274725340000803f000080bf1348f7bd24a4a9341f262b3d2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf1348f7bd24a4a9341f262b3d85cca2b4000080bf75388b34e711b12975388b340000803f000080bf93471fbd9a1b9d3472dc2e3d6a079ab4000080bf274725342ee34629274725340000803f000080bf93471fbd9a1b9d3472dc2e3d2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf828486bd25b996341d15adbd288609b3000080bf724b8e340000803f288609b3e3e118280000803f828486bd25b996341d15adbd6a079ab4000080bf274725342ee34629274725340000803f000080bf9b6e223d6dc19c3dbe8f4fbd93a07dbf0cc4ccbdc84fbcbd285cbbbdd54317bc5fea7e3f0000803f9d471f3d8210653478dc2e3dab737fbfa1547ebd0f67a83cd613a83cfa56a73a26f27f3f0000803f9621ce3dfce66c34a840aabdd5617a3fd8de0bbe411921be6c180a3ec1997d3f46b4b1bc0000803f1c48f73d1f99593427262b3dd4f97e3fa5e5afbc0ba5b1bdda3baf3ce4f07f3fc42cf4ba0000803fc61aee3d25a39e3d2d6c5abd7878e2bcbca8b43ef46d6fbff4e67f3f9fe11f3c78e4d3bc000080bf8684863d34926c342015adbd8869643bea38be3e9fac6dbf9aff7f3f5fb9a9ba0c10543b000080bf1c48f73d1f99593427262b3d5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f1c48f73d1f99593427262b3daf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf1c48f73d1f99593427262b3d56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f1c48f73d1f99593427262b3d226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f9621ce3dfce66c34a840aabd5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f8684863d34926c342015adbd5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f8684863d34926c342015adbdaf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf746a073e606a3a346d2b363e630d7f3f0f5d8f3cc95facbdcbda8ebcf7f57f3fe617c13a0000803f6ba7063e657e2d3d6d2b363e97137f3f91137a3cc8f6aabd0f3479bc5ef87f3f0c07a73a0000803f63a706be807e2d3d642b363e99137fbf4d127a3c95f6aabdce32793c5ef87f3f0106a73a000080bf6b6a07be9976be34622b363e630d7fbfd05b8f3c945facbd8dd98e3cf7f57f3ffd15c13a000080bf9d471f3d8210653478dc2e3daf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf9d471f3d8210653478dc2e3d56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f50256f3db03a45346d2b363e56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f50256f3db03a45346d2b363e226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f6b6a07be9976be34622b363e85cca2b4000080bf75388b34e711b12975388b340000803f000080bf3a256fbd8170b234632b363e2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf3a256fbd8170b234632b363e85cca2b4000080bf75388b34e711b12975388b340000803f000080bfcf196c3dea8b2b3d6d2b363e7c5f7dbf21627cbc3178113eb4d279bc3af87f3f6f6e0f3b000080bf3a256fbd8170b234632b363efc567d3f07e58fbceb22123edd6b8e3ce4f57f3ffa4e243b0000803fbd196cbdfd8b2b3d652b363e7c5f7d3f59617cbc2578113eeed1793c3af87f3ff26d0f3b0000803fd8bdf53d1f959d3d967b2c3d5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bf6ba7063e657e2d3d6d2b363e5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bfcf196c3dea8b2b3d6d2b363e5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bfd1bdf5bd24959d3d967b2c3dea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bf65331cbd72549c3de931303dea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bfbd196cbdfd8b2b3d652b363eea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bf3a256fbd8170b234632b363e00000080c4da17b50000803f0000803f00000000000000000000803f6b6a07be9976be34622b363e00000080c4da17b50000803f0000803f00000000000000000000803f63a706be807e2d3d642b363e00000080c4da17b50000803f0000803f00000000000000000000803f6ba7063e657e2d3d6d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f746a073e606a3a346d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f50256f3db03a45346d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f9e272c3dc820903f92272cbd4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f80a8bb3dc720903f7ba8bbbd4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f9e272c3dc820903fb0272c3d4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f80a8bbbdc720903f8aa8bb3db0f14cb60000803f474410b438fde6aa474410340000803f0000803f80a8bbbdc620903f7ba8bbbdb0f14cb60000803f474410b438fde6aa474410340000803f0000803f9e272cbdc820903fb2272c3db0f14cb60000803f474410b438fde6aa474410340000803f0000803f9d272cbd0413983faf272c3d000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9e272c3dc820903f92272cbd0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf5f0f06be0513983f5d0f06be000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f610f063eff96b93f6b0f063e0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf9d272cbd0413983faf272c3d710034b6000080bf4744103483e0ca2a474410340000803f000080bf9d272cbd0413983f90272cbd710034b6000080bf4744103483e0ca2a474410340000803f000080bf5f0f06be0613983f670f063e710034b6000080bf4744103483e0ca2a474410340000803f000080bf9f272c3d0413983f93272cbdc62b3936000080bf4744103405b4d0aa474410340000803f000080bf9f272c3d0513983fb2272c3dc62b3936000080bf4744103405b4d0aa474410340000803f000080bf5f0f063e0513983f5e0f06bec62b3936000080bf4744103405b4d0aa474410340000803f000080bf5ffebbbdf7068f3fb360aabd1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f80a8bbbdc620903f7ba8bbbd1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f7ca8bb3dc620903f8aa8bb3d1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf5efebb3df8068f3fb260aabd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf5efebb3df8068f3f5f91d63cb1afe43e8a0b653f941301b40b9c6633aaf8e6330000803f0000803f687cbfbd3c92833f2089e43c2f9de23e358f65bfc75d0134700865b38202e8330000803f000080bf5ffebbbdf7068f3fb360aabd4f413ebdf21ea33c42ac7fbf7981723a01f37f3fdbf1a23c0000803f5ffebbbdf7068f3f5e91d63c51413ebd901da33c42ac7f3f6d7f723a01f37f3f79f0a2bc000080bf5efebb3df8068f3f5f91d63c1a413e3d831da33c42ac7f3f147f72ba01f37f3f6cf0a2bc000080bf5efebb3df8068f3fb260aabd31413e3db51ea33c42ac7fbff88072ba01f37f3f9ef1a23c0000803f80a8bbbdc720903f8aa8bb3d000000800000803ffbfec9350000803f0000000000000000000080bf80a8bbbdc620903f7ba8bbbd000000800000803fa489e0b60000803f0000000000000000000080bf9d272cbd0413983faf272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bf9d272cbdc820903f91272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803f600f06beff96b93f6c0f063e00000080dabc8db40000803f0000803f00000000000000000000803f1a7e8c30ff96b93f6c0f063e00000080e6bc8db40000803f0000803f00000000000000000000803f1a7e8c30ff96b93f6c0f063e00000080dabc8db40000803f0000803f00000000000000000000803f5f0f06be0613983f670f063e00000080dabc8db40000803f0000803f00000000000000000000803f610f063eff96b93f6b0f063e00000080e6bc8db40000803f0000803f00000000000000000000803f00da51300613983f670f063e00000080e6bc8db40000803f0000803f00000000000000000000803f5f0f06be0513983f5d0f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf610f06befe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf5f0f06be0613983f670f063e00000080000080bfeee5bd350000803f00000000000000000000803f5f0f06be0513983f5d0f06be7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f44d2bfbd6d78823f43d2bfbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bf1ceef8bd9718243fe294cebd61d317375ac5f6bd84227ebf0000803f2a5a923533b81637000080bf1ceef8bd9718243fe294cebd7bf37fbffd23a03c4e5950361e4f50361b5582b30000803f0000803f441459b19818243ffa40eb3dc2885f3f198cf9be5ca18c335f9775b3e81509330000803f000080bf7c1504bfdf8d613f1c103b3d21771fbfdaa4463f9d8ccb3d24d97e3d08bb9ebd82bb7e3f0000803f8aa5f93ef276543fd253353d882e0bbf6ead56bf40550dbd65c599bc2e2eedbcf9d87f3f000080bf13670cbfda48463f2918453ebcca143fdea94fbff82284bdd1eb193d7dd256bd73777f3f000080bf5eb812bf92a6423fc433183e38ba17bfcffeb5be610639bf31ce66bef3476f3f82ba8cbe0000803f71c510bf212c4b3f0ca8473e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bf13670cbfda48463f2918453e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bfe5e616bf4fa5473fa6171c3e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bf78c5103f1d2c4b3f1ba8473e2cc4333f2ee5303fbfa42f3e9163fabdd363f6bdb8347c3f000080bf18670c3fd748463f3918453eada9abbe22ba363e13d16c3f340e793d26e47b3fafca2bbe000080bf78c5103f1d2c4b3f1ba8473ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bfece6163f4ba5473fb6171c3ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bf18670c3fd748463f3918453ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bfd1bdf5bd24959d3d967b2c3dc5e235bce43785bb6bfb7f3f734d3db876ff7f3fca35853b000080bf9021cebd5d859734a640aabdd5617abfd2de0bbe351921be65180abec1997d3f32b4b1bc000080bf9021cebd5d859734a640aabd288609b3000080bf724b8e340000803f288609b3e3e118280000803f8684863d34926c342015adbd277f73bf827a70be4a2c4dbe023147bef4b844bd07cf7a3f0000803f9621ce3dfce66c34a840aabdc65c173db86ab43e93646fbf3dd37f3ffe7d55bcd9a30d3d000080bf746a073e606a3a346d2b363e226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f50256f3db03a45346d2b363efb567dbf5be58fbcf522123e2f6c8ebce4f57f3f664f243b000080bf6a331c3d6d549c3de731303ddc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bfd8bdf53d1f959d3d967b2c3ddc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bfcf196c3dea8b2b3d6d2b363edc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bf63a706be807e2d3d642b363e7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfd1bdf5bd24959d3d967b2c3d7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfbd196cbdfd8b2b3d652b363e7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfbd196cbdfd8b2b3d652b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803f3a256fbd8170b234632b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803f63a706be807e2d3d642b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803fcf196c3dea8b2b3d6d2b363e00000080474410340000803f0000803f00000000000000000000803f6ba7063e657e2d3d6d2b363e00000080474410340000803f0000803f00000000000000000000803f50256f3db03a45346d2b363e00000080474410340000803f0000803f00000000000000000000803f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000949ff23e3734db3e8972b03d3ff2413c020000000800000003000000010000004702fc3e643adb3e500da33d00000000020000000300000008000000000000006476023f3813fb3e000000000000000002000000050000000000000000000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000004702fc3e643adb3e500da33d00000000020000000300000008000000000000004702fc3e643adb3e500da33d000000000200000003000000080000000000000069c4603fa9deb03dbf7fbb3cfff0503c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000004b975e3fa309f43d37e0393c000000000400000003000000020000000000000081b15e3ffc39053e0000000000000000040000000300000000000000000000007271523fded8153e6e85013d00000000030000000400000002000000000000007271523fded8153e6e85013d00000000030000000400000002000000000000002af4623fe1d5d23d7b462c3c00000000040000000300000002000000000000002af4623fe1d5d23d7b462c3c0000000004000000030000000200000000000000d4a4193f7d33a33eef66903dfa232d3c03000000040000000200000008000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000e6c41e3ffaa1a13ee850833d00000000030000000400000002000000000000007271523fded8153e6e85013d000000000300000004000000020000000000000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000003a95003f8dd5fe3e00000000000000000b0000000000000000000000000000003a95003f8dd5fe3e00000000000000000b00000000000000000000000000000045bd083f7785ee3e0000000000000000000000000b000000000000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000065a0ca3e5235be3e6f22103e4864bc3d0100000002000000000000000500000068780b3f300fe93e0000000000000000000000000f00000000000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000002028033fc0aff93e0000000000000000050000000200000000000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c050000000200000001000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c050000000200000001000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000000676f43ecf95d83e1819b43dbabc3d3c0200000005000000030000000100000062fdca3e1f24c33e54921a3e5055923d02000000010000000000000003000000102c0c3fa119963ee44ce53d24d8413d02000000010000000000000003000000102c0c3fa119963ee44ce53d24d8413d020000000100000000000000030000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000d217023f5bd0fb3e000000000000000008000000020000000000000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000ba08fd3eea15f83ebd15ae3c00000000080000000200000003000000000000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e0000000000000000020000000800000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000008105063f5ff9983e4316da3d3ed8913d02000000010000000000000005000000d986c63eadc8c33eaead203e8d66953d010000000200000000000000030000007876053f0e07913e1c5ce03de8d3af3d020000000100000000000000050000007876053f0e07913e1c5ce03de8d3af3d02000000010000000000000005000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000ba08fd3eea15f83ebd15ae3c00000000080000000200000003000000000000002028033fc0aff93e0000000000000000050000000200000000000000000000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000007b285e3f8598eb3d7e8e8c3c0000000006000000050000000700000000000000d217023f5bd0fb3e0000000000000000080000000200000000000000000000002026053fc0b3f53e000000000000000009000000080000000000000000000000b13b633f8ecdc73d3ba7723c0000000009000000080000000a000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c0500000002000000010000000000000022aa043fbdabf63e00000000000000000600000005000000000000000000000074ab643ff1edb93dc0d9823c0000000006000000050000000700000000000000aca8593f4e5d193e00000000000000000700000006000000000000000000000064573a3f37518b3e0000000000000000060000000700000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000007876053f0e07913e1c5ce03de8d3af3d0200000001000000000000000500000050a55f3f8ba1dc3de0cf983c0000000009000000080000000a00000000000000bf0e043f82e2f73e00000000000000000600000005000000000000000000000022aa043fbdabf63e0000000000000000060000000500000000000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c05000000020000000100000000000000f46c023f1826fb3e000000000000000007000000060000000000000000000000aca8593f4e5d193e0000000000000000070000000600000000000000000000001daa593f8a57193e00000000000000000a0000000900000000000000000000003cbc033f8787f83e000000000000000009000000080000000000000000000000102c0c3fa119963ee44ce53d24d8413d0200000001000000000000000300000074ab643ff1edb93dc0d9823c00000000060000000500000007000000000000007b285e3f8598eb3d7e8e8c3c0000000006000000050000000700000000000000c4cd413fefc8783e000000000000000006000000070000000000000000000000b13b633f8ecdc73d3ba7723c0000000009000000080000000a0000000000000050a55f3f8ba1dc3de0cf983c0000000009000000080000000a000000000000007876053f0e07913e1c5ce03de8d3af3d02000000010000000000000005000000ed28423f4a5c773e0000000000000000090000000a000000000000000000000088f6393ff1128c3e0000000000000000090000000a00000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000003cbc033f8787f83e0000000000000000090000000800000000000000000000002026053fc0b3f53e000000000000000009000000080000000000000000000000f777023f1310fb3e00000000000000000a000000090000000000000000000000f46c023f1826fb3e000000000000000007000000060000000000000000000000bf0e043f82e2f73e000000000000000006000000050000000000000000000000f777023f1310fb3e00000000000000000a000000090000000000000000000000ed28423f4a5c773e0000000000000000090000000a0000000000000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d020000000300000005000000010000004702fc3e643adb3e500da33d00000000020000000300000008000000000000004702fc3e643adb3e500da33d0000000002000000030000000800000000000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d020000000500000001000000030000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c02000000030000000500000001000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000f627253fb9a9413e263a1b3e80c4673c020000000300000005000000080000009276033fdc12f93e0000000000000000020000000800000000000000000000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000004d6d2c3fb9de2d3e9959123ebb27613c02000000030000000800000005000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d000000000200000003000000050000000000000069c4603fa9deb03dbf7fbb3cfff0503c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c030000000200000004000000080000004702fc3e643adb3e500da33d00000000020000000300000008000000000000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c02000000030000000500000001000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000dab673f99a7c23d0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000de3c593f890c1b3e000000000000000004000000030000000000000000000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d000000000300000004000000020000000000000076f86c3f4f3c983d00000000000000000400000003000000000000000000000076f86c3f4f3c983d00000000000000000400000003000000000000000000000076f86c3f4f3c983d0000000000000000040000000300000000000000000000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000004b975e3fa309f43d37e0393c0000000004000000030000000200000000000000d4a4193f7d33a33eef66903dfa232d3c03000000040000000200000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000002af4623fe1d5d23d7b462c3c000000000400000003000000020000000000000076f86c3f4f3c983d0000000000000000040000000300000000000000000000000dab673f99a7c23d00000000000000000400000003000000000000000000000081b15e3ffc39053e0000000000000000040000000300000000000000000000002af4623fe1d5d23d7b462c3c0000000004000000030000000200000000000000de3c593f890c1b3e0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c0000000003000000040000000200000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000fabb563fc63f0a3e7e82d63c000000000300000004000000020000000000000069c4603fa9deb03dbf7fbb3cfff0503c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d00000000030000000400000002000000000000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c03000000020000000400000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d01000000050000000200000000000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d020000000500000001000000030000006476023f3813fb3e0000000000000000020000000500000000000000000000006476023f3813fb3e00000000000000000200000005000000000000000000000065a0ca3e5235be3e6f22103e4864bc3d010000000200000000000000050000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f000000000000005f432d3f53d1213ef4eae33dd5ae5c3d0100000005000000020000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000068780b3f300fe93e0000000000000000000000000f000000000000000000000065a0ca3e5235be3e6f22103e4864bc3d010000000200000000000000050000000676f43ecf95d83e1819b43dbabc3d3c02000000050000000300000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000502c2f3f445f303e2a62a53dca7c803d01000000020000000000000003000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d986c63eadc8c33eaead203e8d66953d0100000002000000000000000300000062fdca3e1f24c33e54921a3e5055923d02000000010000000000000003000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000005c552c3f2f97933ebff01d3d000000000b000000000000000c00000000000000f53d043f3b70f13e7d7b423c00000000000000000b0000000c000000000000003a95003f8dd5fe3e00000000000000000b0000000000000000000000000000007b5ffe3ef5cfdd3efe78253dfe16f23c0b000000000000000f0000000c000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f0000000000000007eb4e3f51012e3e9d94b23c00000000000000000b0000000f000000000000007b5ffe3ef5cfdd3efe78253dfe16f23c0b000000000000000f0000000c00000045bd083f7785ee3e0000000000000000000000000b0000000000000000000000f53d043f3b70f13e7d7b423c00000000000000000b0000000c0000000000000007eb4e3f51012e3e9d94b23c00000000000000000b0000000f00000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f00000000000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b000000000000004440f83e7853e33e2fbc283ddd4bf53c0f000000000000000b0000001000000038212d3fb4e7923edeae163d000000000f0000000000000010000000000000004440f83e7853e33e2fbc283ddd4bf53c0f000000000000000b0000001000000068780b3f300fe93e0000000000000000000000000f00000000000000000000006015053f9a67ef3ebfb44d3c00000000000000000f000000100000000000000068780b3f300fe93e0000000000000000000000000f0000000000000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f00000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f000000000000002f9b503f73d3263e7efeb53c00000000000000000f0000000b00000000000000b9fd023f8e04fa3e00000000000000000c0000000b0000000000000000000000322e4d3f83db3a3e9d5d833c000000000c0000000b0000000000000000000000b95f3f3f1b6a543e5caedd3cbe09933c0c0000000d0000000e0000000b0000000dfb5d3f0552f73db9ac463c000000000d0000000c0000000e00000000000000ee78033f240ef93e00000000000000000b0000000c0000000000000000000000b9fd023f8e04fa3e00000000000000000c0000000b00000000000000000000005c552c3f2f97933ebff01d3d000000000b000000000000000c00000000000000d072473f6314323e1eaac23cba58be3c0c0000000d0000000e0000000b000000b95f3f3f1b6a543e5caedd3cbe09933c0c0000000d0000000e0000000b0000009080523f417f213efbf3a33c000000000b0000000c0000000000000000000000ee78033f240ef93e00000000000000000b0000000c000000000000000000000095fe603f8f05c33db7267e3c7b072a3c0d0000000c0000000b0000000e000000d072473f6314323e1eaac23cba58be3c0c0000000d0000000e0000000b000000322e4d3f83db3a3e9d5d833c000000000c0000000b00000000000000000000009080523f417f213efbf3a33c000000000b0000000c00000000000000000000000dfb5d3f0552f73db9ac463c000000000d0000000c0000000e0000000000000095fe603f8f05c33db7267e3c7b072a3c0d0000000c0000000b0000000e0000004b78523f5086213e20c4a43c000000000f000000100000000000000000000000b476033f9812f93e00000000000000000f000000100000000000000000000000b772473f4937323e7fa6c13c6148be3c1000000011000000120000000f0000002f9b503f73d3263e7efeb53c00000000000000000f0000000b00000000000000b772473f4937323e7fa6c13c6148be3c1000000011000000120000000f000000b476033f9812f93e00000000000000000f00000010000000000000000000000048fc023f7007fa3e0000000000000000100000000f000000000000000000000045623f3fcf42543e7c95de3c5b0b933c1000000011000000120000000f00000048fc023f7007fa3e0000000000000000100000000f00000000000000000000006c334d3faec43a3efe6c833c00000000100000000f000000000000000000000038212d3fb4e7923edeae163d000000000f000000000000001000000000000000b5c35d3f2541f83d7e094d3c00000000110000001000000012000000000000006c334d3faec43a3efe6c833c00000000100000000f00000000000000000000004b78523f5086213e20c4a43c000000000f0000001000000000000000000000006015053f9a67ef3ebfb44d3c00000000000000000f0000001000000000000000c4cd413fefc8783e00000000000000000600000007000000000000000000000019544f3f9baf423e00000000000000000700000006000000000000000000000064573a3f37518b3e000000000000000006000000070000000000000000000000e90a563f5ad4273e00000000000000000700000006000000000000000000000019544f3f9baf423e00000000000000000700000006000000000000000000000024de713fc01d623d000000000000000007000000060000000000000000000000e90a563f5ad4273e000000000000000007000000060000000000000000000000b3b2553f3335293e0000000000000000070000000600000000000000000000000135593ffe2b1b3e00000000000000000a0000000900000000000000000000005c734b3f9032523e00000000000000000a0000000900000000000000000000001daa593f8a57193e00000000000000000a0000000900000000000000000000008f09713f0e676f3d00000000000000000a0000000900000000000000000000000135593ffe2b1b3e00000000000000000a00000009000000000000000000000088f6393ff1128c3e0000000000000000090000000a0000000000000000000000be66593f06651a3e00000000000000000a0000000900000000000000000000005c734b3f9032523e00000000000000000a0000000900000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000700000000000000000000000000000024de713fc01d623d0000000000000000070000000600000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a000000000000000000000000000000be66593f06651a3e00000000000000000a0000000900000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000953c6e3f6e01193d3f35033d000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000b5e56d3f2dea2b3dfc74eb3c000000000d0000000c0000000e00000000000000953c6e3f6e01193d3f35033d000000000d0000000c0000000e000000000000003625613f5885c23d81747d3c4113253c11000000100000000f0000001200000085f0243f40e8593eab55123e000000001100000010000000120000000000000045623f3fcf42543e7c95de3c5b0b933c1000000011000000120000000f000000e2752d3fcf103e3ea9170c3e000000001100000010000000120000000000000085f0243f40e8593eab55123e0000000011000000100000001200000000000000b5c35d3f2541f83d7e094d3c000000001100000010000000120000000000000031d36c3fee31353dfc35fb3c0000000011000000100000001200000000000000e2752d3fcf103e3ea9170c3e00000000110000001000000012000000000000003625613f5885c23d81747d3c4113253c11000000100000000f000000120000008a296f3f6ef7113ddbdff63c0000000011000000100000001200000000000000b5e56d3f2dea2b3dfc74eb3c000000000d0000000c0000000e000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c0000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c000000000000009e53783f3f8cf53c00000000000000000d0000000e000000000000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c0000000000000030b7783f001ae93c00000000000000000d0000000e000000000000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000008a296f3f6ef7113ddbdff63c000000001100000010000000120000000000000074b6613f6f3dc83dbd3ba83c0000000012000000110000001000000000000000688a773f7f59073d000000000000000011000000120000000000000000000000f658673f06f1a63d383a723c000000001200000011000000100000000000000031d36c3fee31353dfc35fb3c0000000011000000100000001200000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000688a773f7f59073d000000000000000011000000120000000000000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000705a793ffeb1d43c00000000000000001100000012000000000000000000000001447d3fbdff2e3c00000000000000001200000011000000000000000000000043af793f9b17ca3c000000000000000012000000110000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d000000000000000000000079387d3fbbe1313c00000000000000000e0000000d000000000000000000000074b6613f6f3dc83dbd3ba83c000000001200000011000000100000000000000074b6613f6f3dc83dbd3ba83c00000000120000001100000010000000000000000000803f000000000000000000000000120000000000000000000000000000000000803f0000000000000000000000001200000000000000000000000000000079387d3fbbe1313c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e0000000000000000000000000000000000803f0000000000000000000000000e0000000000000000000000000000001368793f9cfdd23c0000000000000000120000001100000000000000000000000000803f0000000000000000000000000e000000000000000000000000000000e16c793fdb63d23c00000000000000000e0000000d0000000000000000000000e2752d3fcf103e3ea9170c3e000000001100000010000000120000000000000043af793f9b17ca3c0000000000000000120000001100000000000000000000001368793f9cfdd23c0000000000000000120000001100000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000e16c793fdb63d23c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e00000000000000000000000000000079387d3fbbe1313c00000000000000000e0000000d0000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d000000000000000000000043af793f9b17ca3c00000000000000001200000011000000000000000000000001447d3fbdff2e3c0000000000000000120000001100000000000000000000000000803f000000000000000000000000120000000000000000000000000000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000009276033fdc12f93e0000000000000000020000000800000000000000000000004702fc3e643adb3e500da33d00000000020000000300000008000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006476023f3813fb3e000000000000000002000000050000000000000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000657f5a3f24d2d63de138e23cbc23653c030000000200000004000000050000004d6d2c3fb9de2d3e9959123ebb27613c02000000030000000800000005000000e6c41e3ffaa1a13ee850833d0000000003000000040000000200000000000000de3c593f890c1b3e000000000000000004000000030000000000000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000007271523fded8153e6e85013d00000000030000000400000002000000000000000ee64e3f9f06ec3d20a1653d7ce1a73c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000002028033fc0aff93e0000000000000000050000000200000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000006c06fd3e20ecf93e3ed7903c0000000005000000020000000300000000000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d217023f5bd0fb3e000000000000000008000000020000000000000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000102c0c3fa119963ee44ce53d24d8413d020000000100000000000000030000002028033fc0aff93e0000000000000000050000000200000000000000000000006c06fd3e20ecf93e3ed7903c0000000005000000020000000300000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000d217023f5bd0fb3e0000000000000000080000000200000000000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006476023f3813fb3e000000000000000002000000050000000000000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000f627253fb9a9413e263a1b3e80c4673c0200000003000000050000000800000081b15e3ffc39053e0000000000000000040000000300000000000000000000000dab673f99a7c23d0000000000000000040000000300000000000000000000000dab673f99a7c23d0000000000000000040000000300000000000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000de3c593f890c1b3e0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c0000000003000000040000000200000000000000e6c41e3ffaa1a13ee850833d00000000030000000400000002000000000000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000e6c41e3ffaa1a13ee850833d000000000300000004000000020000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000045bd083f7785ee3e0000000000000000000000000b000000000000000000000045bd083f7785ee3e0000000000000000000000000b0000000000000000000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b00000000000000b3b2553f3335293e0000000000000000070000000600000000000000000000008f09713f0e676f3d00000000000000000a0000000900000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000009e53783f3f8cf53c00000000000000000d0000000e00000000000000000000009e53783f3f8cf53c00000000000000000d0000000e0000000000000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000688a773f7f59073d00000000000000001100000012000000000000000000000001447d3fbdff2e3c0000000000000000120000001100000000000000000000000000803f0000000000000000000000001200000000000000000000000000000085f0243f40e8593eab55123e0000000011000000100000001200000000000000e2752d3fcf103e3ea9170c3e00000000110000001000000012000000000000001368793f9cfdd23c000000000000000012000000110000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d00000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e00000000000000e16c793fdb63d23c00000000000000000e0000000d0000000000000000000000e16c793fdb63d23c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e000000000000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d00000000000000000000001368793f9cfdd23c00000000000000001200000011000000000000000000000043af793f9b17ca3c0000000000000000120000001100000000000000000000000000803f00000000000000000000000012000000000000000000000000000000 + m_CompressedMesh: + m_Vertices: + m_NumItems: 0 + m_Range: 0 + m_Start: 0 + m_Data: + m_BitSize: 0 + m_UV: + m_NumItems: 0 + m_Range: 0 + m_Start: 0 + m_Data: + m_BitSize: 0 + m_Normals: + m_NumItems: 0 + m_Range: 0 + m_Start: 0 + m_Data: + m_BitSize: 0 + m_Tangents: + m_NumItems: 0 + m_Range: 0 + m_Start: 0 + m_Data: + m_BitSize: 0 + m_Weights: + m_NumItems: 0 + m_Data: + m_BitSize: 0 + m_NormalSigns: + m_NumItems: 0 + m_Data: + m_BitSize: 0 + m_TangentSigns: + m_NumItems: 0 + m_Data: + m_BitSize: 0 + m_FloatColors: + m_NumItems: 0 + m_Range: 0 + m_Start: 0 + m_Data: + m_BitSize: 0 + m_BoneIndices: + m_NumItems: 0 + m_Data: + m_BitSize: 0 + m_Triangles: + m_NumItems: 0 + m_Data: + m_BitSize: 0 + m_UVInfo: 0 + m_LocalAABB: + m_Center: {x: 0.00000020861626, y: 0.7249603, z: 0.032029606} + m_Extent: {x: 0.58946085, y: 0.7249602, z: 0.1629476} + m_MeshUsageFlags: 0 + m_BakedConvexCollisionMesh: + m_BakedTriangleCollisionMesh: + m_MeshMetrics[0]: 1 + m_MeshMetrics[1]: 1 + m_MeshOptimizationFlags: 1 + m_StreamData: + offset: 0 + size: 0 + path: diff --git a/Assets/MeshesIntegrated.mesh.asset.meta b/Assets/MeshesIntegrated.mesh.asset.meta new file mode 100644 index 000000000..d4674ae61 --- /dev/null +++ b/Assets/MeshesIntegrated.mesh.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48cadfe261b960249b58f8eac1fe35d4 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4300000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs deleted file mode 100644 index 897bfad0e..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace UniGLTF.MeshUtility -{ - [CustomEditor(typeof(MeshProcessDialog), true)] - public class BoneMeshEraserGUI : Editor - { - public override void OnInspectorGUI() - { - serializedObject.Update(); - var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); - EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); - var list = serializedObject.FindProperty("_eraseBones"); - EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 2183e0180..a5a4c97e7 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -9,16 +9,12 @@ namespace UniGLTF.MeshUtility { public class MeshProcessDialog : EditorWindow { - enum Tabs - { - MeshSeparator, - MeshIntegrator, - BoneMeshEraser, - } private Tabs _tab; private GameObject _exportTarget; - private Editor _boneMeshEraserEditor; + + private MeshProcessDialogEditor _boneMeshEraserEditor; + private SkinnedMeshRenderer _pSkinnedMesh; private Animator _pAnimator; private Transform _pEraseRoot; @@ -27,6 +23,9 @@ namespace UniGLTF.MeshUtility [SerializeField] private SkinnedMeshRenderer _cSkinnedMesh = null; + [SerializeField] + private bool _separateByBlendShape = true; + private Animator _cAnimator = null; private Transform _cEraseRoot = null; @@ -51,7 +50,7 @@ namespace UniGLTF.MeshUtility { if (!_boneMeshEraserEditor) { - _boneMeshEraserEditor = Editor.CreateEditor(this); + _boneMeshEraserEditor = (MeshProcessDialogEditor)Editor.CreateEditor(this); } } @@ -63,7 +62,7 @@ namespace UniGLTF.MeshUtility private void OnGUI() { _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); - EditorGUIUtility.labelWidth = 150; + EditorGUIUtility.labelWidth = 300; // lang LanguageGetter.OnGuiSelectLang(); @@ -90,11 +89,17 @@ namespace UniGLTF.MeshUtility case Tabs.MeshIntegrator: EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); - processed = TabMeshIntegrator.OnGUI(_exportTarget); + _boneMeshEraserEditor.Tabs = _tab; + if (_boneMeshEraserEditor) + { + _boneMeshEraserEditor.OnInspectorGUI(); + } + processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); break; case Tabs.BoneMeshEraser: EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); + _boneMeshEraserEditor.Tabs = _tab; if (_boneMeshEraserEditor) { _boneMeshEraserEditor.OnInspectorGUI(); diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs new file mode 100644 index 000000000..db7929a0a --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs @@ -0,0 +1,36 @@ +using UniGLTF.M17N; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + [CustomEditor(typeof(MeshProcessDialog), true)] + class MeshProcessDialogEditor : Editor + { + public Tabs Tabs; + + public override void OnInspectorGUI() + { + serializedObject.Update(); + switch (Tabs) + { + case Tabs.MeshIntegrator: + { + var skinnedMesh = serializedObject.FindProperty("_separateByBlendShape"); + EditorGUILayout.PropertyField(skinnedMesh, new GUIContent(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg())); + break; + } + + case Tabs.BoneMeshEraser: + { + var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); + EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); + var list = serializedObject.FindProperty("_eraseBones"); + EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); + break; + } + } + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs.meta similarity index 83% rename from Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta rename to Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs.meta index eddf8f87d..de1678682 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5cdbec3de528c61448aeb739ffe1f79e +guid: 04fa1873cf1c0374aab1670a24d741b5 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs index b30c05c8e..3b63cc538 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs @@ -20,17 +20,22 @@ namespace UniGLTF.MeshUtility ")] MESH_SEPARATOR, - [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュを統合します。BlendShape の有無で2つ作成されます。 + + [LangMsg(Languages.ja, "ブレンドシェイプの有無で分割する")] + [LangMsg(Languages.en, "Divide by the presence or absence of `blendshape`")] + MESH_SEPARATOR_BY_BLENDSHAPE, + + [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュを統合します。 * Asset: Assets/MeshIntegrated.mesh が作成されます(上書きされるので注意してください)。 * Scene: コピーされたヒエラルキーでは、統合された Mesh は除去されます。新しく MeshIntegrator ノードが追加されます。 -* VRMではBlendShapeClipの統合など追加の処理が必要でる。VRMの統合機能を使ってください。 +* VRMではBlendShapeClipの統合など追加の処理が必要です。`VRM0-MeshIntegratorWizard` を使ってください。 ")] - [LangMsg(Languages.en, @"Integrates the attached mesh into the SkinnedMeshRenderer or MeshFilter under the target object. A mesh that holds BlendShape and a mesh that does not hold BlendShape are created. + [LangMsg(Languages.en, @"Integrates the attached mesh into the SkinnedMeshRenderer or MeshFilter under the target object. * Asset: Assets/MeshIntegrated.mesh is created (note that it will be overwritten). * Scene: In the copied hierarchy, the integrated mesh is removed. A new MeshIntegrator node is added. -* VRM requires additional processing such as BlendShapeClip integration. Use the VRM integration feature. +* VRM requires additional processing such as BlendShapeClip integration. Use the `VRM0-MeshIntegratorWizard` integration feature. ")] MESH_INTEGRATOR, diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 209437698..ed366f531 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -9,7 +9,7 @@ namespace UniGLTF.MeshUtility { const string ASSET_SUFFIX = ".mesh.asset"; - public static bool OnGUI(GameObject root) + public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -18,7 +18,7 @@ namespace UniGLTF.MeshUtility GUILayout.FlexibleSpace(); if (GUILayout.Button("Process", GUILayout.MinWidth(100))) { - _isInvokeSuccess = TabMeshIntegrator.Execute(root); + _isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers); } GUILayout.EndHorizontal(); } @@ -42,7 +42,7 @@ namespace UniGLTF.MeshUtility return false; } - static bool Execute(GameObject root) + static bool Execute(GameObject root, bool onlyBlendShapeRenderers) { if (root == null) { @@ -62,8 +62,15 @@ namespace UniGLTF.MeshUtility return false; } - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: true); - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: false); + if (onlyBlendShapeRenderers) + { + MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape); + MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape); + } + else + { + MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All); + } CopyAndSaveAssetEtc(root); diff --git a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs b/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs new file mode 100644 index 000000000..dbc064734 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs @@ -0,0 +1,9 @@ +namespace UniGLTF.MeshUtility +{ + enum Tabs + { + MeshSeparator, + MeshIntegrator, + BoneMeshEraser, + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta new file mode 100644 index 000000000..485c04f70 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57ace5e28eb8e7746b00eaa9405197a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs new file mode 100644 index 000000000..a4021e5a7 --- /dev/null +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs @@ -0,0 +1,9 @@ +namespace UniGLTF.MeshUtility +{ + public enum MeshEnumerateOption + { + OnlyWithBlendShape, + OnlyWithoutBlendShape, + All, + } +} diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs.meta b/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs.meta new file mode 100644 index 000000000..566aaa57a --- /dev/null +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshEnumerateOption.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 862f202d0be779744a4954a77cb88a89 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index 569fa4bdf..4e2db9cdb 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -230,7 +230,7 @@ namespace UniGLTF.MeshUtility } } - public void Intgrate(bool onlyBlendShapeRenderers) + public void Intgrate(MeshEnumerateOption onlyBlendShapeRenderers) { var mesh = new Mesh(); @@ -252,24 +252,36 @@ namespace UniGLTF.MeshUtility } mesh.bindposes = BindPoses.ToArray(); - if (onlyBlendShapeRenderers) + switch (onlyBlendShapeRenderers) { - AddBlendShapesToMesh(mesh); - mesh.name = INTEGRATED_MESH_BLENDSHAPE_NAME; - } - else - { - mesh.name = INTEGRATED_MESH_NAME; + case MeshEnumerateOption.OnlyWithBlendShape: + { + AddBlendShapesToMesh(mesh); + mesh.name = INTEGRATED_MESH_BLENDSHAPE_NAME; + break; + } + case MeshEnumerateOption.OnlyWithoutBlendShape: + case MeshEnumerateOption.All: + { + mesh.name = INTEGRATED_MESH_NAME; + break; + } } var meshNode = new GameObject(); - if (onlyBlendShapeRenderers) + switch (onlyBlendShapeRenderers) { - meshNode.name = "MeshIntegrator(BlendShape)"; - } - else - { - meshNode.name = "MeshIntegrator"; + case MeshEnumerateOption.OnlyWithBlendShape: + { + meshNode.name = "MeshIntegrator(BlendShape)"; + break; + } + case MeshEnumerateOption.OnlyWithoutBlendShape: + case MeshEnumerateOption.All: + { + meshNode.name = "MeshIntegrator"; + break; + } } var integrated = meshNode.AddComponent(); diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index 48bffe5fe..87f44f189 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -8,48 +8,83 @@ namespace UniGLTF.MeshUtility public static string INTEGRATED_MESH_NAME => MeshIntegrator.INTEGRATED_MESH_NAME; public static string INTEGRATED_MESH_BLENDSHAPE_NAME => MeshIntegrator.INTEGRATED_MESH_BLENDSHAPE_NAME; + /// /// go を root としたヒエラルキーから Renderer を集めて、統合された Mesh 作成する /// /// - /// BlendShapeを保持するSkinnedMeshRendererのみ/BlendShapeを保持しないSkinnedMeshRenderer + MeshRenderer + /// + /// true: BlendShapeを保持するSkinnedMeshRendererのみ + /// false: BlendShapeを保持しないSkinnedMeshRenderer + MeshRenderer + /// null: すべてのSkinnedMeshRenderer + MeshRenderer + /// /// - public static MeshIntegrationResult Integrate(GameObject go, bool onlyBlendShapeRenderers, IEnumerable excludes = null) + public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption onlyBlendShapeRenderers, IEnumerable excludes = null) { var exclude = new MeshExclude(excludes); var integrator = new MeshUtility.MeshIntegrator(); - if (onlyBlendShapeRenderers) + switch (onlyBlendShapeRenderers) { - foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, true)) - { - if (exclude.IsExcluded(x)) + case MeshEnumerateOption.OnlyWithBlendShape: { - continue; + foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers)) + { + if (exclude.IsExcluded(x)) + { + continue; + } + integrator.Push(x); + } + break; } - integrator.Push(x); - } - } - else - { - foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, false)) - { - if (exclude.IsExcluded(x)) - { - continue; - } - integrator.Push(x); - } - foreach (var x in EnumerateMeshRenderer(go.transform)) - { - if (exclude.IsExcluded(x)) + case MeshEnumerateOption.OnlyWithoutBlendShape: { - continue; + foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers)) + { + if (exclude.IsExcluded(x)) + { + continue; + } + integrator.Push(x); + } + + foreach (var x in EnumerateMeshRenderer(go.transform)) + { + if (exclude.IsExcluded(x)) + { + continue; + } + integrator.Push(x); + } + + break; + } + + case MeshEnumerateOption.All: + { + foreach (var x in EnumerateSkinnedMeshRenderer(go.transform, onlyBlendShapeRenderers)) + { + if (exclude.IsExcluded(x)) + { + continue; + } + integrator.Push(x); + } + + foreach (var x in EnumerateMeshRenderer(go.transform)) + { + if (exclude.IsExcluded(x)) + { + continue; + } + integrator.Push(x); + } + + break; } - integrator.Push(x); - } } integrator.Intgrate(onlyBlendShapeRenderers); @@ -57,7 +92,7 @@ namespace UniGLTF.MeshUtility return integrator.Result; } - public static IEnumerable EnumerateSkinnedMeshRenderer(Transform root, bool hasBlendShape) + public static IEnumerable EnumerateSkinnedMeshRenderer(Transform root, MeshEnumerateOption hasBlendShape) { foreach (var x in Traverse(root)) { @@ -65,10 +100,30 @@ namespace UniGLTF.MeshUtility if (renderer != null && renderer.gameObject.activeInHierarchy && renderer.sharedMesh != null && - renderer.enabled && - renderer.sharedMesh.blendShapeCount > 0 == hasBlendShape) + renderer.enabled) { - yield return renderer; + switch (hasBlendShape) + { + case MeshEnumerateOption.OnlyWithBlendShape: + if (renderer.sharedMesh.blendShapeCount > 0) + { + yield return renderer; + } + break; + + case MeshEnumerateOption.OnlyWithoutBlendShape: + if (renderer.sharedMesh.blendShapeCount == 0) + { + yield return renderer; + } + break; + + case MeshEnumerateOption.All: + { + yield return renderer; + break; + } + } } } } diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs index 9a1df032a..4ef7304cb 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs @@ -138,7 +138,7 @@ namespace VRM } Debug.Log("OnValidate"); - m_uniqueMaterials = MeshIntegratorUtility.EnumerateSkinnedMeshRenderer(m_root.transform, false) + m_uniqueMaterials = MeshIntegratorUtility.EnumerateSkinnedMeshRenderer(m_root.transform, MeshEnumerateOption.OnlyWithoutBlendShape) .SelectMany(x => x.sharedMaterials) .Distinct() .ToArray(); diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index 81f61e0d5..d00cf8b78 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -43,13 +43,13 @@ namespace VRM { var result = new List(); - var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: false, excludes: excludes); + var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); if (withoutBlendShape.IntegratedRenderer != null) { result.Add(withoutBlendShape); } - var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: true, excludes: excludes); + var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); if (onlyBlendShape.IntegratedRenderer != null) { result.Add(onlyBlendShape); From d4cb75852c6f992f8c9181a16540e9297b3be673 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 12 May 2022 14:50:22 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86=E3=80=82m=5FseparateByBlendShape=E3=80=80=E3=82=AA?= =?UTF-8?q?=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3(default:=20true=E3=81=8C?= =?UTF-8?q?=E5=89=8D=E3=81=A8=E5=90=8C=E3=81=98=E6=8C=99=E5=8B=95)?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/MeshesIntegrated.mesh.asset | 507 ------------------ Assets/MeshesIntegrated.mesh.asset.meta | 8 - .../MeshIntegratorEditor.cs | 146 ----- .../SkinnedMeshUtility/SkinnedMeshUtility.cs | 59 -- .../SkinnedMeshUtility.cs.meta | 3 - ...orWizard.cs => VrmMeshIntegratorWizard.cs} | 130 ++++- ...s.meta => VrmMeshIntegratorWizard.cs.meta} | 4 +- .../SkinnedMeshUtility/VrmPrefabUtility.cs | 105 ++++ ...ditor.cs.meta => VrmPrefabUtility.cs.meta} | 4 +- Assets/VRM/Editor/VrmTopMenu.cs | 2 +- .../VRMMeshIntegratorUtility.cs | 57 +- 11 files changed, 238 insertions(+), 787 deletions(-) delete mode 100644 Assets/MeshesIntegrated.mesh.asset delete mode 100644 Assets/MeshesIntegrated.mesh.asset.meta delete mode 100644 Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs delete mode 100644 Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs delete mode 100644 Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs.meta rename Assets/VRM/Editor/SkinnedMeshUtility/{MeshIntegratorWizard.cs => VrmMeshIntegratorWizard.cs} (58%) rename Assets/VRM/Editor/SkinnedMeshUtility/{MeshIntegratorWizard.cs.meta => VrmMeshIntegratorWizard.cs.meta} (71%) create mode 100644 Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs rename Assets/VRM/Editor/SkinnedMeshUtility/{MeshIntegratorEditor.cs.meta => VrmPrefabUtility.cs.meta} (71%) diff --git a/Assets/MeshesIntegrated.mesh.asset b/Assets/MeshesIntegrated.mesh.asset deleted file mode 100644 index 512a17b1f..000000000 --- a/Assets/MeshesIntegrated.mesh.asset +++ /dev/null @@ -1,507 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!43 &4300000 -Mesh: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: MeshesIntegrated.mesh - serializedVersion: 10 - m_SubMeshes: - - serializedVersion: 2 - firstByte: 0 - indexCount: 768 - topology: 0 - baseVertex: 0 - firstVertex: 0 - vertexCount: 453 - localAABB: - m_Center: {x: 0.00000020861626, y: 0.7249603, z: 0.032029606} - m_Extent: {x: 0.58946085, y: 0.7249602, z: 0.1629476} - m_Shapes: - vertices: [] - shapes: [] - channels: [] - fullWeights: [] - m_BindPose: - - e00: 0.99998313 - e01: -0.0058136694 - e02: 0.00044683862 - e03: 0.003988234 - e10: 0.005830814 - e11: 0.99710566 - e12: -0.0758053 - e13: -0.6840148 - e20: -0.000004838265 - e21: 0.07580492 - e22: 0.99714476 - e23: -0.0520032 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 1.0000001 - e01: -0.00000041014468 - e02: 0.000022655031 - e03: 0.0000006004789 - e10: 0.00000009841655 - e11: 0.9999053 - e12: 0.013758672 - e13: -0.8567405 - e20: -0.00002265803 - e21: -0.013758366 - e22: 0.9999275 - e23: 0.02479167 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 1.0000001 - e01: -0.000000010809315 - e02: -0.0000027871315 - e03: -0.00000025579496 - e10: 0.0000005673888 - e11: 0.979841 - e12: 0.19978324 - e13: -1.0513293 - e20: 0.0000027287256 - e21: -0.19977877 - e22: 0.97986287 - e23: 0.22455975 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 1.0000001 - e01: -0.00000012436698 - e02: 0.0000054645266 - e03: 0.0000000549877 - e10: 0.0000000833747 - e11: 0.99997187 - e12: 0.0075012175 - e13: -1.1264704 - e20: -0.0000054651855 - e21: -0.0075010513 - e22: 0.99999404 - e23: 0.007969917 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -1.0000001 - e01: 0.00000006111686 - e02: 0.0000015178592 - e03: 0.0000000021680735 - e10: 0.00000005557859 - e11: 0.99999356 - e12: -0.0036486278 - e13: -1.1929911 - e20: -0.0000015180384 - e21: -0.0036485475 - e22: -1.0000156 - e23: 0.005353814 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.062392827 - e01: 0.005693435 - e02: 0.99805737 - e03: -0.0016267168 - e10: -0.8915193 - e11: -0.4498517 - e12: -0.053168807 - e13: 0.40415704 - e20: 0.44866517 - e21: -0.89308506 - e22: 0.03314401 - e23: 0.9989868 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.5302006 - e01: -0.0017470117 - e02: 0.8478889 - e03: 0.18342696 - e10: -0.760035 - e11: -0.44421852 - e12: 0.4743695 - e13: 0.20656405 - e20: 0.37581098 - e21: -0.8959166 - e22: -0.23685805 - e23: 0.97321355 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.6314424 - e01: 0.0041904435 - e02: 0.7754282 - e03: 0.22815786 - e10: -0.64927876 - e11: -0.5438431 - e12: 0.53167975 - e13: 0.15465824 - e20: 0.42393002 - e21: -0.83917594 - e22: -0.34069243 - e23: 0.9514504 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.11570896 - e01: 0.09731569 - e02: 0.9885267 - e03: -0.10564935 - e10: 0.86856437 - e11: -0.49271676 - e12: -0.053163834 - e13: 0.45235664 - e20: 0.4818793 - e21: 0.86473095 - e22: -0.14153978 - e23: -0.978427 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.0705073 - e01: -0.78196716 - e02: -0.61933315 - e03: 0.76114917 - e10: 0.76003367 - e11: -0.4442222 - e12: 0.47436923 - e13: 0.20656744 - e20: -0.6460482 - e21: -0.43725756 - e22: 0.6256562 - e23: 0.63359594 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.11137952 - e01: -0.6235332 - e02: -0.7738399 - e03: 0.55021447 - e10: 0.64928055 - e11: -0.5438397 - e12: 0.5316826 - e13: 0.15465552 - e20: -0.7523496 - e21: -0.561645 - e22: 0.3442828 - e23: 0.8090615 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.8304809 - e01: -0.09163624 - e02: -0.549484 - e03: 0.00030874347 - e10: -0.033970688 - e11: -0.97621197 - e12: 0.21415916 - e13: 0.59686774 - e20: -0.55601645 - e21: 0.1965135 - e22: 0.8076394 - e23: -0.15930209 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.99973345 - e01: 0.0000712631 - e02: 0.023235448 - e03: -0.07843342 - e10: -0.0051243966 - e11: -0.97604984 - e12: -0.21750544 - e13: 0.35795337 - e20: 0.022662591 - e21: -0.21755776 - e22: 0.9758227 - e23: 0.022222105 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.9993303 - e01: 0.00000014435534 - e02: 0.036683597 - e03: -0.07836859 - e10: 0.02870476 - e11: -0.622619 - e12: 0.7820302 - e13: 0.05673951 - e20: 0.022839148 - e21: 0.78252804 - e22: 0.62222296 - e23: -0.06347845 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.9940157 - e01: -0.00042184885 - e02: 0.10927121 - e03: 0.07555784 - e10: 0.10925592 - e11: 0.018802257 - e12: -0.9938745 - e13: 0.04058164 - e20: -0.0016352328 - e21: 0.99982494 - e22: 0.018736433 - e23: -0.022736017 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.9946902 - e01: -0.012200378 - e02: 0.10219161 - e03: 0.0750665 - e10: 0.03397443 - e11: -0.97620946 - e12: 0.21415551 - e13: 0.59686655 - e20: 0.09714545 - e21: 0.2164853 - e22: 0.9714627 - e23: -0.14050381 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.99817085 - e01: 0.00810431 - e02: -0.059908763 - e03: 0.07754238 - e10: 0.0051283613 - e11: -0.9760492 - e12: -0.21749379 - e13: 0.3579512 - e20: -0.060235165 - e21: -0.21739827 - e22: 0.9742449 - e23: 0.025155144 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: -0.99932635 - e01: -0.035765577 - e02: 0.008291565 - e03: 0.08149831 - e10: 0.02874168 - e11: -0.62159574 - e12: 0.7828291 - e13: 0.052144762 - e20: -0.022843808 - e21: 0.7825217 - e22: 0.62221843 - e23: -0.06347658 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - - e00: 0.99401116 - e01: -0.00048218702 - e02: -0.109282345 - e03: -0.07553721 - e10: -0.10925147 - e11: 0.018809272 - e12: -0.9938595 - e13: 0.040580485 - e20: 0.0025346808 - e21: 0.9998237 - e22: 0.018644353 - e23: -0.02280339 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_BoneNameHashes: - m_RootBoneNameHash: 0 - m_BonesAABB: - - m_Min: {x: -0.12132926, y: -0.3321573, z: -0.10399473} - m_Max: {x: 0.12293162, y: 0.3478911, z: 0.11866063} - - m_Min: {x: -0.09366471, y: 0.16117442, z: -0.08289033} - m_Max: {x: 0.093665116, y: 0.27041388, z: 0.10442592} - - m_Min: {x: -0.13091865, y: -0.07128954, z: -0.19338548} - m_Max: {x: 0.13091813, y: 0.34320712, z: 0.11548869} - - m_Min: {x: -0.13091889, y: -0.106496334, z: -0.13382383} - m_Max: {x: 0.13091865, y: 0.32439137, z: 0.12997614} - - m_Min: {x: -0.13091815, y: -0.0053960085, z: -0.13085672} - m_Max: {x: 0.13091832, y: 0.25739765, z: 0.13193926} - - m_Min: {x: -0.09514809, y: -0.143085, z: -0.08232039} - m_Max: {x: 0.1019532, y: 0.24670334, z: 0.1275838} - - m_Min: {x: -0.053297207, y: -0.027800113, z: -0.050008178} - m_Max: {x: 0.065450795, y: 0.22947535, z: 0.048172534} - - m_Min: {x: -0.05853103, y: -0.17048313, z: -0.055241168} - m_Max: {x: 0.064517915, y: 0.19430375, z: 0.040798068} - - m_Min: {x: -0.104298025, y: -0.13671392, z: -0.036469102} - m_Max: {x: 0.105109304, y: 0.24834424, z: 0.13055974} - - m_Min: {x: -0.066080034, y: -0.027800724, z: -0.060244143} - m_Max: {x: 0.0595662, y: 0.22947536, z: 0.06067574} - - m_Min: {x: -0.06880224, y: -0.1704818, z: -0.058241367} - m_Max: {x: 0.05276963, y: 0.19430572, z: 0.0751766} - - m_Min: {x: -0.12889893, y: -0.050486565, z: -0.15093169} - m_Max: {x: 0.09793951, y: 0.50948244, z: 0.115712374} - - m_Min: {x: -0.055570632, y: -0.25439042, z: -0.2010099} - m_Max: {x: 0.04680603, y: 0.34948346, z: 0.06299932} - - m_Min: {x: -0.040597796, y: -0.045691475, z: -0.117564246} - m_Max: {x: 0.06031075, y: 0.19206639, z: 0.078671955} - - m_Min: {x: -0.04586801, y: -0.1506767, z: -0.024211802} - m_Max: {x: 0.042569388, y: 0.11740069, z: 0.08117606} - - m_Min: {x: -0.06396452, y: -0.05048579, z: -0.1550012} - m_Max: {x: 0.09857974, y: 0.50948185, z: 0.10985528} - - m_Min: {x: -0.04842049, y: -0.25439093, z: -0.20234244} - m_Max: {x: 0.0558579, y: 0.34948236, z: 0.06440397} - - m_Min: {x: -0.049950972, y: -0.04355136, z: -0.11756235} - m_Max: {x: 0.042991817, y: 0.19521084, z: 0.07867251} - - m_Min: {x: -0.042641893, y: -0.15067479, z: -0.024212375} - m_Max: {x: 0.04581874, y: 0.11739859, z: 0.081212334} - m_VariableBoneCountWeights: - m_Data: - m_MeshCompression: 0 - m_IsReadable: 1 - m_KeepVertices: 0 - m_KeepIndices: 0 - m_IndexFormat: 0 - m_IndexBuffer: 0200010000000500040003000900080006000e000d000b001400120011001900170016001c001b001a001f001e001d002300220020002700250024002b002a0029002f002e002d0034003200310034002c0023003800370035003c0024003a003f003e0024004000430042004600450044004900480047004c004b004a004c004e004d00510050004f005400530052005300560055005100580057005b005a0059005a005b005c005f005e005d005e006100600064006300620063006400650046006700660049006900680071006d006b006f00740073007b00790075007e007d00770086008300800085008a00890092008f008c008e009500930099009800960097009b009a00a200a1009d009f00a600a400a900a800a700a800ab00aa00b200b000ac00b600b400af00bd00ba00b800be00c100c000c800c600c200cb00ca00c300cf00ce00cd00d100d000cd00d400d300d200d400d600d500d800d400d700d800d900d600db00da002100dd00d800dc00e000df00de00e300e200e100e600e500e400e800e700d900ea00e9002600ee00ec00eb00f000ef00da00f000f200f100f500f400f300f400f700f600e000f900f800fb00fa00f800fd00fc00e200fd00ff00fe00020101010001e60003010001060105010401e700e80005010901080107010901ea000a010d010c010b010d01ee000e0110010f016600130112011101150114014d001601550056001801170168001b011a0119011d011c0157001e016000610020011f0110012201210112012301140115012501160124012801270126012901170118012b012a011a012d012c011d012f011e012e013201310130013301f100f2003401f600f70036013501fa0038013701fe003a01020139013d013c013b0140013f013e01420141010b0144013301430146014501350148014701370150014d014a0152013a015101540153013f015601420155015c015b0157015f015e015401440161016001640163015901680166014c0169013a0152016b016a0146016e016d016c01710170016f017401730172017701760175017a01790178017d017c017b010a0007007e010f000c007f01130010008001180015008101840183018201870186018501230020003200270024003e002c00280023008a0189018801330030008b01340023003200390036008c013d003b008d013f0024003c003f0041003e00460044006700490047008e014c004a008f014c004d004b0051004f005800540052009001530055005200510057001c015b00590091015a005c0011015f005d0092015e0060005d00640062009301630065001901460066000f0149006800480070006a0094016e0072006c007c00760095017f0078007a0087008200960184008800810091008b009701900094008d009b019a0198019d019c019901a3009e009e01a000a5009c00a900a7009f01a800aa00a700b300ae00a001b500ad00b100bb00b700a101bc00bf00b900c900c400a201cc00c500c700cf00cd00a301d100cd00ce00d400d200d700d400d500d300d800d700dc00d800d600d400db002100a401dd00dc00f500e000de00a501e300e100ed00e600e4000301e800d900d800ea0026000a01ee00eb000e01f000da00db00f000f100ef00f500f300dd00f400f600f300e000f800df00fb00f800f900fd00e200e300fd00fe00fc00020100013901e60000010101060104013b01e70005010601090107013e0109010a0108010d010b0141010d010e010c0110016600a601130111015c0015014d004e001601560024011801680069001b01190165001d015700a7011e0161002e0120011001a60122011201130123011501a80125012401a901ac01ab01aa0129011801ad012b011a011b012d011d01a7012f012e01ae01b101b001af013301f20043013401f700b2013601fa00fb003801fe00ff003a01390151013d013b01040140013e01070142010b01550144014301b3014601350136014801370138014f014901b40152015101b50154013f01400156015501b6015d01580162015f015401400144016001330165015a01b70167014b014e0169015201b8016b0146013601bb01ba01b901be01bd01bc01c101c001bf01c401c301c201 - m_VertexData: - serializedVersion: 3 - m_VertexCount: 453 - m_Channels: - - stream: 0 - offset: 0 - format: 0 - dimension: 3 - - stream: 0 - offset: 12 - format: 0 - dimension: 3 - - stream: 0 - offset: 24 - format: 0 - dimension: 4 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 1 - offset: 0 - format: 0 - dimension: 2 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 0 - offset: 0 - format: 0 - dimension: 0 - - stream: 2 - offset: 0 - format: 0 - dimension: 4 - - stream: 2 - offset: 16 - format: 10 - dimension: 4 - m_DataSize: 36256 - _typelessdata: 80a8bb3dc720903f7ba8bbbda3768b360000803f474410b4dc2f1d2b474410340000803f0000803f7ca8bb3dc620903f8aa8bb3da3768b360000803f474410b4dc2f1d2b474410340000803f0000803f9e272c3dc820903fb0272c3da3768b360000803f474410b4dc2f1d2b474410340000803f0000803f80a8bbbdc620903f7ba8bbbd4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9d272cbdc820903f91272cbd4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9e272cbdc820903fb2272c3d4a4aa1b60000803fd703c1b4da36f3abd703c1340000803f0000803f9e272cbdc820903fb2272c3d000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9e272cbdc820903fb2272c3d000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9d272cbdc820903f91272cbd000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9d272cbd0413983f90272cbd000080bf6549bc3326573eb326573eb392fe8b270000803f0000803f9d272cbd0413983f90272cbd000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9e272c3dc820903fb0272c3d0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9e272c3dc820903fb0272c3d0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf9f272c3d0513983fb2272c3d0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9f272c3d0413983f93272cbd0000803f93b88fb4d81f682ad81f68aa2651821f0000803f000080bf9f272c3d0413983f93272cbd0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf610f06befe96b93f560f06be000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f610f06befe96b93f560f06be000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf600f06beff96b93f6c0f063e000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf5f0f06be0613983f670f063e000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f5f0f06be0613983f670f063e000080bf4f081cb3846d74334f081cb30000803fabfa1427000080bf600f063efe96b93f560f06be0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf600f063efe96b93f560f06be0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f5f0f063e0513983f5e0f06be0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f5e0f063e0513983f670f063e0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf5e0f063e0513983f670f063e0000803fc6be09287b6d7433c6be09a80000803fbd84039c0000803f9d272cbd0413983f90272cbdcc1bf1b5000080bf47441034f1df872a474410340000803f000080bf5f0f06be0513983f5d0f06becc1bf1b5000080bf47441034f1df872a474410340000803f000080bf5f0f06be0613983f670f063ecc1bf1b5000080bf47441034f1df872a474410340000803f000080bf9f272c3d0513983fb2272c3d00000080000080bf546ec9340000803f00000000000000000000803f5e0f063e0513983f670f063e00000080000080bf546ec9340000803f00000000000000000000803f5f0f063e0513983f5e0f06be00000080000080bf546ec9340000803f00000000000000000000803f1deef8bd9818243ff194ce3dd7f37fbf02ce9d3c56f480b636ee80b63dfb9e330000803f0000803f1deef8bd9818243ff194ce3dd8f37fbfe7c69d3c77ec5ab612e25ab61ded86330000803f0000803f1ceef8bd9718243fe294cebd79f37fbf2d29a03ce13e7736c832773611af9ab30000803f0000803f44d2bfbd6d78823f43d2bfbdbab87fbfebfa3e3dd623dfb5b6e5deb54f77a6330000803f0000803f47d2bf3d6e78823f42d2bfbdb9b87f3f52fb3e3dabe9b1b522b8b13516ba84330000803f000080bf1deef83d9618243fe294cebd79f37f3f0329a03c37ee783609e278b6c3bc9bb30000803f000080bf1deef83d9718243ff294ce3dd8f37f3f94c79d3c15825ab6b5775a3620ac86330000803f000080bf1deef83d9718243ff294ce3dd7f37f3fddcd9d3c7aac7cb679a07c36f7c09b330000803f000080bf80a8bbbdc620903f7ba8bbbd1cf47fbfc50a9c3c5758ccb6d94eccb6db1cf9330000803f0000803f80a8bbbdc620903f7ba8bbbd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f5ffebbbdf7068f3fb360aabd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f647cbfbd3b92833facdeadbd1cf47fbf7f0c9c3cc2010e3729fb0d3701202db40000803f0000803f647cbfbd3b92833facdeadbd1ef47fbf30059c3c39fc52b66ef252b6f99580330000803f0000803f80a8bbbdc620903f7ba8bbbd1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f80a8bbbdc720903f8aa8bb3d1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1ef47fbf1efc9b3cd6ce2fb1adc62fb1c03e562e0000803f0000803f80a8bbbdc720903f8aa8bb3d1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f80a8bbbdc720903f8aa8bb3d1cf47fbf230b9c3c418e3835af8538356efd60b20000803f0000803f48d2bfbd6f78823f4bd2bf3db9b87fbf09fc3e3d854e5034851450345b671bb20000803f0000803f687cbfbd3c92833f2089e43c1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f687cbfbd3c92833f2089e43c1ef47fbfc2029c3c36b4a53385aca53334f7c9b00000803f0000803f80a8bb3dc720903f7ba8bbbd1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf80a8bb3dc720903f7ba8bbbd1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf5efebb3df8068f3fb260aabd1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf5efebb3df8068f3f5f91d63c1ef47f3f95fa9b3c1bcd2fb1f2c42f31883a562e0000803f000080bf5efebb3df8068f3f5f91d63c1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf80a8bb3dc720903f7ba8bbbd1cf47f3ffc0a9c3c4bafb0b616a7b036cd64d7330000803f000080bf80a8bb3dc720903f7ba8bbbd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf677cbf3d3c92833faadeadbd1df47f3f53079c3ca2722db6946a2d36a26d53330000803f000080bf677cbf3d3c92833faadeadbd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf48d2bf3d6e78823f49d2bf3db9b87f3f38fc3e3db7699f34543d9fb40adb6db20000803f000080bf677cbf3d3c92833f2289e43c1ef47f3ff0029c3cc14d37343f4537b4f86a5fb10000803f000080bf677cbf3d3c92833f2289e43c1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf7ca8bb3dc620903f8aa8bb3d1df47f3ffa0b9c3c02b74335ecad43b55a996eb20000803f000080bf7ca8bb3dc620903f8aa8bb3d1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf5efebb3df8068f3f5f91d63c1cf47f3f620d9c3ce24240b5f43940359d656a320000803f000080bf5ffebbbdf7068f3fb360aabdb6afe4be880b653f931301b40e9c66b3a6f8e6330000803f0000803f5ffebbbdf7068f3f5e91d63cb8afe4be890b653f931301b4109c66b3a7f8e6330000803f0000803f98bba5be6a35803f121f913c340dffbe7df95d3f08802e3bb1daad3aba4e17bbc5ff7f3f0000803f5efebb3df8068f3fb260aabdb2afe43e8b0b653ff60802b473526833c2afe8330000803f0000803f9ebba53e6a35803f2a0499bde4f1f63e6c41603fb32f59b50d81d1343d413e350000803f0000803f9dbba53e6b35803f261f913c370dff3e7cf95d3f8b762e3b3fd1adba7f4617bbc5ff7f3f0000803f647cbfbd3b92833facdeadbd289de23e388f65bf9c503934ed0aa4b3c82c26340000803f000080bf2fe593be17756e3f95f79bbd3cfde23e7c7765bfdf14823434aee6b3c43269340000803f000080bf30e593be15756e3f90ec9c3c3b5ee33ef25e65bf4724783be963dcbae4545e3b88ff7f3f000080bfcfafe4be17695a3fac51223d1384f23e406f61bfa8935b3ca507d0bba560413c1dfa7f3f000080bfe8e7d4be1bf35e3f8e4cc13d3c7af23ec36b61bf7f02983c4a0110bc15e0853cb8f47f3f000080bf677cbf3d3c92833faadeadbd1e9de2be398f65bfca5d0134640865338c02e8330000803f000080bf677cbf3d3c92833f2289e43c1c9de2be3a8f65bfca5d0134620865338d02e8330000803f000080bf32e5933e17756e3fa4ec9c3c4c5ee3beed5e65bfe12c783b9e6bdc3a955c5e3b88ff7f3f000080bf9abba5be6a35803f2c0499bdfe418bbe62fbe6bdb2a674bf2de9fcbcd95d7e3fe228debd0000803f2fe593be17756e3f95f79bbddb6d8dbe0f66f7bd9d1674bf7faf09bd11207e3f9da0edbd0000803f647cbfbd3b92833facdeadbdf5983cbdedcd853cbfb17fbf162d453a43f77f3f97a9853c0000803fc78bf3be3a9a673febb5253d95f69cbe37f91cbe0e7e70bf89cb42bd66f97c3f773a15be0000803fcfafe4be17695a3fac51223d4f979bbe40361cbe05bf70bf0b2240bdf2007d3fcea414be0000803fd7afe43e16695a3fcd51223d3484f2be356f61bf849c5b3c2710d03b6968413c1dfa7f3f000080bf32e5933e16756e3f93f79bbd51fde2be767765bf66500134df51653386d2e7330000803f000080bf687cbfbd3c92833f2089e43cf6983cbd72cc853cbfb17f3fe72a453a43f77f3f1da885bc000080bf30e593be15756e3f90ec9c3cf0253f3e3b85ee3d0fba793f2551b3bc03427e3f1245eabd000080bf98bba5be6a35803f121f913cbbe3363e2b3fe43d45437a3fa315a4bcba677e3fc187e0bd000080bfe93de4be1e016c3fa79abf3d5223173f9200b53edebf393f767964be24786f3ff4658cbe000080bf9dbba53e6b35803f261f913cc9e336be4a3fe43d44437a3fc715a43cba677e3fdf87e0bd000080bf32e5933e17756e3fa4ec9c3cec253fbe4585ee3d0fba793f2951b33c03427e3f1c45eabd000080bf677cbf3d3c92833f2289e43cc8983c3d69cc853cbfb17f3faa2a45ba43f77f3f14a885bc000080bff03de43e1f016c3fb69abf3d482317bf7e00b53eebbf393f4979643e28786f3feb658cbe000080bff1e7d43e1cf35e3f9d4cc13d010917bfeb3cb93e61c9383fcb746a3e7fa86e3fc06c8fbe000080bf677cbf3d3c92833faadeadbddf983c3dbbcd853cbfb17fbfb52c45ba43f77f3f65a9853c0000803f32e5933e16756e3f93f79bbdde6d8d3e2f66f7bd9c1674bf95af093d11207e3fbba0edbd0000803f9ebba53e6a35803f2a0499bd06428b3e88fbe6bdb1a674bf67e9fc3cd95d7e3f0629debd0000803fd18bf33e3a9a673f08b6253d81f69c3e4cf91cbe117e70bf8bcb423d66f97c3f8d3a15be0000803fc78bf3be3a9a673febb5253dcec404bf40dc5a3f04a43b3ceaa4c23bcd6d20bcb4fb7f3f0000803f9abba5be6a35803f2c0499bde0f1f6be6e41603f0f1cf3b3a9826ab3b0f6d4330000803f0000803fd18bf33e3a9a673f08b6253dd3c4043f3ddc5a3f14ae3b3c62afc2bb657620bcb4fb7f3f0000803ff03de43e1f016c3fb69abf3d66ca043f0ed55a3f0ac9783c2a1001bc86b054bc72f87f3f0000803f9e272cbdc820903fb2272c3d000000800000803ffbfec9350000803f0000000000000000000080bf9e272cbdc820903fb2272c3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bfe0c89030c920903fb2272c3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bfe0c89030c920903fb2272c3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bf80f2cbb0c720903f8aa8bb3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bf80f2cbb0c720903f8aa8bb3d899dae350000803f474410b45fce442a474410340000803f0000803f80f2cbb0c720903f8aa8bb3d000000800000803ffbfec9350000803f0000000000000000000080bf80f2cbb0c720903f8aa8bb3d21573eb60000803f7fa403370000803f21573e36c8c1c32d000080bf9e272c3dc820903fb0272c3d28573e360000803f0b976d370000803f28573eb6fea630ae000080bf9e272c3dc820903fb0272c3d899dae350000803f474410b45fce442a474410340000803f0000803f7ca8bb3dc620903f8aa8bb3d899dae350000803f474410b45fce442a474410340000803f0000803f006a0631c620903f7aa8bbbd25573e360000803f474410b49187d62a474410340000803f0000803f006a0631c620903f7aa8bbbd000000800000803fa489e0b60000803f0000000000000000000080bf006a0631c620903f7aa8bbbd859daeb50000803f474410b45ace44aa474410340000803f0000803f006a0631c620903f7aa8bbbd21573eb60000803f474410b48d87d6aa474410340000803f0000803fa4d83d31c720903f90272cbd25573e360000803f474410b49187d62a474410340000803f0000803fa4d83d31c720903f90272cbd21573eb60000803f474410b48d87d6aa474410340000803f0000803f9d272cbdc820903f91272cbd25573e360000803f474410b49187d62a474410340000803f0000803f9d272cbdc820903f91272cbd000000800000803fa489e0b60000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbd859daeb50000803f474410b45ace44aa474410340000803f0000803f9e272c3dc820903f92272cbd859daeb50000803f474410b45ace44aa474410340000803f0000803f9e272c3dc820903f92272cbd21573eb60000803f474410b48d87d6aa474410340000803f0000803f2b2a26310513983fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bf2b2a26310513983fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803f2b2a26310513983fb2272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bfe0c89030c920903fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bfe0c89030c920903fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803fe0c89030c920903fb2272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803f9e272cbdc820903fb2272c3dc32bb833d82044b30000803f22198d270000803fd8204433000080bf9e272cbdc820903fb2272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bf9f272c3d0513983fb2272c3d00000080f42144b30000803f0000803f00000000000000000000803f9f272c3d0513983fb2272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803f9e272c3dc820903fb0272c3d152cb8b31ae631b40000803f0000803f0af87fa8152cb8330000803fa4d83d31c720903f90272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803fa4d83d31c720903f90272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bfa4d83d31c720903f90272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f4cb688310413983f93272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf4cb688310413983f93272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bf4cb688310413983f93272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f9d272cbd0413983f90272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803f9d272cbd0413983f90272cbd9ba03fb410b350b4000080bf0000803f87381ca99ba03fb4000080bf9e272c3dc820903f92272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf9e272c3dc820903f92272cbdbea0bfb41ab350b4000080bfab389ca90000803f1ab350b40000803f9f272c3d0413983f93272cbd00000080e7aa9fb3000080bf0000803f0000000000000000000080bf1a7e8c30ff96b93f6c0f063e00000080e2bc8db40000803f0000803f00000000000000000000803f00da51300613983f670f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f00da51300613983f670f063e00000080e2bc8db40000803f0000803f00000000000000000000803f5f0f06be0613983f670f063e00000080e2bc8db40000803f0000803f00000000000000000000803f610f063eff96b93f6b0f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f5e0f063e0513983f670f063e76ca3033895e5eb40000803f0000803fdb90192876ca30b30000803f86f4c1310613983f5e0f06be000000809865e934000080bf0000803f0000000000000000000080bf86f4c1310613983f5e0f06be00000080a065e934000080bf0000803f0000000000000000000080bf86f4c1310613983f5e0f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf1299cd31fe96b93f560f06be000000807c65e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be000000809865e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be00000080a065e934000080bf0000803f0000000000000000000080bf610f06befe96b93f560f06be00000080a065e934000080bf0000803f0000000000000000000080bf610f06befe96b93f560f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf5f0f063e0513983f5e0f06be000000807c65e934000080bf0000803f0000000000000000000080bf5f0f063e0513983f5e0f06be000000809865e934000080bf0000803f0000000000000000000080bf600f063efe96b93f560f06be000000807c65e934000080bf0000803f0000000000000000000080bf1299cd31fe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf1a7e8c30ff96b93f6c0f063e000000800000803f474410b40000803f0000000000000000000080bf600f06beff96b93f6c0f063e000000800000803f474410b40000803f0000000000000000000080bf600f063efe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf610f063eff96b93f6b0f063e000000800000803f474410b40000803f0000000000000000000080bf00da51300613983f670f063e1f573e36000080bf474410348b87d6aa474410340000803f000080bf00da51300613983f670f063e00000080000080bf474410340000803f00000000000000000000803f00da51300613983f670f063e00000080000080bfeee5bd350000803f00000000000000000000803f00da51300613983f670f063e836d74b5000080bf47441034cbbe092a474410340000803f000080bf2b2a26310513983fb2272c3d1f573e36000080bf474410348b87d6aa474410340000803f000080bf2b2a26310513983fb2272c3d00000080000080bf474410340000803f00000000000000000000803f9d272cbd0413983faf272c3d1f573e36000080bf474410348b87d6aa474410340000803f000080bf9d272cbd0413983faf272c3d00000080000080bfeee5bd350000803f00000000000000000000803f5e0f063e0513983f670f063e836d74b5000080bf47441034cbbe092a474410340000803f000080bf9f272c3d0513983fb2272c3d00000080000080bf474410340000803f00000000000000000000803f9f272c3d0513983fb2272c3d836d74b5000080bf47441034cbbe092a474410340000803f000080bf9d272cbd0413983f90272cbd7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f9d272cbd0413983f90272cbd96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f4cb688310413983f93272cbd00000080000080bfa5a2f9b50000803f00000000000000000000803f4cb688310413983f93272cbd96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f86f4c1310613983f5e0f06be7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f86f4c1310613983f5e0f06be00000080000080bfa5a2f9b50000803f00000000000000000000803f86f4c1310613983f5e0f06be96d585ab000080bff08a3bb60000803f96d585ab4e1744a20000803f86f4c1310613983f5e0f06be836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803f9f272c3d0413983f93272cbd00000080000080bfa5a2f9b50000803f00000000000000000000803f9f272c3d0413983f93272cbd836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803f5f0f063e0513983f5e0f06be836d74b5000080bf28d922b60000803f836d74b5a47c1bac0000803fd0bdd6316e78823f42d2bfbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bfd0bdd6316e78823f42d2bfbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bfd0bdd6316e78823f42d2bfbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bfd0bdd6316e78823f42d2bfbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bf006a0631c620903f7aa8bbbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bf006a0631c620903f7aa8bbbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bf80a8bbbdc620903f7ba8bbbdb9864c34120b9c3c1df47fbf0000803fe25579b13a7d4c34000080bf80a8bbbdc620903f7ba8bbbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bf47d2bf3d6e78823f42d2bfbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbd00000080e00a9c3c1cf47fbf0000803f0000000000000000000080bf80a8bb3dc720903f7ba8bbbdcd864cb4220b9c3c1cf47fbf0000803f145679314d7d4cb4000080bfa8318bb09718243fe194cebdbc8cb036bed6bebddae27ebf0000803f8c9c033515c8af36000080bfd0bdd6316e78823f42d2bfbdbc1be133780a9c3c1df47fbf0000803f1b3609b14811e133000080bf44d2bfbd6d78823f43d2bfbd3bd135347b0a9c3c1cf47fbf0000803fe3a55db1c9c83534000080bf1deef83d9618243fe294cebdff131cb759c5f6bd84227ebf0000803f897396b5e2f01ab7000080bf47d2bf3d6e78823f42d2bfbddacf05b3760a9c3c1cf47fbf0000803f41202330a3c905b3000080bf80a8bbbdc720903f8aa8bb3d00000080f6099c3c1df47f3f0000803f00000000000000000000803f80f2cbb0c720903f8aa8bb3d00000080db099c3c1cf47f3f0000803f00000000000000000000803f78cbd6306e78823f4ad2bf3d0b7761334eaa193dded17f3f0000803f235607b16a4e61b30000803f7ca8bb3dc620903f8aa8bb3d00000080cd099c3c1df47f3f0000803f00000000000000000000803f48d2bf3d6e78823f49d2bf3db97d3a3c3154103d0ed37f3fc1fb7f3f974bd2b912603abc0000803f48d2bfbd6f78823f4bd2bf3d4e7d3abc3d54103d0fd37f3fc1fb7f3f304bd239a85f3a3c0000803f441459b19818243ffa40eb3de06221b3834e9fbd6f397f3f0000803fd0db48b1b2e520330000803f1deef83d9718243ff294ce3d6e23eb3d1cf9e4bdfab07c3f0ea4533c1e657e3f8f70e33d000080bfc29bf5bd04bb1a3f74dcbb3dd1f17fbf029aa9bc272c07bbbd2407bb081b33b8ddff7f3f0000803fc49bf5bd05bb1a3fccd3babd57eb7fbfd7aecdbc949bb2322a8db23291800f300000803f0000803f1deef8bd9818243ff194ce3d6623ebbde0f8e4bdfab07c3fcfa353bc1f657e3f5370e33d000080bf4549a7bc05bb1a3feaeed33d2cadebbd7d69f9bd88617c3fa04c7e3faa2567bc0ce6e93d0000803fa8318bb09718243fe194cebdc8885f3f038cf9be549c3f348e4f27b4d9c7ba330000803f000080bf4349a7bc04bb1a3fcbd3babd096a723f9e93a4bedfbd0e349c2a07b4e48737330000803f000080bf4549a7bc05bb1a3feaeed33d5bd3743f639d95be56ba063be7d800bba77a1d3addff7f3f000080bf1ceef8bd9718243fe294cebd00c0cfb5efc2f6bd8e227ebf0000803fb14048b48b3cceb5000080bfc49bf5bd05bb1a3fccd3babdfd0d17b47c839fbe434273bf0000803f8b3e3cb360890fb4000080bf4349a7bc04bb1a3fcbd3babd32b0aab391759bbe05ea73bf0000803f234ecfb248a1a2b3000080bfa8318bb09718243fe194cebdc2885fbf168cf9be6130cf33d3e9b4336ff749330000803f0000803f441459b19818243ffa40eb3dc4885fbf138cf9be3aca9134179a7e34781d0e340000803f0000803f3e49a73c05bb1a3feaeed33d5cd374bf619d95be61bb063be7d9003bdd7b1d3addff7f3f0000803fc59bf53d05bb1a3f75dcbb3d1470eb3d4dc1d0bddef57c3f2dfe403ca7aa7e3f435bcf3d000080bf3e49a73c05bb1a3feaeed33d0badeb3d9369f9bd89617c3fa04c7e3f9d25673cece5e9bd0000803f1deef83d9618243fe294cebd7bf37f3f8923a03ce21253368f0853b61a0984b30000803f000080bfc59bf53d04bb1a3fccd3babd57eb7f3fd9aecdbce7c82231c4bb22b110ca822e0000803f000080bf1deef83d9618243fe294cebd8e9da6350cc3f6bd8d227ebf0000803f589a2034d066a535000080bfa8318bb09718243fe194cebdff7fbb36afd3bebde3e27ebf0000803f0ac40b352cafba36000080bfa8318bb09718243fe194cebd90a4bbb628d4bebde2e27ebf0000803fa4df0bb594d3bab6000080bf4249a73c05bb1a3fcbd3babd61196db483759bbe08ea73bf0000803f34fb8fb3d8e761b4000080bfe690fbbdce17b53e4e99d43de1f37fbf65620a3b019a9cbced5b0a3bdbff7f3f844e2938000080bf59cff7bd6958b53e011b023cb2f57fbfd102f8392d3791bcd7f8f739feff7f3f0eaf0c37000080bfbe3af5bdecd3d23d56ed2c3d84ca7fbf86906cbabc6725bd1f5f6cbaf9ff7f3f06d918b8000080bf2697edbda5dbd33d19b635bde2c67fbf4d54fa3b9a1528bd521efa3b17fe7f3fad5da439000080bf380910bdce17b53e70dde63db336d2bd6b6fd7bd4e387d3fdba57e3fe6d731bcf008d13d0000803fe690fbbdce17b53e4e99d43dd7e4bcbdc55ddcbd856a7d3fa6e87e3f0b4c23bcadc9bb3d0000803fc29bf5bd04bb1a3f74dcbb3d1d70ebbd09c1d0bde0f57c3ff4fd40bca8aa7e3fff5acf3d000080bf932c1bbd0d93d13dbaa3303dc61fabbc616a00be38ec7d3fb3f17f3f96b72bbbc9c5a93c0000803fbe3af5bdecd3d23d56ed2c3dbb0e43bc5467fbbdaa0b7e3f5bfb7f3fa691bfba0495413c0000803f888608bd6a58b53e051b023c22cf7f3f3ef817bd46342f3c65152fbc8106d03941fc7f3f000080bf380910bdce17b53e70dde63d87c57f3f96cf1dbd99bc8d3ca6a18dbce3c52e3a31f67f3f000080bfd56721bdd0f9d13d97d92abd0ff27f3f764d3cbce64c8cbc64463c3cacfb7f3f56694eb90000803f932c1bbd0d93d13dbaa3303d8bf27f3f586874bc1ebd60bcb8b6603c079556b9d6f97f3f000080bf59cff7bd6958b53e011b023c1d319a33bf9cb2bd4a067fbf0000803f1e29d731b69a9933000080bf888608bd6a58b53e051b023ccb2c623b6096bfbd38e07ebf9cff7f3f8944a939e22e613b000080bf2697edbda5dbd33d19b635bdb005063d6468853ed90377bfe9dc7f3f5fc20bbc3d63013d000080bfd56721bdd0f9d13d97d92abd4d93153d53a7843eeb1477bf4ad47f3feb1d1bbc0376103d000080bf8e86083d6b58b53efc1a023c21cf7fbf52f817bd04342f3c23152f3c4e06d03941fc7f3f0000803f3d09103dcc17b53e70dde63d87c57fbfa3cf1dbd6dbc8d3c7aa18d3cbbc52e3a31f67f3f0000803f992c1b3d0893d13db7a3303d8bf27fbf426874bcfbbc60bc95b660bcd29456b9d6f97f3f0000803f4249a73c05bb1a3fcbd3babd056a72bfb293a4be82690133aa16f532826426320000803f0000803f992c1b3d0893d13db7a3303d901fab3c5f6a00be38ec7d3fb3f17f3f5db72b3b94c5a9bc0000803f3d09103dcc17b53e70dde63d9236d23d6f6fd7bd50387d3fdba57e3fccd7313cd008d1bd0000803feb90fb3dcc17b53e5099d43dbfe4bc3dc95ddcbd856a7d3fa6e87e3ff94b233c95c9bbbd0000803fc53af53de6d3d23d57ed2c3d84ca7f3fadb46cba9b6725bd3f836c3af9ff7f3f44f018b80000803feb90fb3dcc17b53e5099d43de1f37f3f3a630a3b2d999cbcc25c0abbdbff7f3fa34e29380000803f63cff73d6b58b53e051b023cb2f57f3ff70ef839953691bcfd04f8b9feff7f3f5eb50c370000803fc59bf53d05bb1a3f75dcbb3dd1f17f3f6a99a9bc1e2c07bbb424073b5b1a33b8ddff7f3f000080bf2e97ed3d9ddbd33d1cb635bd900506bd6568853ed90377bfe9dc7f3f3fc20b3c1f6301bd000080bf63cff73d6b58b53e051b023ce6b6e333da9cb2bd49067fbf0000803fb1e01e32c6d8e233000080bf8e86083d6b58b53efc1a023c192b62bb6f96bfbd37e07ebf9cff7f3f5143a9b9312d61bb000080bfc59bf53d04bb1a3fccd3babd6b0489b486839fbe404273bf0000803f47c0aab3a73282b4000080bfe93de4be1e016c3fa79abf3d3fca04bf26d55a3f0ac2783c620c013ca2aa54bc72f87f3f0000803fedb2eebe20e1683f4241093ecf741fbf04a7463f4a7acb3d44be7e3d54ae9ebdbcbb7e3f0000803fe8e7d4be1bf35e3f8e4cc13df208173fde3cb93e72c9383fa1746abe80a86e3fc16c8fbe000080bfe35edfbea4055c3f41b00a3ed2240d3f30ceb13e4831423f6b1351be3a11703f0ed48fbe000080bfedb2eebe20e1683f4241093e6552153f8941ba3e76eb393fa24369bec3756e3fcb3791be000080bf80a5f9bef476543fac53353d8d2e0b3f6bad56bf70560dbdb5c6993c2830edbcf8d87f3f000080bfe35edfbea4055c3f41b00a3ee02d0b3fe4ad56bf9c490dbdfeb7993c211bedbc00d97f3f000080bf7c1504bfdf8d613f1c103b3d907bb0be3e132ebe7e566cbf048e73bd1e467c3f341423be0000803f8115043fdf8d613f42103b3d18771f3fdda4463f118ecb3decda7ebd2fbc9ebd7ebb7e3f0000803ff3b2ee3e1ee1683f4c41093ed7741f3ff9a6463fe07acb3d0dbf7ebdc1ae9ebdbabb7e3f0000803fd7afe43e16695a3fcd51223d37979b3e48361cbe0abf70bff721403df2007d3fd9a414be0000803f8aa5f93ef276543fd253353d128bc43e8a3e43bed94a67bf17b3983db74d7b3f74b233be0000803f8115043fdf8d613f42103b3d907bb03e43132ebe7e566cbf0a8e733d1e467c3f391423be0000803ff1e7d43e1cf35e3f9d4cc13dab7af2bea46b61bf4806983c2205103c58e3853cb7f47f3f000080bfeb5edf3ea2055c3f4bb00a3ef22d0bbfd7ad56bf84490dbdf7b799bcea1aedbc00d97f3f000080bff3b2ee3e1ee1683f4c41093e665215bf7241ba3e7beb393f8243693ec8756e3fba3791be000080bf71c510bf212c4b3f0ca8473e2dc433bf17e5303f11a62f3e8365fa3d9c65f6bda9347c3f0000803fe5e616bf4fa5473fa6171c3e23c433bf18e5303f9ba62f3e4066fa3d6566f6bda3347c3f0000803f13670cbfda48463f2918453e02aaab3edbb9363e08d16c3f4b0e79bd28e47b3f61ca2bbe000080bf71c510bf212c4b3f0ca8473ee494a93ea0d13e3eefca6c3f47a880bd14847b3f12a633be000080bf5eb812bf92a6423fc433183ec6ca143fdea94fbfc32084bd47e9193de3ce56bd77777f3f000080bf80a5f9bef476543fac53353d058bc4be923e43bedc4a67bf14b398bdb64d7b3f7eb233be0000803fe5e616bf4fa5473fa6171c3ec8ce18bfaffab1bed01c39bfef9a62befb08703f764189be0000803f13670cbfda48463f2918453e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bf5eb812bf92a6423fc433183e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bfe5e616bf4fa5473fa6171c3e5ca018bfcc391abff3d9073f6f1ebf3e211fc13eeefa583f000080bfece6163f4ba5473fb6171c3e20c4333f27e5303fefa52f3e4065fabd8365f6bdac347c3f000080bf66b8123f8ea6423fd333183e57ba173f53feb5be660639bfaccd663e0a486f3f17ba8cbe0000803fece6163f4ba5473fb6171c3ee1ce183f4dfab1bed11c39bf889a623e0e09703f214189be0000803f18670c3fd748463f3918453ebaca14bfdea94fbf282484bd33ed19bd6fd456bd71777f3f000080bf66b8123f8ea6423fd333183ebfca14bfe0a94fbf442184bdd6e919bdb7cf56bd76777f3f000080bfeb5edf3ea2055c3f4bb00a3ed7240dbf2cceb13e4431423f6d13513e3b11703f07d48fbe000080bf78c5103f1d2c4b3f1ba8473ea094a9bec2d13e3ef9ca6c3f2aa8803d12847b3f3aa633be000080bfece6163f4ba5473fb6171c3e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bf66b8123f8ea6423fd333183e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bf18670c3fd748463f3918453e51a0183f64391abf75da073f5f1fbfbea01fc13e9dfa583f000080bfd1bdf5bd24959d3d967b2c3d8aa07fbf9be0303cc48758bd49a1303c2ffc7f3f8d9d153a000080bf65331cbd72549c3de931303d34e535bce84685bb6bfb7f3f52653db875ff7f3fcd44853b000080bf986e22bd73c19c3db98f4fbd93a07d3f10c4ccbdd44fbcbd345cbb3de24317bc5fea7e3f000080bf65331cbd72549c3de931303dc5df7f3f961b1cbcedbdf43cbf091c3c07fd7f3fd83f95390000803fbf1aeebd2ba39e3d2b6c5abdc278e23cb7a8b43ef46d6fbff4e67f3fcfe11fbcbde4d33c000080bf986e22bd73c19c3db98f4fbdaae1153d854fb63e9e096fbf1cd47f3f9b9e55bc520b0c3d000080bfda67213dcbf9d13d9cd92abd0ff27fbfa84c3cbcc14c8cbc96453cbcacfb7f3f3e684eb9000080bf6a331c3d6d549c3de731303dc5df7fbf071c1cbc1bbef43c300a1cbc07fd7f3f60409539000080bfc53af53de6d3d23d57ed2c3d8e0e433c6167fbbdaa0b7e3f5bfb7f3f8491bf3ad79441bc0000803fd8bdf53d1f959d3d967b2c3d7be2353c2f3985bb6bfb7f3ffc4e3d3876ff7f3f1537853b000080bf6a331c3d6d549c3de731303dbde4353c304685bb6cfb7f3fd2633d3876ff7f3f1744853b000080bf2e97ed3d9ddbd33d1cb635bde2c67f3fbe56fa3b8e1528bdc120fabb16fe7f3f3b5fa4390000803fc61aee3d25a39e3d2d6c5abd27cd7e3f25a331bd49e8b0bdd9f8303d57c27f3fe0bd75bb0000803fd8bdf53d1f959d3d967b2c3d8aa07f3f14df303cd98758bdc39f30bc2ffc7f3f509c153a0000803fda67213dcbf9d13d9cd92abd209315bd4da7843eeb1477bf4ad47f3fb51d1b3cd77510bd000080bf9b6e223d6dc19c3dbe8f4fbd82e115bd844fb63e9f096fbf1cd47f3f619e553c2d0b0cbd000080bfbf1aeebd2ba39e3d2b6c5abd27cd7ebf76a331bd40e8b0bd2af930bd57c27f3f44be75bb000080bf1348f7bd24a4a9341f262b3dd4f97ebf81e5afbceda4b1bdb63bafbce4f07f3f692cf4ba000080bf828486bd25b996341d15adbd277f733f737a70be512c4dbe0a31473eeeb844bd07cf7a3f000080bf93471fbd9a1b9d3472dc2e3dab737f3f68547ebdb866a83c7f13a8bc7e56a73a26f27f3f000080bf9021cebd5d859734a640aabd625c17bdbf6ab43e92646fbf3dd37f3f787d553c7aa30dbd000080bf828486bd25b996341d15adbde56464bbed38be3e9eac6dbf9aff7f3fefb5a93abd0b54bb000080bf1348f7bd24a4a9341f262b3d288609b3000080bf724b8e340000803f288609b3e3e118280000803f1348f7bd24a4a9341f262b3d6a079ab4000080bf274725342ee34629274725340000803f000080bf1348f7bd24a4a9341f262b3d2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf1348f7bd24a4a9341f262b3d85cca2b4000080bf75388b34e711b12975388b340000803f000080bf93471fbd9a1b9d3472dc2e3d6a079ab4000080bf274725342ee34629274725340000803f000080bf93471fbd9a1b9d3472dc2e3d2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf828486bd25b996341d15adbd288609b3000080bf724b8e340000803f288609b3e3e118280000803f828486bd25b996341d15adbd6a079ab4000080bf274725342ee34629274725340000803f000080bf9b6e223d6dc19c3dbe8f4fbd93a07dbf0cc4ccbdc84fbcbd285cbbbdd54317bc5fea7e3f0000803f9d471f3d8210653478dc2e3dab737fbfa1547ebd0f67a83cd613a83cfa56a73a26f27f3f0000803f9621ce3dfce66c34a840aabdd5617a3fd8de0bbe411921be6c180a3ec1997d3f46b4b1bc0000803f1c48f73d1f99593427262b3dd4f97e3fa5e5afbc0ba5b1bdda3baf3ce4f07f3fc42cf4ba0000803fc61aee3d25a39e3d2d6c5abd7878e2bcbca8b43ef46d6fbff4e67f3f9fe11f3c78e4d3bc000080bf8684863d34926c342015adbd8869643bea38be3e9fac6dbf9aff7f3f5fb9a9ba0c10543b000080bf1c48f73d1f99593427262b3d5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f1c48f73d1f99593427262b3daf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf1c48f73d1f99593427262b3d56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f1c48f73d1f99593427262b3d226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f9621ce3dfce66c34a840aabd5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f8684863d34926c342015adbd5dd67a32000080bf350f1db40000803f5dd67a325ee419270000803f8684863d34926c342015adbdaf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf746a073e606a3a346d2b363e630d7f3f0f5d8f3cc95facbdcbda8ebcf7f57f3fe617c13a0000803f6ba7063e657e2d3d6d2b363e97137f3f91137a3cc8f6aabd0f3479bc5ef87f3f0c07a73a0000803f63a706be807e2d3d642b363e99137fbf4d127a3c95f6aabdce32793c5ef87f3f0106a73a000080bf6b6a07be9976be34622b363e630d7fbfd05b8f3c945facbd8dd98e3cf7f57f3ffd15c13a000080bf9d471f3d8210653478dc2e3daf0f0db4000080bf8374b1b3179043a88374b1b30000803f000080bf9d471f3d8210653478dc2e3d56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f50256f3db03a45346d2b363e56750eb4000080bf5fe856b40000803f56750eb4ca2eefa80000803f50256f3db03a45346d2b363e226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f6b6a07be9976be34622b363e85cca2b4000080bf75388b34e711b12975388b340000803f000080bf3a256fbd8170b234632b363e2a9d9ab4000080bf8178873451a3a329817887340000803f000080bf3a256fbd8170b234632b363e85cca2b4000080bf75388b34e711b12975388b340000803f000080bfcf196c3dea8b2b3d6d2b363e7c5f7dbf21627cbc3178113eb4d279bc3af87f3f6f6e0f3b000080bf3a256fbd8170b234632b363efc567d3f07e58fbceb22123edd6b8e3ce4f57f3ffa4e243b0000803fbd196cbdfd8b2b3d652b363e7c5f7d3f59617cbc2578113eeed1793c3af87f3ff26d0f3b0000803fd8bdf53d1f959d3d967b2c3d5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bf6ba7063e657e2d3d6d2b363e5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bfcf196c3dea8b2b3d6d2b363e5a5cccbba80a783fb9427d3ebafe7f3ff602c63b8a2dca3a000080bfd1bdf5bd24959d3d967b2c3dea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bf65331cbd72549c3de931303dea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bfbd196cbdfd8b2b3d652b363eea33933ba9fe773f4e087e3e57ff7f3fe4998ebbaa1292ba000080bf3a256fbd8170b234632b363e00000080c4da17b50000803f0000803f00000000000000000000803f6b6a07be9976be34622b363e00000080c4da17b50000803f0000803f00000000000000000000803f63a706be807e2d3d642b363e00000080c4da17b50000803f0000803f00000000000000000000803f6ba7063e657e2d3d6d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f746a073e606a3a346d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f50256f3db03a45346d2b363eb3f642b3474410340000803f0000803f89bddb27b3f642330000803f9e272c3dc820903f92272cbd4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f80a8bb3dc720903f7ba8bbbd4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f9e272c3dc820903fb0272c3d4d4a21360000803f474410b4a0c9b52a474410340000803f0000803f80a8bbbdc720903f8aa8bb3db0f14cb60000803f474410b438fde6aa474410340000803f0000803f80a8bbbdc620903f7ba8bbbdb0f14cb60000803f474410b438fde6aa474410340000803f0000803f9e272cbdc820903fb2272c3db0f14cb60000803f474410b438fde6aa474410340000803f0000803f9d272cbd0413983faf272c3d000080bfe0a0bf3334fb57a834fb57a826aca11c0000803f0000803f9e272c3dc820903f92272cbd0000803fdea0bf3332fb57a832fb572823aca11c0000803f000080bf5f0f06be0513983f5d0f06be000080bf0b60e9b38e20052a8e20052a26b9721e0000803f0000803f610f063eff96b93f6b0f063e0000803f0b6069b4756d74b3756d743353d35ea80000803f000080bf9d272cbd0413983faf272c3d710034b6000080bf4744103483e0ca2a474410340000803f000080bf9d272cbd0413983f90272cbd710034b6000080bf4744103483e0ca2a474410340000803f000080bf5f0f06be0613983f670f063e710034b6000080bf4744103483e0ca2a474410340000803f000080bf9f272c3d0413983f93272cbdc62b3936000080bf4744103405b4d0aa474410340000803f000080bf9f272c3d0513983fb2272c3dc62b3936000080bf4744103405b4d0aa474410340000803f000080bf5f0f063e0513983f5e0f06bec62b3936000080bf4744103405b4d0aa474410340000803f000080bf5ffebbbdf7068f3fb360aabd1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f80a8bbbdc620903f7ba8bbbd1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1ef47fbf94fa9b3c1acd2fb1f1c42fb1853a562e0000803f0000803f5ffebbbdf7068f3f5e91d63c1bf47fbf420d9c3c8b5895b59b5195b56113b6320000803f0000803f7ca8bb3dc620903f8aa8bb3d1ef47f3f8d009c3c72ac2f344ba42fb4ec1a56b10000803f000080bf5efebb3df8068f3fb260aabd1cf47f3f9b0d9c3c3e2718372d2018b7008039b40000803f000080bf5efebb3df8068f3f5f91d63cb1afe43e8a0b653f941301b40b9c6633aaf8e6330000803f0000803f687cbfbd3c92833f2089e43c2f9de23e358f65bfc75d0134700865b38202e8330000803f000080bf5ffebbbdf7068f3fb360aabd4f413ebdf21ea33c42ac7fbf7981723a01f37f3fdbf1a23c0000803f5ffebbbdf7068f3f5e91d63c51413ebd901da33c42ac7f3f6d7f723a01f37f3f79f0a2bc000080bf5efebb3df8068f3f5f91d63c1a413e3d831da33c42ac7f3f147f72ba01f37f3f6cf0a2bc000080bf5efebb3df8068f3fb260aabd31413e3db51ea33c42ac7fbff88072ba01f37f3f9ef1a23c0000803f80a8bbbdc720903f8aa8bb3d000000800000803ffbfec9350000803f0000000000000000000080bf80a8bbbdc620903f7ba8bbbd000000800000803fa489e0b60000803f0000000000000000000080bf9d272cbd0413983faf272c3de2a03fb4484410340000803f38fbd7280000803f484410b4000080bf9d272cbdc820903f91272cbde2a03f3468214433000080bf2fd012a80000803f682144330000803f600f06beff96b93f6c0f063e00000080dabc8db40000803f0000803f00000000000000000000803f1a7e8c30ff96b93f6c0f063e00000080e6bc8db40000803f0000803f00000000000000000000803f1a7e8c30ff96b93f6c0f063e00000080dabc8db40000803f0000803f00000000000000000000803f5f0f06be0613983f670f063e00000080dabc8db40000803f0000803f00000000000000000000803f610f063eff96b93f6b0f063e00000080e6bc8db40000803f0000803f00000000000000000000803f00da51300613983f670f063e00000080e6bc8db40000803f0000803f00000000000000000000803f5f0f06be0513983f5d0f06be026069b4f8d7ca34000080bf0000803fa3eab829026069b4000080bf610f06befe96b93f560f06be000000800000803f474410b40000803f0000000000000000000080bf5f0f06be0613983f670f063e00000080000080bfeee5bd350000803f00000000000000000000803f5f0f06be0513983f5d0f06be7f6d7435000080bfaee134360000803f7f6d743578b42cac0000803f44d2bfbd6d78823f43d2bfbd00000080000b9c3c1df47fbf0000803f0000000000000000000080bf1ceef8bd9718243fe294cebd61d317375ac5f6bd84227ebf0000803f2a5a923533b81637000080bf1ceef8bd9718243fe294cebd7bf37fbffd23a03c4e5950361e4f50361b5582b30000803f0000803f441459b19818243ffa40eb3dc2885f3f198cf9be5ca18c335f9775b3e81509330000803f000080bf7c1504bfdf8d613f1c103b3d21771fbfdaa4463f9d8ccb3d24d97e3d08bb9ebd82bb7e3f0000803f8aa5f93ef276543fd253353d882e0bbf6ead56bf40550dbd65c599bc2e2eedbcf9d87f3f000080bf13670cbfda48463f2918453ebcca143fdea94fbff82284bdd1eb193d7dd256bd73777f3f000080bf5eb812bf92a6423fc433183e38ba17bfcffeb5be610639bf31ce66bef3476f3f82ba8cbe0000803f71c510bf212c4b3f0ca8473e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bf13670cbfda48463f2918453e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bfe5e616bf4fa5473fa6171c3e09a118bf59381abfd6da073f0421bf3e121fc13e60fa583f000080bf78c5103f1d2c4b3f1ba8473e2cc4333f2ee5303fbfa42f3e9163fabdd363f6bdb8347c3f000080bf18670c3fd748463f3918453eada9abbe22ba363e13d16c3f340e793d26e47b3fafca2bbe000080bf78c5103f1d2c4b3f1ba8473ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bfece6163f4ba5473fb6171c3ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bf18670c3fd748463f3918453ee4a0183f83381abfd2da073fcc20bfbe3d1fc13e62fa583f000080bfd1bdf5bd24959d3d967b2c3dc5e235bce43785bb6bfb7f3f734d3db876ff7f3fca35853b000080bf9021cebd5d859734a640aabdd5617abfd2de0bbe351921be65180abec1997d3f32b4b1bc000080bf9021cebd5d859734a640aabd288609b3000080bf724b8e340000803f288609b3e3e118280000803f8684863d34926c342015adbd277f73bf827a70be4a2c4dbe023147bef4b844bd07cf7a3f0000803f9621ce3dfce66c34a840aabdc65c173db86ab43e93646fbf3dd37f3ffe7d55bcd9a30d3d000080bf746a073e606a3a346d2b363e226a12b4000080bf59b858b40000803f226a12b4f8e5f7a80000803f50256f3db03a45346d2b363efb567dbf5be58fbcf522123e2f6c8ebce4f57f3f664f243b000080bf6a331c3d6d549c3de731303ddc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bfd8bdf53d1f959d3d967b2c3ddc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bfcf196c3dea8b2b3d6d2b363edc3393bbaafe773f4a087e3e57ff7f3fd7998e3b9912923a000080bf63a706be807e2d3d642b363e7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfd1bdf5bd24959d3d967b2c3d7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfbd196cbdfd8b2b3d652b363e7c5fcc3ba90a783fae427d3ebafe7f3f0006c6bb9b30caba000080bfbd196cbdfd8b2b3d652b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803f3a256fbd8170b234632b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803f63a706be807e2d3d642b363e8da0a1b47cf719b50000803f0000803f696a42aa8da0a1340000803fcf196c3dea8b2b3d6d2b363e00000080474410340000803f0000803f00000000000000000000803f6ba7063e657e2d3d6d2b363e00000080474410340000803f0000803f00000000000000000000803f50256f3db03a45346d2b363e00000080474410340000803f0000803f00000000000000000000803f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000949ff23e3734db3e8972b03d3ff2413c020000000800000003000000010000004702fc3e643adb3e500da33d00000000020000000300000008000000000000006476023f3813fb3e000000000000000002000000050000000000000000000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000004702fc3e643adb3e500da33d00000000020000000300000008000000000000004702fc3e643adb3e500da33d000000000200000003000000080000000000000069c4603fa9deb03dbf7fbb3cfff0503c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000004b975e3fa309f43d37e0393c000000000400000003000000020000000000000081b15e3ffc39053e0000000000000000040000000300000000000000000000007271523fded8153e6e85013d00000000030000000400000002000000000000007271523fded8153e6e85013d00000000030000000400000002000000000000002af4623fe1d5d23d7b462c3c00000000040000000300000002000000000000002af4623fe1d5d23d7b462c3c0000000004000000030000000200000000000000d4a4193f7d33a33eef66903dfa232d3c03000000040000000200000008000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000e6c41e3ffaa1a13ee850833d00000000030000000400000002000000000000007271523fded8153e6e85013d000000000300000004000000020000000000000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000003a95003f8dd5fe3e00000000000000000b0000000000000000000000000000003a95003f8dd5fe3e00000000000000000b00000000000000000000000000000045bd083f7785ee3e0000000000000000000000000b000000000000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000065a0ca3e5235be3e6f22103e4864bc3d0100000002000000000000000500000068780b3f300fe93e0000000000000000000000000f00000000000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000002028033fc0aff93e0000000000000000050000000200000000000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c050000000200000001000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c050000000200000001000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000000676f43ecf95d83e1819b43dbabc3d3c0200000005000000030000000100000062fdca3e1f24c33e54921a3e5055923d02000000010000000000000003000000102c0c3fa119963ee44ce53d24d8413d02000000010000000000000003000000102c0c3fa119963ee44ce53d24d8413d020000000100000000000000030000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000d217023f5bd0fb3e000000000000000008000000020000000000000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000ba08fd3eea15f83ebd15ae3c00000000080000000200000003000000000000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e0000000000000000020000000800000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000008105063f5ff9983e4316da3d3ed8913d02000000010000000000000005000000d986c63eadc8c33eaead203e8d66953d010000000200000000000000030000007876053f0e07913e1c5ce03de8d3af3d020000000100000000000000050000007876053f0e07913e1c5ce03de8d3af3d02000000010000000000000005000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000ba08fd3eea15f83ebd15ae3c00000000080000000200000003000000000000002028033fc0aff93e0000000000000000050000000200000000000000000000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000007b285e3f8598eb3d7e8e8c3c0000000006000000050000000700000000000000d217023f5bd0fb3e0000000000000000080000000200000000000000000000002026053fc0b3f53e000000000000000009000000080000000000000000000000b13b633f8ecdc73d3ba7723c0000000009000000080000000a000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c0500000002000000010000000000000022aa043fbdabf63e00000000000000000600000005000000000000000000000074ab643ff1edb93dc0d9823c0000000006000000050000000700000000000000aca8593f4e5d193e00000000000000000700000006000000000000000000000064573a3f37518b3e0000000000000000060000000700000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000007876053f0e07913e1c5ce03de8d3af3d0200000001000000000000000500000050a55f3f8ba1dc3de0cf983c0000000009000000080000000a00000000000000bf0e043f82e2f73e00000000000000000600000005000000000000000000000022aa043fbdabf63e0000000000000000060000000500000000000000000000001ebe3d3f5c2c143e1767ac3d0b3df53c05000000020000000100000000000000f46c023f1826fb3e000000000000000007000000060000000000000000000000aca8593f4e5d193e0000000000000000070000000600000000000000000000001daa593f8a57193e00000000000000000a0000000900000000000000000000003cbc033f8787f83e000000000000000009000000080000000000000000000000102c0c3fa119963ee44ce53d24d8413d0200000001000000000000000300000074ab643ff1edb93dc0d9823c00000000060000000500000007000000000000007b285e3f8598eb3d7e8e8c3c0000000006000000050000000700000000000000c4cd413fefc8783e000000000000000006000000070000000000000000000000b13b633f8ecdc73d3ba7723c0000000009000000080000000a0000000000000050a55f3f8ba1dc3de0cf983c0000000009000000080000000a000000000000007876053f0e07913e1c5ce03de8d3af3d02000000010000000000000005000000ed28423f4a5c773e0000000000000000090000000a000000000000000000000088f6393ff1128c3e0000000000000000090000000a00000000000000000000008105063f5ff9983e4316da3d3ed8913d020000000100000000000000050000003cbc033f8787f83e0000000000000000090000000800000000000000000000002026053fc0b3f53e000000000000000009000000080000000000000000000000f777023f1310fb3e00000000000000000a000000090000000000000000000000f46c023f1826fb3e000000000000000007000000060000000000000000000000bf0e043f82e2f73e000000000000000006000000050000000000000000000000f777023f1310fb3e00000000000000000a000000090000000000000000000000ed28423f4a5c773e0000000000000000090000000a0000000000000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000b642f83e3adf9a3e6f2e023e611baf3d020000000300000005000000010000004702fc3e643adb3e500da33d00000000020000000300000008000000000000004702fc3e643adb3e500da33d0000000002000000030000000800000000000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d020000000500000001000000030000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c02000000030000000500000001000000f627253fb9a9413e263a1b3e80c4673c02000000030000000500000008000000f627253fb9a9413e263a1b3e80c4673c020000000300000005000000080000009276033fdc12f93e0000000000000000020000000800000000000000000000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000004d6d2c3fb9de2d3e9959123ebb27613c02000000030000000800000005000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000bae6f73e903bf63e9e7c933cbe5e8a3c03000000020000000800000005000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000763bfc3ee776e03e90368d3d000000000200000003000000050000000000000069c4603fa9deb03dbf7fbb3cfff0503c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c030000000200000004000000080000004702fc3e643adb3e500da33d00000000020000000300000008000000000000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c020000000300000005000000010000002f22493f3f301b3e2ee8493dabcf5c3c02000000030000000500000001000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000dab673f99a7c23d0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000de3c593f890c1b3e000000000000000004000000030000000000000000000000fabb563fc63f0a3e7e82d63c0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d000000000300000004000000020000000000000076f86c3f4f3c983d00000000000000000400000003000000000000000000000076f86c3f4f3c983d00000000000000000400000003000000000000000000000076f86c3f4f3c983d0000000000000000040000000300000000000000000000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000004b975e3fa309f43d37e0393c0000000004000000030000000200000000000000d4a4193f7d33a33eef66903dfa232d3c03000000040000000200000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000002af4623fe1d5d23d7b462c3c000000000400000003000000020000000000000076f86c3f4f3c983d0000000000000000040000000300000000000000000000000dab673f99a7c23d00000000000000000400000003000000000000000000000081b15e3ffc39053e0000000000000000040000000300000000000000000000002af4623fe1d5d23d7b462c3c0000000004000000030000000200000000000000de3c593f890c1b3e0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c00000000030000000400000002000000000000009927603fd705c83d7ff5da3c0000000003000000040000000200000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000f20f633ff8b3c93db7636e3c0000000003000000020000000400000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000fabb563fc63f0a3e7e82d63c000000000300000004000000020000000000000069c4603fa9deb03dbf7fbb3cfff0503c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c03000000020000000400000005000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000eff9593fcfdce33d6ea7183d0000000003000000020000000400000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d0000000003000000040000000200000000000000ac7d213fa3d4963e18c0983d00000000030000000400000002000000000000000ee64e3f9f06ec3d20a1653d7ce1a73c030000000200000004000000080000000ee64e3f9f06ec3d20a1653d7ce1a73c03000000020000000400000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d010000000500000002000000000000005f432d3f53d1213ef4eae33dd5ae5c3d01000000050000000200000000000000d6933a3f0110ff3d7769b33db0cf713d02000000050000000100000003000000d6933a3f0110ff3d7769b33db0cf713d020000000500000001000000030000006476023f3813fb3e0000000000000000020000000500000000000000000000006476023f3813fb3e00000000000000000200000005000000000000000000000065a0ca3e5235be3e6f22103e4864bc3d010000000200000000000000050000009276033fdc12f93e0000000000000000020000000800000000000000000000009276033fdc12f93e000000000000000002000000080000000000000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f000000000000005f432d3f53d1213ef4eae33dd5ae5c3d0100000005000000020000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000068780b3f300fe93e0000000000000000000000000f000000000000000000000065a0ca3e5235be3e6f22103e4864bc3d010000000200000000000000050000000676f43ecf95d83e1819b43dbabc3d3c02000000050000000300000001000000b642f83e3adf9a3e6f2e023e611baf3d02000000030000000500000001000000502c2f3f445f303e2a62a53dca7c803d01000000020000000000000003000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d986c63eadc8c33eaead203e8d66953d0100000002000000000000000300000062fdca3e1f24c33e54921a3e5055923d02000000010000000000000003000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b000000000000001e6d003fc425ff3e00000000000000000f0000000000000000000000000000005c552c3f2f97933ebff01d3d000000000b000000000000000c00000000000000f53d043f3b70f13e7d7b423c00000000000000000b0000000c000000000000003a95003f8dd5fe3e00000000000000000b0000000000000000000000000000007b5ffe3ef5cfdd3efe78253dfe16f23c0b000000000000000f0000000c000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f0000000000000007eb4e3f51012e3e9d94b23c00000000000000000b0000000f000000000000007b5ffe3ef5cfdd3efe78253dfe16f23c0b000000000000000f0000000c00000045bd083f7785ee3e0000000000000000000000000b0000000000000000000000f53d043f3b70f13e7d7b423c00000000000000000b0000000c0000000000000007eb4e3f51012e3e9d94b23c00000000000000000b0000000f00000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f00000000000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b000000000000004440f83e7853e33e2fbc283ddd4bf53c0f000000000000000b0000001000000038212d3fb4e7923edeae163d000000000f0000000000000010000000000000004440f83e7853e33e2fbc283ddd4bf53c0f000000000000000b0000001000000068780b3f300fe93e0000000000000000000000000f00000000000000000000006015053f9a67ef3ebfb44d3c00000000000000000f000000100000000000000068780b3f300fe93e0000000000000000000000000f0000000000000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f00000000000000ec34693fafa53a3d8f0b323d00000000000000000b0000000f000000000000002f9b503f73d3263e7efeb53c00000000000000000f0000000b00000000000000b9fd023f8e04fa3e00000000000000000c0000000b0000000000000000000000322e4d3f83db3a3e9d5d833c000000000c0000000b0000000000000000000000b95f3f3f1b6a543e5caedd3cbe09933c0c0000000d0000000e0000000b0000000dfb5d3f0552f73db9ac463c000000000d0000000c0000000e00000000000000ee78033f240ef93e00000000000000000b0000000c0000000000000000000000b9fd023f8e04fa3e00000000000000000c0000000b00000000000000000000005c552c3f2f97933ebff01d3d000000000b000000000000000c00000000000000d072473f6314323e1eaac23cba58be3c0c0000000d0000000e0000000b000000b95f3f3f1b6a543e5caedd3cbe09933c0c0000000d0000000e0000000b0000009080523f417f213efbf3a33c000000000b0000000c0000000000000000000000ee78033f240ef93e00000000000000000b0000000c000000000000000000000095fe603f8f05c33db7267e3c7b072a3c0d0000000c0000000b0000000e000000d072473f6314323e1eaac23cba58be3c0c0000000d0000000e0000000b000000322e4d3f83db3a3e9d5d833c000000000c0000000b00000000000000000000009080523f417f213efbf3a33c000000000b0000000c00000000000000000000000dfb5d3f0552f73db9ac463c000000000d0000000c0000000e0000000000000095fe603f8f05c33db7267e3c7b072a3c0d0000000c0000000b0000000e0000004b78523f5086213e20c4a43c000000000f000000100000000000000000000000b476033f9812f93e00000000000000000f000000100000000000000000000000b772473f4937323e7fa6c13c6148be3c1000000011000000120000000f0000002f9b503f73d3263e7efeb53c00000000000000000f0000000b00000000000000b772473f4937323e7fa6c13c6148be3c1000000011000000120000000f000000b476033f9812f93e00000000000000000f00000010000000000000000000000048fc023f7007fa3e0000000000000000100000000f000000000000000000000045623f3fcf42543e7c95de3c5b0b933c1000000011000000120000000f00000048fc023f7007fa3e0000000000000000100000000f00000000000000000000006c334d3faec43a3efe6c833c00000000100000000f000000000000000000000038212d3fb4e7923edeae163d000000000f000000000000001000000000000000b5c35d3f2541f83d7e094d3c00000000110000001000000012000000000000006c334d3faec43a3efe6c833c00000000100000000f00000000000000000000004b78523f5086213e20c4a43c000000000f0000001000000000000000000000006015053f9a67ef3ebfb44d3c00000000000000000f0000001000000000000000c4cd413fefc8783e00000000000000000600000007000000000000000000000019544f3f9baf423e00000000000000000700000006000000000000000000000064573a3f37518b3e000000000000000006000000070000000000000000000000e90a563f5ad4273e00000000000000000700000006000000000000000000000019544f3f9baf423e00000000000000000700000006000000000000000000000024de713fc01d623d000000000000000007000000060000000000000000000000e90a563f5ad4273e000000000000000007000000060000000000000000000000b3b2553f3335293e0000000000000000070000000600000000000000000000000135593ffe2b1b3e00000000000000000a0000000900000000000000000000005c734b3f9032523e00000000000000000a0000000900000000000000000000001daa593f8a57193e00000000000000000a0000000900000000000000000000008f09713f0e676f3d00000000000000000a0000000900000000000000000000000135593ffe2b1b3e00000000000000000a00000009000000000000000000000088f6393ff1128c3e0000000000000000090000000a0000000000000000000000be66593f06651a3e00000000000000000a0000000900000000000000000000005c734b3f9032523e00000000000000000a0000000900000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000700000000000000000000000000000024de713fc01d623d0000000000000000070000000600000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a000000000000000000000000000000be66593f06651a3e00000000000000000a0000000900000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000953c6e3f6e01193d3f35033d000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000b5e56d3f2dea2b3dfc74eb3c000000000d0000000c0000000e00000000000000953c6e3f6e01193d3f35033d000000000d0000000c0000000e000000000000003625613f5885c23d81747d3c4113253c11000000100000000f0000001200000085f0243f40e8593eab55123e000000001100000010000000120000000000000045623f3fcf42543e7c95de3c5b0b933c1000000011000000120000000f000000e2752d3fcf103e3ea9170c3e000000001100000010000000120000000000000085f0243f40e8593eab55123e0000000011000000100000001200000000000000b5c35d3f2541f83d7e094d3c000000001100000010000000120000000000000031d36c3fee31353dfc35fb3c0000000011000000100000001200000000000000e2752d3fcf103e3ea9170c3e00000000110000001000000012000000000000003625613f5885c23d81747d3c4113253c11000000100000000f000000120000008a296f3f6ef7113ddbdff63c0000000011000000100000001200000000000000b5e56d3f2dea2b3dfc74eb3c000000000d0000000c0000000e000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c0000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c000000000000009e53783f3f8cf53c00000000000000000d0000000e000000000000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000009916663fb896af3dfaa37d3c000000000e0000000d0000000c000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c000000000000001a5a633f6853bd3d1c6f9f3c000000000e0000000d0000000c0000000000000030b7783f001ae93c00000000000000000d0000000e000000000000000000000030b7783f001ae93c00000000000000000d0000000e00000000000000000000008a296f3f6ef7113ddbdff63c000000001100000010000000120000000000000074b6613f6f3dc83dbd3ba83c0000000012000000110000001000000000000000688a773f7f59073d000000000000000011000000120000000000000000000000f658673f06f1a63d383a723c000000001200000011000000100000000000000031d36c3fee31353dfc35fb3c0000000011000000100000001200000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000f658673f06f1a63d383a723c0000000012000000110000001000000000000000688a773f7f59073d000000000000000011000000120000000000000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000705a793ffeb1d43c00000000000000001100000012000000000000000000000001447d3fbdff2e3c00000000000000001200000011000000000000000000000043af793f9b17ca3c000000000000000012000000110000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d000000000000000000000079387d3fbbe1313c00000000000000000e0000000d000000000000000000000074b6613f6f3dc83dbd3ba83c000000001200000011000000100000000000000074b6613f6f3dc83dbd3ba83c00000000120000001100000010000000000000000000803f000000000000000000000000120000000000000000000000000000000000803f0000000000000000000000001200000000000000000000000000000079387d3fbbe1313c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e0000000000000000000000000000000000803f0000000000000000000000000e0000000000000000000000000000001368793f9cfdd23c0000000000000000120000001100000000000000000000000000803f0000000000000000000000000e000000000000000000000000000000e16c793fdb63d23c00000000000000000e0000000d0000000000000000000000e2752d3fcf103e3ea9170c3e000000001100000010000000120000000000000043af793f9b17ca3c0000000000000000120000001100000000000000000000001368793f9cfdd23c0000000000000000120000001100000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000007ec2243fc8d7593e411e133e000000000d0000000c0000000e00000000000000e16c793fdb63d23c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e00000000000000000000000000000079387d3fbbe1313c00000000000000000e0000000d0000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d000000000000000000000043af793f9b17ca3c00000000000000001200000011000000000000000000000001447d3fbdff2e3c0000000000000000120000001100000000000000000000000000803f000000000000000000000000120000000000000000000000000000004d6d2c3fb9de2d3e9959123ebb27613c020000000300000008000000050000009276033fdc12f93e0000000000000000020000000800000000000000000000004702fc3e643adb3e500da33d00000000020000000300000008000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006476023f3813fb3e000000000000000002000000050000000000000000000000763bfc3ee776e03e90368d3d0000000002000000030000000500000000000000657f5a3f24d2d63de138e23cbc23653c030000000200000004000000050000004d6d2c3fb9de2d3e9959123ebb27613c02000000030000000800000005000000e6c41e3ffaa1a13ee850833d0000000003000000040000000200000000000000de3c593f890c1b3e000000000000000004000000030000000000000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000c4fa573f87bcbf3d1df9383d1cc38f3c030000000200000004000000050000007271523fded8153e6e85013d00000000030000000400000002000000000000000ee64e3f9f06ec3d20a1653d7ce1a73c0300000002000000040000000800000069c4603fa9deb03dbf7fbb3cfff0503c03000000020000000400000008000000d4a4193f7d33a33eef66903dfa232d3c030000000400000002000000080000002028033fc0aff93e0000000000000000050000000200000000000000000000006476023f3813fb3e0000000000000000020000000500000000000000000000006c06fd3e20ecf93e3ed7903c00000000050000000200000003000000000000006c06fd3e20ecf93e3ed7903c0000000005000000020000000300000000000000949ff23e3734db3e8972b03d3ff2413c02000000080000000300000001000000d217023f5bd0fb3e000000000000000008000000020000000000000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000102c0c3fa119963ee44ce53d24d8413d020000000100000000000000030000002028033fc0aff93e0000000000000000050000000200000000000000000000006c06fd3e20ecf93e3ed7903c0000000005000000020000000300000000000000ba08fd3eea15f83ebd15ae3c0000000008000000020000000300000000000000d217023f5bd0fb3e0000000000000000080000000200000000000000000000000676f43ecf95d83e1819b43dbabc3d3c020000000500000003000000010000006476023f3813fb3e000000000000000002000000050000000000000000000000657f5a3f24d2d63de138e23cbc23653c03000000020000000400000005000000f627253fb9a9413e263a1b3e80c4673c0200000003000000050000000800000081b15e3ffc39053e0000000000000000040000000300000000000000000000000dab673f99a7c23d0000000000000000040000000300000000000000000000000dab673f99a7c23d0000000000000000040000000300000000000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000de3c593f890c1b3e0000000000000000040000000300000000000000000000009927603fd705c83d7ff5da3c0000000003000000040000000200000000000000e6c41e3ffaa1a13ee850833d00000000030000000400000002000000000000004b975e3fa309f43d37e0393c00000000040000000300000002000000000000007271523fded8153e6e85013d0000000003000000040000000200000000000000e6c41e3ffaa1a13ee850833d000000000300000004000000020000000000000009302b3f909a163ef32e073e68d9553d0500000001000000020000000000000045bd083f7785ee3e0000000000000000000000000b000000000000000000000045bd083f7785ee3e0000000000000000000000000b0000000000000000000000cb4c503fc8edbe3de1abbe3d00000000000000000f0000000b00000000000000b3b2553f3335293e0000000000000000070000000600000000000000000000008f09713f0e676f3d00000000000000000a0000000900000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f000000000000000000000000070000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000000000803f0000000000000000000000000a0000000000000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e000000000000009e53783f3f8cf53c00000000000000000d0000000e00000000000000000000009e53783f3f8cf53c00000000000000000d0000000e0000000000000000000000705a793ffeb1d43c000000000000000011000000120000000000000000000000688a773f7f59073d00000000000000001100000012000000000000000000000001447d3fbdff2e3c0000000000000000120000001100000000000000000000000000803f0000000000000000000000001200000000000000000000000000000085f0243f40e8593eab55123e0000000011000000100000001200000000000000e2752d3fcf103e3ea9170c3e00000000110000001000000012000000000000001368793f9cfdd23c000000000000000012000000110000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d00000000000000000000002e982d3f660e3e3ee4900b3e000000000d0000000c0000000e00000000000000e16c793fdb63d23c00000000000000000e0000000d0000000000000000000000e16c793fdb63d23c00000000000000000e0000000d00000000000000000000000000803f0000000000000000000000000e000000000000000000000000000000e1a9793fdcc3ca3c00000000000000000e0000000d00000000000000000000001368793f9cfdd23c00000000000000001200000011000000000000000000000043af793f9b17ca3c0000000000000000120000001100000000000000000000000000803f00000000000000000000000012000000000000000000000000000000 - m_CompressedMesh: - m_Vertices: - m_NumItems: 0 - m_Range: 0 - m_Start: 0 - m_Data: - m_BitSize: 0 - m_UV: - m_NumItems: 0 - m_Range: 0 - m_Start: 0 - m_Data: - m_BitSize: 0 - m_Normals: - m_NumItems: 0 - m_Range: 0 - m_Start: 0 - m_Data: - m_BitSize: 0 - m_Tangents: - m_NumItems: 0 - m_Range: 0 - m_Start: 0 - m_Data: - m_BitSize: 0 - m_Weights: - m_NumItems: 0 - m_Data: - m_BitSize: 0 - m_NormalSigns: - m_NumItems: 0 - m_Data: - m_BitSize: 0 - m_TangentSigns: - m_NumItems: 0 - m_Data: - m_BitSize: 0 - m_FloatColors: - m_NumItems: 0 - m_Range: 0 - m_Start: 0 - m_Data: - m_BitSize: 0 - m_BoneIndices: - m_NumItems: 0 - m_Data: - m_BitSize: 0 - m_Triangles: - m_NumItems: 0 - m_Data: - m_BitSize: 0 - m_UVInfo: 0 - m_LocalAABB: - m_Center: {x: 0.00000020861626, y: 0.7249603, z: 0.032029606} - m_Extent: {x: 0.58946085, y: 0.7249602, z: 0.1629476} - m_MeshUsageFlags: 0 - m_BakedConvexCollisionMesh: - m_BakedTriangleCollisionMesh: - m_MeshMetrics[0]: 1 - m_MeshMetrics[1]: 1 - m_MeshOptimizationFlags: 1 - m_StreamData: - offset: 0 - size: 0 - path: diff --git a/Assets/MeshesIntegrated.mesh.asset.meta b/Assets/MeshesIntegrated.mesh.asset.meta deleted file mode 100644 index d4674ae61..000000000 --- a/Assets/MeshesIntegrated.mesh.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 48cadfe261b960249b58f8eac1fe35d4 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 4300000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs b/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs deleted file mode 100644 index 793972b4c..000000000 --- a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UniGLTF; -using UniGLTF.MeshUtility; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; - - -namespace VRM -{ - /// - /// 複数のメッシュを統合する。 - /// VRM の場合、BlendShapeClip の調整が必用なのでこれも実行する。 - /// - [DisallowMultipleComponent] - public static class MeshIntegratorEditor - { - const string ASSET_SUFFIX = ".mesh.asset"; - - public static bool IntegrateValidation() - { - return Selection.activeObject != null && - Selection.activeObject is GameObject && - SkinnedMeshUtility.IsPrefab(Selection.activeObject); - } - - public static List Integrate(GameObject prefab, UniGLTF.UnityPath writeAssetPath, IEnumerable excludes) - { - Undo.RecordObject(prefab, "Mesh Integration"); - var instance = SkinnedMeshUtility.InstantiatePrefab(prefab); - - var clips = new List(); - var proxy = instance.GetComponent(); - if (proxy != null && proxy.BlendShapeAvatar != null) - { - clips = proxy.BlendShapeAvatar.Clips; - } - foreach (var clip in clips) - { - Undo.RecordObject(clip, "Mesh Integration"); - } - - // Backup Exists - BackupVrmPrefab(prefab); - - // Execute - var results = VRMMeshIntegratorUtility.Integrate(instance, clips, excludes); - - // disable source renderer - foreach (var res in results) - { - foreach (var renderer in res.SourceSkinnedMeshRenderers) - { - Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); - renderer.gameObject.SetActive(false); - } - - foreach (var renderer in res.SourceMeshRenderers) - { - Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); - renderer.gameObject.SetActive(false); - } - } - - foreach (var result in results) - { - if (result.IntegratedRenderer == null) continue; - - var assetPath = writeAssetPath.Parent.Child($"{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"); - Debug.LogFormat("CreateAsset: {0}", assetPath); - assetPath.CreateAsset(result.IntegratedRenderer.sharedMesh); - Undo.RegisterCreatedObjectUndo(result.IntegratedRenderer.gameObject, "Integrate Renderers"); - } - - // Apply to Prefab - var prefabPath = UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(prefab)); - if (prefabPath.Equals(writeAssetPath)) - { - SkinnedMeshUtility.ApplyChangesToPrefab(instance); - } - else - { - PrefabUtility.SaveAsPrefabAsset(instance, writeAssetPath.Value, out bool success); - if (!success) - { - throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {writeAssetPath}"); - } - } - - // destroy source renderers - Object.DestroyImmediate(instance); - - return results; - } - - private static void BackupVrmPrefab(GameObject rootPrefab) - { - var proxy = rootPrefab.GetComponent(); - - var srcAvatar = proxy.BlendShapeAvatar; - var dstAvatar = (BlendShapeAvatar)BackupAsset(srcAvatar, rootPrefab); - - var clipMapper = srcAvatar.Clips.ToDictionary(x => x, x => (BlendShapeClip)BackupAsset(x, rootPrefab)); - dstAvatar.Clips = clipMapper.Values.ToList(); - - var dstPrefab = BackupAsset(rootPrefab, rootPrefab); - var dstInstance = SkinnedMeshUtility.InstantiatePrefab(dstPrefab); - dstInstance.GetComponent().BlendShapeAvatar = dstAvatar; - SkinnedMeshUtility.ApplyChangesToPrefab(dstInstance); - Object.DestroyImmediate(dstInstance); - } - - private static T BackupAsset(T asset, GameObject rootPrefab) where T : UnityEngine.Object - { - var srcAssetPath = UnityPath.FromAsset(asset); - var assetName = srcAssetPath.FileName; - - var backupDir = "MeshIntegratorBackup"; - var backupPath = UnityPath.FromAsset(rootPrefab).Parent.Child(backupDir); - backupPath.EnsureFolder(); - var dstAssetPath = backupPath.Child(assetName); - - AssetDatabase.CopyAsset(srcAssetPath.Value, dstAssetPath.Value); - return dstAssetPath.LoadAsset(); - } - - private static string GetRootPrefabPath(GameObject go) - { - var prefab = SkinnedMeshUtility.IsPrefab(go) ? go : SkinnedMeshUtility.GetPrefab(go); - var assetPath = ""; - if (prefab != null) - { - var prefabPath = AssetDatabase.GetAssetPath(prefab); - assetPath = string.Format("{0}/", Path.GetDirectoryName(prefabPath)); - } - else - { - assetPath = string.Format("Assets/"); - } - assetPath = assetPath.Replace(@"\", @"/"); - return assetPath; - } - } -} diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs deleted file mode 100644 index 20c05a315..000000000 --- a/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace VRM -{ - public static class SkinnedMeshUtility - { - public const string MENU_KEY = "GameObject/UnityEditorScripts/"; - public const int MENU_PRIORITY = 11; - - public static Object GetPrefab(GameObject instance) - { -#if UNITY_2018_2_OR_NEWER - return PrefabUtility.GetCorrespondingObjectFromSource(instance); -#else - return PrefabUtility.GetPrefabParent(go); -#endif - } - - public static bool IsPrefab(Object instance) - { - if (instance == null) - { - return false; - } - if (PrefabUtility.GetPrefabAssetType(instance) != PrefabAssetType.Regular) - { - return false; - } - return true; - } - - public static void ApplyChangesToPrefab(GameObject instance) - { - var prefab = GetPrefab(instance); - if (prefab == null) - { - return; - } - - var path = AssetDatabase.GetAssetPath(prefab); - if (string.IsNullOrEmpty(path)) - { - return; - } - - PrefabUtility.SaveAsPrefabAssetAndConnect(instance, path, InteractionMode.AutomatedAction); - } - - public static GameObject InstantiatePrefab(GameObject prefab) - { - if (!IsPrefab(prefab)) return null; - - return (GameObject)PrefabUtility.InstantiatePrefab(prefab); - } - } -} \ No newline at end of file diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs.meta b/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs.meta deleted file mode 100644 index 6cda243d5..000000000 --- a/Assets/VRM/Editor/SkinnedMeshUtility/SkinnedMeshUtility.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d66a91f4b51e42a6b165fe39fdb48d64 -timeCreated: 1559541677 \ No newline at end of file diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs similarity index 58% rename from Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs rename to Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index 4ef7304cb..3f991627b 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -6,14 +6,34 @@ using System; using System.Collections.Generic; using UniGLTF.MeshUtility; using System.IO; +using UniGLTF.M17N; namespace VRM { - public class MeshIntegratorWizard : ScriptableWizard + public class VrmMeshIntegratorWizard : ScriptableWizard { + const string ASSET_SUFFIX = ".mesh.asset"; + + enum HelpMessage + { + Ready, + SetTarget, + InvalidTarget, + } + + enum ValidationError + { + None, + NoTarget, + HasParent, + } + [SerializeField] GameObject m_root; + [SerializeField] + bool m_separateByBlendShape = true; + [Header("Validation")] [SerializeField] Material[] m_uniqueMaterials; @@ -74,11 +94,12 @@ namespace VRM public static void CreateWizard() { - ScriptableWizard.DisplayWizard("MeshIntegratorWizard", "Integrate and close window", "Integrate"); + ScriptableWizard.DisplayWizard("MeshIntegratorWizard", "Integrate and close window", "Integrate"); } private void OnEnable() { + Clear(HelpMessage.Ready, ValidationError.None); m_root = Selection.activeGameObject; OnValidate(); } @@ -125,19 +146,32 @@ namespace VRM return key; } + void Clear(HelpMessage help, ValidationError error) + { + helpString = help.Msg(); + errorString = error != ValidationError.None ? error.Msg() : null; + m_uniqueMaterials = new Material[] { }; + m_duplicateMaterials = new MaterialList[] { }; + m_excludes.Clear(); + isValid = false; + } + void OnValidate() { - if (m_root == null - || !PrefabUtility.IsPartOfAnyPrefab(m_root) || m_root.transform.parent != null) + if (m_root == null) { - Debug.LogWarning("Invalidate"); - m_uniqueMaterials = new Material[] { }; - m_duplicateMaterials = new MaterialList[] { }; - m_excludes.Clear(); + Clear(HelpMessage.SetTarget, ValidationError.NoTarget); return; } - Debug.Log("OnValidate"); + if (m_root.transform.parent != null) + { + Clear(HelpMessage.InvalidTarget, ValidationError.HasParent); + return; + } + + Clear(HelpMessage.Ready, ValidationError.None); + isValid = true; m_uniqueMaterials = MeshIntegratorUtility.EnumerateSkinnedMeshRenderer(m_root.transform, MeshEnumerateOption.OnlyWithoutBlendShape) .SelectMany(x => x.sharedMaterials) .Distinct() @@ -180,18 +214,13 @@ namespace VRM void OnWizardUpdate() { - helpString = "select target mesh root"; + // helpString = "Set target gameobject `in scene`. Prefab not supported."; } void Integrate() { - if (m_root == null) - { - Debug.LogWarning("no root object"); - return; - } - var prefabPath = AssetDatabase.GetAssetPath(m_root); + Debug.Log(prefabPath); var path = EditorUtility.SaveFilePanel("save prefab", Path.GetDirectoryName(prefabPath), m_root.name, "prefab"); if (string.IsNullOrEmpty(path)) { @@ -206,20 +235,81 @@ namespace VRM } var excludes = m_excludes.Where(x => x.Exclude).Select(x => x.Mesh); - integrationResults = MeshIntegratorEditor.Integrate(m_root, assetPath, excludes).Select(x => x.MeshMap).ToArray(); + + // Backup Exists + VrmPrefabUtility.BackupVrmPrefab(m_root); + + Undo.RecordObject(m_root, "Mesh Integration"); + var instance = VrmPrefabUtility.InstantiatePrefab(m_root); + + var clips = new List(); + var proxy = instance.GetComponent(); + if (proxy != null && proxy.BlendShapeAvatar != null) + { + clips = proxy.BlendShapeAvatar.Clips; + } + foreach (var clip in clips) + { + Undo.RecordObject(clip, "Mesh Integration"); + } + + // Execute + var results = VRMMeshIntegratorUtility.Integrate(instance, clips, excludes, m_separateByBlendShape); + // integrationResults = MeshIntegratorEditor.Integrate(m_root, assetPath, excludes, m_separateByBlendShape).Select(x => x.MeshMap).ToArray(); + // public static List Integrate(GameObject prefab, UniGLTF.UnityPath writeAssetPath, IEnumerable excludes, bool separateByBlendShape) + + // disable source renderer + foreach (var res in results) + { + foreach (var renderer in res.SourceSkinnedMeshRenderers) + { + Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); + renderer.gameObject.SetActive(false); + } + + foreach (var renderer in res.SourceMeshRenderers) + { + Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); + renderer.gameObject.SetActive(false); + } + } + + foreach (var result in results) + { + if (result.IntegratedRenderer == null) continue; + + var childAssetPath = assetPath.Parent.Child($"{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"); + Debug.LogFormat("CreateAsset: {0}", childAssetPath); + childAssetPath.CreateAsset(result.IntegratedRenderer.sharedMesh); + Undo.RegisterCreatedObjectUndo(result.IntegratedRenderer.gameObject, "Integrate Renderers"); + } + + // Apply to Prefab + if (UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)) + { + VrmPrefabUtility.ApplyChangesToPrefab(instance); + } + else + { + PrefabUtility.SaveAsPrefabAsset(instance, assetPath.Value, out bool success); + if (!success) + { + throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {assetPath}"); + } + } + + // destroy source renderers + UnityEngine.Object.DestroyImmediate(instance); } void OnWizardCreate() { - Debug.Log("OnWizardCreate"); Integrate(); - // close } void OnWizardOtherButton() { - Debug.Log("OnWizardOtherButton"); Integrate(); } } diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs.meta b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs.meta similarity index 71% rename from Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs.meta rename to Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs.meta index 19c7bdf94..aec3bc01f 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorWizard.cs.meta +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 744f66c7013807b4cae1d38d2ecfff38 -timeCreated: 1518503829 -licenseType: Free +guid: 0c6fe206e704d2148be9fd6ede8ca4f0 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs new file mode 100644 index 000000000..574c7121c --- /dev/null +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs @@ -0,0 +1,105 @@ +using System.Linq; +using UniGLTF; +using UnityEditor; +using UnityEngine; + +namespace VRM +{ + public static class VrmPrefabUtility + { + const string BACKUP_DIR = "MeshIntegratorBackup"; + + public static GameObject InstantiatePrefab(GameObject prefab) + { + if (!IsPrefab(prefab)) return null; + + return (GameObject)PrefabUtility.InstantiatePrefab(prefab); + } + + static bool IsPrefab(Object instance) + { + if (instance == null) + { + return false; + } + if (PrefabUtility.GetPrefabAssetType(instance) != PrefabAssetType.Regular) + { + return false; + } + return true; + } + + public static void ApplyChangesToPrefab(GameObject instance) + { + var prefab = GetPrefab(instance); + if (prefab == null) + { + return; + } + + var path = AssetDatabase.GetAssetPath(prefab); + if (string.IsNullOrEmpty(path)) + { + return; + } + + PrefabUtility.SaveAsPrefabAssetAndConnect(instance, path, InteractionMode.AutomatedAction); + } + + static Object GetPrefab(GameObject instance) + { +#if UNITY_2018_2_OR_NEWER + return PrefabUtility.GetCorrespondingObjectFromSource(instance); +#else + return PrefabUtility.GetPrefabParent(go); +#endif + } + + /// + /// VRM prefab を ${prefab_dir}/MeshIntegratorBackup/ に複製する。 + /// + /// * prefab + /// * BlendShapeAvatar + /// * BlendShapeClip + /// + /// が複製される。 + /// + /// + public static void BackupVrmPrefab(GameObject rootPrefab) + { + var proxy = rootPrefab.GetComponent(); + + var srcAvatar = proxy.BlendShapeAvatar; + var dstAvatar = (BlendShapeAvatar)BackupAsset(srcAvatar, rootPrefab); + + var clipMapper = srcAvatar.Clips.ToDictionary(x => x, x => (BlendShapeClip)BackupAsset(x, rootPrefab)); + dstAvatar.Clips = clipMapper.Values.ToList(); + + var dstPrefab = BackupAsset(rootPrefab, rootPrefab); + var dstInstance = InstantiatePrefab(dstPrefab); + dstInstance.GetComponent().BlendShapeAvatar = dstAvatar; + ApplyChangesToPrefab(dstInstance); + Object.DestroyImmediate(dstInstance); + } + + /// + /// asset を ${prefab_dir}/MeshIntegratorBackup/ にコピーし、コピーしたアセットをロードして返す + /// + /// + /// + /// + /// + private static T BackupAsset(T asset, GameObject rootPrefab) where T : UnityEngine.Object + { + var srcAssetPath = UnityPath.FromAsset(asset); + var assetName = srcAssetPath.FileName; + + var backupPath = UnityPath.FromAsset(rootPrefab).Parent.Child(BACKUP_DIR); + backupPath.EnsureFolder(); + var dstAssetPath = backupPath.Child(assetName); + + AssetDatabase.CopyAsset(srcAssetPath.Value, dstAssetPath.Value); + return dstAssetPath.LoadAsset(); + } + } +} diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs.meta b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs.meta similarity index 71% rename from Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs.meta rename to Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs.meta index f87becc3d..9534b545b 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/MeshIntegratorEditor.cs.meta +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 648920943c26bde4b920119bdbb38f70 -timeCreated: 1518194696 -licenseType: Free +guid: 6d3e24cadf1393841988d0c53830b67e MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Editor/VrmTopMenu.cs b/Assets/VRM/Editor/VrmTopMenu.cs index a79dc302a..3ed060112 100644 --- a/Assets/VRM/Editor/VrmTopMenu.cs +++ b/Assets/VRM/Editor/VrmTopMenu.cs @@ -28,7 +28,7 @@ namespace VRM private static void FreezeTPose() => VRMHumanoidNormalizerMenu.Normalize(); [MenuItem(UserMenuPrefix + "/MeshIntegratorWizard", priority = 21)] - private static void OpenMeshIntegratorWizard() => MeshIntegratorWizard.CreateWizard(); + private static void OpenMeshIntegratorWizard() => VrmMeshIntegratorWizard.CreateWizard(); [MenuItem(UserMenuPrefix + "/Save SpringBone to JSON", validate = true)] private static bool SaveSpringBoneToJsonValidation() => VRMSpringBoneUtilityEditor.SaveSpringBoneToJsonValidation(); diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index d00cf8b78..fea51d76c 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -11,49 +11,32 @@ namespace VRM /// public static class VRMMeshIntegratorUtility { - public static bool IntegrateRuntime(GameObject vrmRootObject) - { - if (vrmRootObject == null) return false; - var proxy = vrmRootObject.GetComponent(); - if (proxy == null) return false; - var avatar = proxy.BlendShapeAvatar; - if (avatar == null) return false; - var clips = avatar.Clips; - - var results = Integrate(vrmRootObject, clips, null); - if (results.Any(x => x.IntegratedRenderer == null)) return false; - - foreach (var result in results) - { - foreach (var renderer in result.SourceSkinnedMeshRenderers) - { - Object.Destroy(renderer); - } - - foreach (var renderer in result.SourceMeshRenderers) - { - Object.Destroy(renderer); - } - } - - return true; - } - - public static List Integrate(GameObject root, List blendshapeClips, IEnumerable excludes) + public static List Integrate(GameObject root, List blendshapeClips, IEnumerable excludes, bool separateByBlendShape) { var result = new List(); - var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); - if (withoutBlendShape.IntegratedRenderer != null) + if (separateByBlendShape) { - result.Add(withoutBlendShape); - } + var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); + if (withoutBlendShape.IntegratedRenderer != null) + { + result.Add(withoutBlendShape); + } - var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); - if (onlyBlendShape.IntegratedRenderer != null) + var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); + if (onlyBlendShape.IntegratedRenderer != null) + { + result.Add(onlyBlendShape); + FollowBlendshapeRendererChange(blendshapeClips, onlyBlendShape, root); + } + } + else { - result.Add(onlyBlendShape); - FollowBlendshapeRendererChange(blendshapeClips, onlyBlendShape, root); + var integrated = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); + if (integrated.IntegratedRenderer != null) + { + result.Add(integrated); + } } return result;