From 54353520be6fbc240297f0a23c30c9d555dae8bf Mon Sep 17 00:00:00 2001
From: changyunjia <905640960@qq.com>
Date: Fri, 12 Jun 2026 10:38:10 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 -
Assets/SGModule/ApplePay.meta | 8 +
Assets/SGModule/ApplePay/README.md | 3 +
Assets/SGModule/ApplePay/README.md.meta | 7 +
Assets/SGModule/ApplePay/SGModule.meta | 3 +
Assets/SGModule/ApplePay/SGModule/Model.meta | 3 +
.../ApplePay/SGModule/Model/ApplePayModel.cs | 43 +
.../SGModule/Model/ApplePayModel.cs.meta | 3 +
.../SGModule/ApplePay/SGModule/Scripts.meta | 3 +
.../SGModule/Scripts/ApplePayBackType.cs | 18 +
.../SGModule/Scripts/ApplePayBackType.cs.meta | 3 +
.../SGModule/Scripts/ApplePayManager.cs | 911 ++++++++
.../SGModule/Scripts/ApplePayManager.cs.meta | 3 +
.../ApplePay/SGModule/Scripts/ApplePayNet.cs | 95 +
.../SGModule/Scripts/ApplePayNet.cs.meta | 3 +
.../SGModule/Scripts/ProductConfig.cs | 22 +
.../SGModule/Scripts/ProductConfig.cs.meta | 3 +
Assets/SGModule/Common.meta | 8 +
Assets/SGModule/Common/README.md | 138 ++
Assets/SGModule/Common/README.md.meta | 7 +
Assets/SGModule/Common/SGModule.meta | 8 +
Assets/SGModule/Common/SGModule/Editor.meta | 8 +
.../SGModule/Editor/GameConfigCreator.cs | 75 +
.../SGModule/Editor/GameConfigCreator.cs.meta | 3 +
.../SGModule/Editor/GameConfigEditor.cs | 39 +
.../SGModule/Editor/GameConfigEditor.cs.meta | 3 +
.../Editor/HardwareAccelerationSetter.cs | 94 +
.../Editor/HardwareAccelerationSetter.cs.meta | 3 +
.../SGModule/Editor/NetworkConfigCreator.cs | 78 +
.../Editor/NetworkConfigCreator.cs.meta | 3 +
Assets/SGModule/Common/SGModule/Plugins.meta | 8 +
.../SGModule/Common/SGModule/Plugins/iOS.meta | 8 +
.../SGModule/Plugins/iOS/KeychainPlugin.mm | 66 +
.../Plugins/iOS/KeychainPlugin.mm.meta | 3 +
Assets/SGModule/Common/SGModule/Scripts.meta | 8 +
.../Common/SGModule/Scripts/Base.meta | 8 +
.../Scripts/Base/SingletonMonoBehaviour.cs | 57 +
.../Base/SingletonMonoBehaviour.cs.meta | 3 +
.../Common/SGModule/Scripts/ConfigManager.cs | 30 +
.../SGModule/Scripts/ConfigManager.cs.meta | 3 +
.../Common/SGModule/Scripts/Extensions.meta | 8 +
.../Scripts/Extensions/ArrayExtensions.cs | 14 +
.../Extensions/ArrayExtensions.cs.meta | 3 +
.../Scripts/Extensions/EnumExtensions.cs | 12 +
.../Scripts/Extensions/EnumExtensions.cs.meta | 3 +
.../Scripts/Extensions/ListExtensions.cs | 22 +
.../Scripts/Extensions/ListExtensions.cs.meta | 3 +
.../Scripts/Extensions/ObjectExtensions.cs | 302 +++
.../Extensions/ObjectExtensions.cs.meta | 3 +
.../Scripts/Extensions/StringExtensions.cs | 7 +
.../Extensions/StringExtensions.cs.meta | 3 +
.../SGModule/Common/SGModule/Scripts/GM.meta | 3 +
.../Common/SGModule/Scripts/GM/GMTool.cs | 367 ++++
.../Common/SGModule/Scripts/GM/GMTool.cs.meta | 11 +
.../Common/SGModule/Scripts/Helper.meta | 8 +
.../SGModule/Scripts/Helper/Base64Helper.cs | 26 +
.../Scripts/Helper/Base64Helper.cs.meta | 3 +
.../SGModule/Scripts/Helper/CommonUtils.cs | 21 +
.../Scripts/Helper/CommonUtils.cs.meta | 3 +
.../Common/SGModule/Scripts/Helper/Cryptor.cs | 35 +
.../SGModule/Scripts/Helper/Cryptor.cs.meta | 3 +
.../SGModule/Scripts/Helper/DeviceHelper.cs | 23 +
.../Scripts/Helper/DeviceHelper.cs.meta | 2 +
.../Common/SGModule/Scripts/Helper/Log.cs | 115 +
.../SGModule/Scripts/Helper/Log.cs.meta | 3 +
.../SGModule/Scripts/Helper/MD5Helper.cs | 60 +
.../SGModule/Scripts/Helper/MD5Helper.cs.meta | 3 +
.../SGModule/Scripts/Helper/ModuleVersion.cs | 59 +
.../Scripts/Helper/ModuleVersion.cs.meta | 3 +
.../SGModule/Scripts/Helper/RandomHelper.cs | 29 +
.../Scripts/Helper/RandomHelper.cs.meta | 3 +
.../Scripts/Helper/SerializeHelper.cs | 40 +
.../Scripts/Helper/SerializeHelper.cs.meta | 3 +
.../SGModule/Scripts/Helper/TimeHelper.cs | 54 +
.../Scripts/Helper/TimeHelper.cs.meta | 3 +
.../Common/SGModule/Scripts/Interface.meta | 3 +
.../SGModule/Scripts/Interface/IWeighted.cs | 7 +
.../Scripts/Interface/IWeighted.cs.meta | 3 +
.../Common/SGModule/Scripts/Keychain.meta | 8 +
.../SGModule/Scripts/Keychain/Keychain.cs | 46 +
.../Scripts/Keychain/Keychain.cs.meta | 2 +
.../SGModule/Scripts/ScriptableObjects.meta | 8 +
.../Scripts/ScriptableObjects/GameConfig.cs | 24 +
.../ScriptableObjects/GameConfig.cs.meta | 11 +
.../ScriptableObjects/NetworkConfig.cs | 18 +
.../ScriptableObjects/NetworkConfig.cs.meta | 3 +
Assets/SGModule/ConfigLoader.meta | 8 +
Assets/SGModule/ConfigLoader/README.md | 70 +
Assets/SGModule/ConfigLoader/README.md.meta | 7 +
Assets/SGModule/ConfigLoader/SGModule.meta | 8 +
.../ConfigLoader/SGModule/Editor.meta | 8 +
.../SGModule/Editor/AddressablesManager.cs | 188 ++
.../Editor/AddressablesManager.cs.meta | 3 +
.../ConfigLoader/SGModule/Scripts.meta | 8 +
.../SGModule/Scripts/ConfigLoader.meta | 8 +
.../Scripts/ConfigLoader/ConfigDataManager.cs | 53 +
.../ConfigLoader/ConfigDataManager.cs.meta | 3 +
.../Scripts/ConfigLoader/ConfigFileManager.cs | 167 ++
.../ConfigLoader/ConfigFileManager.cs.meta | 3 +
.../Scripts/ConfigLoader/ConfigInitOptions.cs | 42 +
.../ConfigLoader/ConfigInitOptions.cs.meta | 3 +
.../Scripts/ConfigLoader/ConfigLoader.cs | 69 +
.../Scripts/ConfigLoader/ConfigLoader.cs.meta | 3 +
.../ConfigLoader/FileNetworkManager.cs | 235 ++
.../ConfigLoader/FileNetworkManager.cs.meta | 3 +
.../SGModule/Scripts/ConfigParser.meta | 3 +
.../ConfigParser/ConfigKeyAttribute.cs | 19 +
.../ConfigParser/ConfigKeyAttribute.cs.meta | 3 +
.../Scripts/ConfigParser/ConfigParser.cs | 114 +
.../Scripts/ConfigParser/ConfigParser.cs.meta | 3 +
.../ConfigParser/ParseConfigOptions.cs | 20 +
.../ConfigParser/ParseConfigOptions.cs.meta | 3 +
Assets/SGModule/DataStorage.meta | 8 +
Assets/SGModule/DataStorage/README.md | 139 ++
Assets/SGModule/DataStorage/README.md.meta | 7 +
Assets/SGModule/DataStorage/SGModule.meta | 8 +
.../DataStorage/SGModule/Plugins.meta | 8 +
.../SGModule/Plugins/Easy Save 3.meta | 8 +
.../SGModule/Plugins/Easy Save 3/Editor.meta | 8 +
.../Easy Save 3/Editor/AddES3Prefab.cs | 88 +
.../Easy Save 3/Editor/AddES3Prefab.cs.meta | 12 +
.../Easy Save 3/Editor/AutoSaveWindow.cs | 369 ++++
.../Easy Save 3/Editor/AutoSaveWindow.cs.meta | 12 +
.../Easy Save 3/Editor/ChangeReferenceID.cs | 93 +
.../Editor/ChangeReferenceID.cs.meta | 11 +
.../Easy Save 3/Editor/ES3AutoSaveEditor.cs | 21 +
.../Editor/ES3AutoSaveEditor.cs.meta | 12 +
.../Editor/ES3AutoSaveMgrEditor.cs | 20 +
.../Editor/ES3AutoSaveMgrEditor.cs.meta | 12 +
.../Easy Save 3/Editor/ES3EditorStyle.cs | 84 +
.../Easy Save 3/Editor/ES3EditorStyle.cs.meta | 12 +
.../Easy Save 3/Editor/ES3EditorUtility.cs | 60 +
.../Editor/ES3EditorUtility.cs.meta | 12 +
.../Easy Save 3/Editor/ES3GameObjectEditor.cs | 46 +
.../Editor/ES3GameObjectEditor.cs.meta | 11 +
.../Editor/ES3GlobalReferencesEditor.cs | 91 +
.../Editor/ES3GlobalReferencesEditor.cs.meta | 12 +
.../Editor/ES3InspectorInfoEditor.cs | 14 +
.../Editor/ES3InspectorInfoEditor.cs.meta | 12 +
.../Easy Save 3/Editor/ES3PlayMakerEditor.cs | 803 +++++++
.../Editor/ES3PlayMakerEditor.cs.meta | 12 +
.../Easy Save 3/Editor/ES3Postprocessor.cs | 269 +++
.../Editor/ES3Postprocessor.cs.meta | 12 +
.../Easy Save 3/Editor/ES3PrefabEditor.cs | 50 +
.../Editor/ES3PrefabEditor.cs.meta | 12 +
.../Editor/ES3ReferenceMgrEditor.cs | 296 +++
.../Editor/ES3ReferenceMgrEditor.cs.meta | 12 +
.../Editor/ES3ScriptingDefineSymbols.cs | 128 ++
.../Editor/ES3ScriptingDefineSymbols.cs.meta | 11 +
.../Easy Save 3/Editor/ES3SettingsEditor.cs | 56 +
.../Editor/ES3SettingsEditor.cs.meta | 12 +
.../Plugins/Easy Save 3/Editor/ES3Window.cs | 238 ++
.../Easy Save 3/Editor/ES3Window.cs.meta | 12 +
.../Editor/EnableES3AssemblyDefinitions.cs | 23 +
.../EnableES3AssemblyDefinitions.cs.meta | 11 +
.../Plugins/Easy Save 3/Editor/HomeWindow.cs | 70 +
.../Easy Save 3/Editor/HomeWindow.cs.meta | 12 +
.../Easy Save 3/Editor/ReferencesWindow.cs | 21 +
.../Editor/ReferencesWindow.cs.meta | 12 +
.../Easy Save 3/Editor/SettingsWindow.cs | 179 ++
.../Easy Save 3/Editor/SettingsWindow.cs.meta | 12 +
.../Plugins/Easy Save 3/Editor/ToolsWindow.cs | 155 ++
.../Easy Save 3/Editor/ToolsWindow.cs.meta | 12 +
.../Plugins/Easy Save 3/Editor/TypesWindow.cs | 728 +++++++
.../Easy Save 3/Editor/TypesWindow.cs.meta | 12 +
.../Plugins/Easy Save 3/PlayMaker.meta | 8 +
.../Easy Save 3/PlayMaker/ES3PlayMaker.cs | 1907 +++++++++++++++++
.../PlayMaker/ES3PlayMaker.cs.meta | 12 +
.../Plugins/Easy Save 3/Resources.meta | 8 +
.../Plugins/Easy Save 3/Resources/ES3.meta | 8 +
.../Resources/ES3/ES3Defaults.asset | 56 +
.../Resources/ES3/ES3Defaults.asset.meta | 8 +
.../SGModule/Plugins/Easy Save 3/Scripts.meta | 8 +
.../Easy Save 3/Scripts/Attributes.meta | 8 +
.../Scripts/Attributes/ES3Attributes.cs | 7 +
.../Scripts/Attributes/ES3Attributes.cs.meta | 11 +
.../Easy Save 3/Scripts/Auto Save.meta | 8 +
.../Scripts/Auto Save/ES3AutoSave.cs | 55 +
.../Scripts/Auto Save/ES3AutoSave.cs.meta | 12 +
.../Scripts/Auto Save/ES3AutoSaveMgr.cs | 195 ++
.../Scripts/Auto Save/ES3AutoSaveMgr.cs.meta | 12 +
.../Easy Save 3/Scripts/Debugging.meta | 8 +
.../Easy Save 3/Scripts/Debugging/ES3Debug.cs | 52 +
.../Scripts/Debugging/ES3Debug.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/ES3.cs | 1660 ++++++++++++++
.../Plugins/Easy Save 3/Scripts/ES3.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/ES3Crypto.cs | 208 ++
.../Easy Save 3/Scripts/ES3Crypto.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/ES3File.cs | 524 +++++
.../Easy Save 3/Scripts/ES3File.cs.meta | 12 +
.../Easy Save 3/Scripts/ES3GameObject.cs | 20 +
.../Easy Save 3/Scripts/ES3GameObject.cs.meta | 11 +
.../Plugins/Easy Save 3/Scripts/ES3IO.cs | 181 ++
.../Plugins/Easy Save 3/Scripts/ES3IO.cs.meta | 12 +
.../Easy Save 3/Scripts/ES3InspectorInfo.cs | 19 +
.../Scripts/ES3InspectorInfo.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/ES3Prefab.cs | 218 ++
.../Easy Save 3/Scripts/ES3Prefab.cs.meta | 12 +
.../Easy Save 3/Scripts/ES3ReferenceMgr.cs | 262 +++
.../Scripts/ES3ReferenceMgr.cs.meta | 12 +
.../Scripts/ES3ReferenceMgrBase.cs | 758 +++++++
.../Scripts/ES3ReferenceMgrBase.cs.meta | 12 +
.../Easy Save 3/Scripts/ES3Reflection.cs | 794 +++++++
.../Easy Save 3/Scripts/ES3Reflection.cs.meta | 12 +
.../Scripts/ES3SerializableDictionary.cs | 88 +
.../Scripts/ES3SerializableDictionary.cs.meta | 12 +
.../Easy Save 3/Scripts/ES3Spreadsheet.cs | 307 +++
.../Scripts/ES3Spreadsheet.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/Readers.meta | 8 +
.../Scripts/Readers/ES3JSONReader.cs | 571 +++++
.../Scripts/Readers/ES3JSONReader.cs.meta | 12 +
.../Easy Save 3/Scripts/Readers/ES3Reader.cs | 459 ++++
.../Scripts/Readers/ES3Reader.cs.meta | 12 +
.../Scripts/Readers/ES3XMLReader.cs | 5 +
.../Scripts/Readers/ES3XMLReader.cs.meta | 11 +
.../Easy Save 3/Scripts/Referencing.meta | 8 +
.../Referencing/ES3GlobalReferences.cs | 129 ++
.../Referencing/ES3GlobalReferences.cs.meta | 11 +
.../Easy Save 3/Scripts/Save Slots.meta | 8 +
.../Scripts/Save Slots/ES3CreateSlot.cs | 82 +
.../Scripts/Save Slots/ES3CreateSlot.cs.meta | 11 +
.../Easy Save 3/Scripts/Save Slots/ES3Slot.cs | 150 ++
.../Scripts/Save Slots/ES3Slot.cs.meta | 11 +
.../Scripts/Save Slots/ES3SlotDialog.cs | 29 +
.../Scripts/Save Slots/ES3SlotDialog.cs.meta | 11 +
.../Scripts/Save Slots/ES3SlotManager.cs | 208 ++
.../Scripts/Save Slots/ES3SlotManager.cs.meta | 11 +
.../Plugins/Easy Save 3/Scripts/Settings.meta | 8 +
.../Scripts/Settings/ES3DefaultSettings.cs | 13 +
.../Settings/ES3DefaultSettings.cs.meta | 12 +
.../Scripts/Settings/ES3Defaults.cs | 24 +
.../Scripts/Settings/ES3Defaults.cs.meta | 11 +
.../Scripts/Settings/ES3Settings.cs | 386 ++++
.../Scripts/Settings/ES3Settings.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/Streams.meta | 8 +
.../Scripts/Streams/ES3FileStream.cs | 68 +
.../Scripts/Streams/ES3FileStream.cs.meta | 12 +
.../Scripts/Streams/ES3PlayerPrefsStream.cs | 63 +
.../Streams/ES3PlayerPrefsStream.cs.meta | 12 +
.../Scripts/Streams/ES3ResourcesStream.cs | 32 +
.../Streams/ES3ResourcesStream.cs.meta | 12 +
.../Easy Save 3/Scripts/Streams/ES3Stream.cs | 123 ++
.../Scripts/Streams/ES3Stream.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/Types.meta | 8 +
.../Scripts/Types/Collection Types.meta | 8 +
.../Types/Collection Types/ES32DArrayType.cs | 150 ++
.../Collection Types/ES32DArrayType.cs.meta | 12 +
.../Types/Collection Types/ES33DArrayType.cs | 164 ++
.../Collection Types/ES33DArrayType.cs.meta | 12 +
.../Types/Collection Types/ES3ArrayType.cs | 98 +
.../Collection Types/ES3ArrayType.cs.meta | 12 +
.../Collection Types/ES3CollectionType.cs | 119 +
.../ES3CollectionType.cs.meta | 12 +
.../ES3ConcurrentDictionaryType.cs | 142 ++
.../ES3ConcurrentDictionaryType.cs.meta | 12 +
.../Collection Types/ES3DictionaryType.cs | 142 ++
.../ES3DictionaryType.cs.meta | 12 +
.../Types/Collection Types/ES3HashSetType.cs | 90 +
.../Collection Types/ES3HashSetType.cs.meta | 12 +
.../Types/Collection Types/ES3ListType.cs | 110 +
.../Collection Types/ES3ListType.cs.meta | 12 +
.../Collection Types/ES3NativeArrayType.cs | 74 +
.../ES3NativeArrayType.cs.meta | 12 +
.../Types/Collection Types/ES3QueueType.cs | 147 ++
.../Collection Types/ES3QueueType.cs.meta | 12 +
.../Types/Collection Types/ES3StackType.cs | 151 ++
.../Collection Types/ES3StackType.cs.meta | 12 +
.../Types/Collection Types/ES3TupleType.cs | 78 +
.../Collection Types/ES3TupleType.cs.meta | 12 +
.../Collection Types/ES3Type_ArrayList.cs | 66 +
.../ES3Type_ArrayList.cs.meta | 11 +
.../Scripts/Types/ES3ComponentType.cs | 145 ++
.../Scripts/Types/ES3ComponentType.cs.meta | 12 +
.../Scripts/Types/ES3ObjectType.cs | 80 +
.../Scripts/Types/ES3ObjectType.cs.meta | 12 +
.../Easy Save 3/Scripts/Types/ES3Property.cs | 30 +
.../Scripts/Types/ES3Property.cs.meta | 12 +
.../Scripts/Types/ES3ScriptableObjectType.cs | 75 +
.../Types/ES3ScriptableObjectType.cs.meta | 12 +
.../Easy Save 3/Scripts/Types/ES3Type.cs | 194 ++
.../Easy Save 3/Scripts/Types/ES3Type.cs.meta | 12 +
.../Easy Save 3/Scripts/Types/ES3TypeMgr.cs | 161 ++
.../Scripts/Types/ES3TypeMgr.cs.meta | 12 +
.../Scripts/Types/ES3UnityObjectType.cs | 123 ++
.../Scripts/Types/ES3UnityObjectType.cs.meta | 12 +
.../Easy Save 3/Scripts/Types/NET Types.meta | 8 +
.../Types/NET Types/ES3Type_BigInteger.cs | 38 +
.../NET Types/ES3Type_BigInteger.cs.meta | 12 +
.../Scripts/Types/NET Types/ES3Type_Random.cs | 71 +
.../Types/NET Types/ES3Type_Random.cs.meta | 12 +
.../Scripts/Types/NET Types/ES3Type_Type.cs | 27 +
.../Types/NET Types/ES3Type_Type.cs.meta | 12 +
.../Scripts/Types/Primitive Types.meta | 8 +
.../Types/Primitive Types/ES3Type_DateTime.cs | 37 +
.../Primitive Types/ES3Type_DateTime.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_ES3Ref.cs | 57 +
.../Primitive Types/ES3Type_ES3Ref.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_UIntPtr.cs | 37 +
.../Primitive Types/ES3Type_UIntPtr.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_bool.cs | 37 +
.../Primitive Types/ES3Type_bool.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_byte.cs | 27 +
.../Primitive Types/ES3Type_byte.cs.meta | 12 +
.../Primitive Types/ES3Type_byteArray.cs | 27 +
.../Primitive Types/ES3Type_byteArray.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_char.cs | 33 +
.../Primitive Types/ES3Type_char.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_decimal.cs | 37 +
.../Primitive Types/ES3Type_decimal.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_double.cs | 37 +
.../Primitive Types/ES3Type_double.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_enum.cs | 59 +
.../Primitive Types/ES3Type_enum.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_float.cs | 37 +
.../Primitive Types/ES3Type_float.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_int.cs | 37 +
.../Types/Primitive Types/ES3Type_int.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_intptr.cs | 37 +
.../Primitive Types/ES3Type_intptr.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_long.cs | 37 +
.../Primitive Types/ES3Type_long.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_sbyte.cs | 37 +
.../Primitive Types/ES3Type_sbyte.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_short.cs | 37 +
.../Primitive Types/ES3Type_short.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_string.cs | 37 +
.../Primitive Types/ES3Type_string.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_uint.cs | 37 +
.../Primitive Types/ES3Type_uint.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_ulong.cs | 37 +
.../Primitive Types/ES3Type_ulong.cs.meta | 12 +
.../Types/Primitive Types/ES3Type_ushort.cs | 37 +
.../Primitive Types/ES3Type_ushort.cs.meta | 12 +
.../Scripts/Types/Reflected Types.meta | 8 +
.../ES3ReflectedComponentType.cs | 24 +
.../ES3ReflectedComponentType.cs.meta | 12 +
.../Reflected Types/ES3ReflectedObjectType.cs | 35 +
.../ES3ReflectedObjectType.cs.meta | 12 +
.../ES3ReflectedScriptableObjectType.cs | 27 +
.../ES3ReflectedScriptableObjectType.cs.meta | 12 +
.../Types/Reflected Types/ES3ReflectedType.cs | 119 +
.../Reflected Types/ES3ReflectedType.cs.meta | 12 +
.../ES3ReflectedUnityObjectType.cs | 35 +
.../ES3ReflectedUnityObjectType.cs.meta | 12 +
.../Reflected Types/ES3ReflectedValueType.cs | 38 +
.../ES3ReflectedValueType.cs.meta | 12 +
.../Scripts/Types/Unity Types.meta | 8 +
.../Types/Unity Types/Component Types.meta | 8 +
.../Component Types/ES3Type_BoxCollider.cs | 66 +
.../ES3Type_BoxCollider.cs.meta | 12 +
.../Component Types/ES3Type_BoxCollider2D.cs | 66 +
.../ES3Type_BoxCollider2D.cs.meta | 12 +
.../Component Types/ES3Type_Camera.cs | 165 ++
.../Component Types/ES3Type_Camera.cs.meta | 12 +
.../ES3Type_CapsuleCollider.cs | 73 +
.../ES3Type_CapsuleCollider.cs.meta | 12 +
.../Component Types/ES3Type_EventSystem.cs | 31 +
.../ES3Type_EventSystem.cs.meta | 12 +
.../Component Types/ES3Type_Image.cs | 137 ++
.../Component Types/ES3Type_Image.cs.meta | 11 +
.../Component Types/ES3Type_MeshCollider.cs | 84 +
.../ES3Type_MeshCollider.cs.meta | 12 +
.../Component Types/ES3Type_MeshFilter.cs | 51 +
.../ES3Type_MeshFilter.cs.meta | 12 +
.../Component Types/ES3Type_MeshRenderer.cs | 116 +
.../ES3Type_MeshRenderer.cs.meta | 12 +
.../Component Types/ES3Type_ParticleSystem.cs | 149 ++
.../ES3Type_ParticleSystem.cs.meta | 12 +
.../ES3Type_PolygonCollider2D.cs | 87 +
.../ES3Type_PolygonCollider2D.cs.meta | 12 +
.../Component Types/ES3Type_RawImage.cs | 100 +
.../Component Types/ES3Type_RawImage.cs.meta | 11 +
.../Component Types/ES3Type_Rigidbody.cs | 153 ++
.../Component Types/ES3Type_Rigidbody.cs.meta | 11 +
.../Component Types/ES3Type_SphereCollider.cs | 64 +
.../ES3Type_SphereCollider.cs.meta | 12 +
.../Component Types/ES3Type_Text.cs | 148 ++
.../Component Types/ES3Type_Text.cs.meta | 11 +
.../Component Types/ES3Type_Transform.cs | 70 +
.../Component Types/ES3Type_Transform.cs.meta | 12 +
.../Unity Types/ES3Type_AnimationCurve.cs | 58 +
.../ES3Type_AnimationCurve.cs.meta | 12 +
.../Types/Unity Types/ES3Type_AudioClip.cs | 90 +
.../Unity Types/ES3Type_AudioClip.cs.meta | 12 +
.../Types/Unity Types/ES3Type_BoneWeight.cs | 61 +
.../Unity Types/ES3Type_BoneWeight.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Bounds.cs | 42 +
.../Types/Unity Types/ES3Type_Bounds.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Burst.cs | 77 +
.../Types/Unity Types/ES3Type_Burst.cs.meta | 11 +
.../Unity Types/ES3Type_CollisionModule.cs | 117 +
.../ES3Type_CollisionModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Color.cs | 44 +
.../Types/Unity Types/ES3Type_Color.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Color32.cs | 51 +
.../Types/Unity Types/ES3Type_Color32.cs.meta | 12 +
.../Unity Types/ES3Type_ColorBySpeedModule.cs | 58 +
.../ES3Type_ColorBySpeedModule.cs.meta | 12 +
.../ES3Type_ColorOverLifetimeModule.cs | 54 +
.../ES3Type_ColorOverLifetimeModule.cs.meta | 12 +
.../Unity Types/ES3Type_EmissionModule.cs | 74 +
.../ES3Type_EmissionModule.cs.meta | 12 +
.../ES3Type_ExternalForcesModule.cs | 54 +
.../ES3Type_ExternalForcesModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Flare.cs | 60 +
.../Types/Unity Types/ES3Type_Flare.cs.meta | 12 +
.../Scripts/Types/Unity Types/ES3Type_Font.cs | 57 +
.../Types/Unity Types/ES3Type_Font.cs.meta | 12 +
.../ES3Type_ForceOverLifetimeModule.cs | 82 +
.../ES3Type_ForceOverLifetimeModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_GameObject.cs | 320 +++
.../Unity Types/ES3Type_GameObject.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Gradient.cs | 55 +
.../Unity Types/ES3Type_Gradient.cs.meta | 12 +
.../Unity Types/ES3Type_GradientAlphaKey.cs | 41 +
.../ES3Type_GradientAlphaKey.cs.meta | 12 +
.../Unity Types/ES3Type_GradientColorKey.cs | 41 +
.../ES3Type_GradientColorKey.cs.meta | 12 +
.../Scripts/Types/Unity Types/ES3Type_Guid.cs | 37 +
.../Types/Unity Types/ES3Type_Guid.cs.meta | 12 +
.../ES3Type_InheritVelocityModule.cs | 62 +
.../ES3Type_InheritVelocityModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Keyframe.cs | 45 +
.../Unity Types/ES3Type_Keyframe.cs.meta | 12 +
.../Types/Unity Types/ES3Type_LayerMask.cs | 43 +
.../Unity Types/ES3Type_LayerMask.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Light.cs | 117 +
.../Types/Unity Types/ES3Type_Light.cs.meta | 12 +
.../Types/Unity Types/ES3Type_LightsModule.cs | 94 +
.../Unity Types/ES3Type_LightsModule.cs.meta | 12 +
...ES3Type_LimitVelocityOverLifetimeModule.cs | 94 +
...pe_LimitVelocityOverLifetimeModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_MainModule.cs | 206 ++
.../Unity Types/ES3Type_MainModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Material.cs | 1304 +++++++++++
.../Unity Types/ES3Type_Material.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Matrix4x4.cs | 47 +
.../Unity Types/ES3Type_Matrix4x4.cs.meta | 12 +
.../Scripts/Types/Unity Types/ES3Type_Mesh.cs | 169 ++
.../Types/Unity Types/ES3Type_Mesh.cs.meta | 12 +
.../Types/Unity Types/ES3Type_MinMaxCurve.cs | 114 +
.../Unity Types/ES3Type_MinMaxCurve.cs.meta | 12 +
.../Unity Types/ES3Type_MinMaxGradient.cs | 68 +
.../ES3Type_MinMaxGradient.cs.meta | 12 +
.../Types/Unity Types/ES3Type_NoiseModule.cs | 154 ++
.../Unity Types/ES3Type_NoiseModule.cs.meta | 12 +
.../Unity Types/ES3Type_PhysicMaterial.cs | 140 ++
.../ES3Type_PhysicMaterial.cs.meta | 12 +
.../Unity Types/ES3Type_PhysicsMaterial2D.cs | 59 +
.../ES3Type_PhysicsMaterial2D.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Quaternion.cs | 44 +
.../Unity Types/ES3Type_Quaternion.cs.meta | 12 +
.../Scripts/Types/Unity Types/ES3Type_Rect.cs | 35 +
.../Types/Unity Types/ES3Type_Rect.cs.meta | 12 +
.../Unity Types/ES3Type_RectTransform.cs | 96 +
.../Unity Types/ES3Type_RectTransform.cs.meta | 12 +
.../Unity Types/ES3Type_RenderTexture.cs | 165 ++
.../Unity Types/ES3Type_RenderTexture.cs.meta | 11 +
.../ES3Type_RotationBySpeedModule.cs | 82 +
.../ES3Type_RotationBySpeedModule.cs.meta | 12 +
.../ES3Type_RotationOverLifetimeModule.cs | 78 +
...ES3Type_RotationOverLifetimeModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Shader.cs | 61 +
.../Types/Unity Types/ES3Type_Shader.cs.meta | 12 +
.../Types/Unity Types/ES3Type_ShapeModule.cs | 132 ++
.../Unity Types/ES3Type_ShapeModule.cs.meta | 12 +
.../Unity Types/ES3Type_SizeBySpeedModule.cs | 90 +
.../ES3Type_SizeBySpeedModule.cs.meta | 12 +
.../ES3Type_SizeOverLifetimeModule.cs | 86 +
.../ES3Type_SizeOverLifetimeModule.cs.meta | 12 +
.../ES3Type_SkinnedMeshRenderer.cs | 157 ++
.../ES3Type_SkinnedMeshRenderer.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Sprite.cs | 69 +
.../Types/Unity Types/ES3Type_Sprite.cs.meta | 12 +
.../Unity Types/ES3Type_SpriteRenderer.cs | 126 ++
.../ES3Type_SpriteRenderer.cs.meta | 12 +
.../Unity Types/ES3Type_SubEmittersModule.cs | 86 +
.../ES3Type_SubEmittersModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Texture.cs | 45 +
.../Types/Unity Types/ES3Type_Texture.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Texture2D.cs | 132 ++
.../Unity Types/ES3Type_Texture2D.cs.meta | 12 +
.../ES3Type_TextureSheetAnimationModule.cs | 112 +
...S3Type_TextureSheetAnimationModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_TrailModule.cs | 106 +
.../Unity Types/ES3Type_TrailModule.cs.meta | 12 +
.../Unity Types/ES3Type_TriggerModule.cs | 70 +
.../Unity Types/ES3Type_TriggerModule.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Vector2.cs | 40 +
.../Types/Unity Types/ES3Type_Vector2.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Vector2Int.cs | 42 +
.../Unity Types/ES3Type_Vector2Int.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Vector3.cs | 42 +
.../Types/Unity Types/ES3Type_Vector3.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Vector3Int.cs | 44 +
.../Unity Types/ES3Type_Vector3Int.cs.meta | 12 +
.../Types/Unity Types/ES3Type_Vector4.cs | 50 +
.../Types/Unity Types/ES3Type_Vector4.cs.meta | 12 +
.../ES3Type_VelocityOverLifetimeModule.cs | 77 +
...ES3Type_VelocityOverLifetimeModule.cs.meta | 12 +
.../Types/Unity Types/UnityObjectType.cs | 18 +
.../Types/Unity Types/UnityObjectType.cs.meta | 11 +
.../Plugins/Easy Save 3/Scripts/Web.meta | 8 +
.../Easy Save 3/Scripts/Web/ES3Cloud.cs | 757 +++++++
.../Easy Save 3/Scripts/Web/ES3Cloud.cs.meta | 12 +
.../Easy Save 3/Scripts/Web/ES3WebClass.cs | 148 ++
.../Scripts/Web/ES3WebClass.cs.meta | 12 +
.../Plugins/Easy Save 3/Scripts/Writers.meta | 8 +
.../Easy Save 3/Scripts/Writers/ES3Binary.cs | 121 ++
.../Scripts/Writers/ES3Binary.cs.meta | 11 +
.../Scripts/Writers/ES3BinaryWriter.cs | 4 +
.../Scripts/Writers/ES3BinaryWriter.cs.meta | 11 +
.../Scripts/Writers/ES3CacheWriter.cs | 157 ++
.../Scripts/Writers/ES3CacheWriter.cs.meta | 12 +
.../Scripts/Writers/ES3JSONWriter.cs | 233 ++
.../Scripts/Writers/ES3JSONWriter.cs.meta | 12 +
.../Easy Save 3/Scripts/Writers/ES3Writer.cs | 512 +++++
.../Scripts/Writers/ES3Writer.cs.meta | 12 +
.../Scripts/Writers/ES3XMLWriter.cs | 4 +
.../Scripts/Writers/ES3XMLWriter.cs.meta | 11 +
.../DataStorage/SGModule/Scripts.meta | 8 +
.../SGModule/Scripts/DataStorage.meta | 3 +
.../SGModule/Scripts/DataStorage/DataKey.cs | 45 +
.../Scripts/DataStorage/DataKey.cs.meta | 3 +
.../Scripts/DataStorage/DataManager.cs | 381 ++++
.../Scripts/DataStorage/DataManager.cs.meta | 3 +
.../Scripts/DataStorage/DataStorage.cs | 50 +
.../Scripts/DataStorage/DataStorage.cs.meta | 3 +
Assets/SGModule/MarkdownKit.meta | 8 +
Assets/SGModule/MarkdownKit/README.md | 153 ++
Assets/SGModule/MarkdownKit/README.md.meta | 7 +
Assets/SGModule/MarkdownKit/SGModule.meta | 8 +
.../MarkdownKit/SGModule/Scripts.meta | 8 +
.../SGModule/Scripts/MakdownData.cs | 68 +
.../SGModule/Scripts/MakdownData.cs.meta | 3 +
.../SGModule/Scripts/MarkdownConvert.cs | 124 ++
.../SGModule/Scripts/MarkdownConvert.cs.meta | 3 +
.../SGModule/Scripts/MarkdownKit.cs | 227 ++
.../SGModule/Scripts/MarkdownKit.cs.meta | 11 +
Assets/SGModule/Net.meta | 8 +
Assets/SGModule/Net/README.md | 67 +
Assets/SGModule/Net/README.md.meta | 7 +
Assets/SGModule/Net/SGModule.meta | 8 +
Assets/SGModule/Net/SGModule/Scripts.meta | 8 +
.../SGModule/Net/SGModule/Scripts/Core.meta | 8 +
.../Net/SGModule/Scripts/Core/NetChecker.cs | 284 +++
.../SGModule/Scripts/Core/NetChecker.cs.meta | 3 +
.../Net/SGModule/Scripts/Core/NetCore.cs | 272 +++
.../Net/SGModule/Scripts/Core/NetCore.cs.meta | 3 +
.../Net/SGModule/Scripts/Core/ServerClock.cs | 20 +
.../SGModule/Scripts/Core/ServerClock.cs.meta | 3 +
.../Net/SGModule/Scripts/Core/TokenManager.cs | 204 ++
.../Scripts/Core/TokenManager.cs.meta | 3 +
.../SGModule/Net/SGModule/Scripts/Models.meta | 8 +
.../SGModule/Scripts/Models/NetCoreModel.cs | 6 +
.../Scripts/Models/NetCoreModel.cs.meta | 3 +
.../SGModule/Scripts/Models/ResponseData.cs | 21 +
.../Scripts/Models/ResponseData.cs.meta | 3 +
.../Net/SGModule/Scripts/WebSocket.meta | 3 +
.../Scripts/WebSocket/ResponseData.cs | 36 +
.../Scripts/WebSocket/ResponseData.cs.meta | 3 +
.../Scripts/WebSocket/WebSocketData.cs | 4 +
.../Scripts/WebSocket/WebSocketData.cs.meta | 3 +
.../Scripts/WebSocket/WebSocketEvent.cs | 6 +
.../Scripts/WebSocket/WebSocketEvent.cs.meta | 3 +
.../Scripts/WebSocket/WebSocketService.cs | 221 ++
.../WebSocket/WebSocketService.cs.meta | 3 +
.../Scripts/WebSocket/WebSocketTools.cs | 70 +
.../Scripts/WebSocket/WebSocketTools.cs.meta | 3 +
.../SGModule/com.endel.nativewebsocket.meta | 8 +
.../com.endel.nativewebsocket/WebSocket.meta | 8 +
.../WebSocket/WebSocket.cs | 848 ++++++++
.../WebSocket/WebSocket.cs.meta | 11 +
.../WebSocket/WebSocket.jslib | 333 +++
.../WebSocket/WebSocket.jslib.meta | 32 +
.../WebSocket/endel.nativewebsocket.asmdef | 3 +
.../endel.nativewebsocket.asmdef.meta | 7 +
.../WebSocketExample.meta | 8 +
.../com.endel.nativewebsocket/package.json | 32 +
.../package.json.meta | 7 +
Assets/SGModule/NetKit.meta | 8 +
Assets/SGModule/NetKit/README.md | 62 +
Assets/SGModule/NetKit/README.md.meta | 7 +
Assets/SGModule/NetKit/SGModule.meta | 3 +
Assets/SGModule/NetKit/SGModule/Model.meta | 8 +
.../SGModule/NetKit/SGModule/Model/H5Model.cs | 13 +
.../NetKit/SGModule/Model/H5Model.cs.meta | 3 +
.../NetKit/SGModule/Model/LoginModel.cs | 22 +
.../NetKit/SGModule/Model/LoginModel.cs.meta | 3 +
.../NetKit/SGModule/Model/OrderModel.cs | 30 +
.../NetKit/SGModule/Model/OrderModel.cs.meta | 3 +
.../NetKit/SGModule/Model/RequestLoginData.cs | 16 +
.../SGModule/Model/RequestLoginData.cs.meta | 3 +
.../SGModule/Model/RequestResultData.cs | 8 +
.../SGModule/Model/RequestResultData.cs.meta | 3 +
.../SGModule/Model/RequestSavePlayData.cs | 8 +
.../Model/RequestSavePlayData.cs.meta | 3 +
.../NetKit/SGModule/Model/RequestStageData.cs | 15 +
.../SGModule/Model/RequestStageData.cs.meta | 3 +
.../NetKit/SGModule/Model/RespDebugData.cs | 17 +
.../SGModule/Model/RespDebugData.cs.meta | 3 +
.../SGModule/Model/RespLoginFunnelData.cs | 14 +
.../Model/RespLoginFunnelData.cs.meta | 3 +
.../NetKit/SGModule/Model/TrackData.cs | 9 +
.../NetKit/SGModule/Model/TrackData.cs.meta | 3 +
Assets/SGModule/NetKit/SGModule/Scripts.meta | 8 +
.../NetKit/SGModule/Scripts/Core.meta | 3 +
.../NetKit/SGModule/Scripts/Core/NetKit.cs | 96 +
.../SGModule/Scripts/Core/NetKit.cs.meta | 3 +
.../NetKit/SGModule/Scripts/Kits.meta | 3 +
.../SGModule/Scripts/Kits/ErrorLogKit.cs | 85 +
.../SGModule/Scripts/Kits/ErrorLogKit.cs.meta | 3 +
.../SGModule/Scripts/Kits/HeartbeatKit.cs | 129 ++
.../Scripts/Kits/HeartbeatKit.cs.meta | 3 +
.../NetKit/SGModule/Scripts/Kits/LoginKit.cs | 111 +
.../SGModule/Scripts/Kits/LoginKit.cs.meta | 3 +
.../NetKit/SGModule/Scripts/Kits/NetGmTool.cs | 51 +
.../SGModule/Scripts/Kits/NetGmTool.cs.meta | 11 +
.../NetKit/SGModule/Scripts/Kits/Track.meta | 3 +
.../SGModule/Scripts/Kits/Track/TrackEvent.cs | 46 +
.../Scripts/Kits/Track/TrackEvent.cs.meta | 3 +
.../SGModule/Scripts/Kits/Track/TrackKit.cs | 139 ++
.../Scripts/Kits/Track/TrackKit.cs.meta | 3 +
.../Scripts/Kits/Track/TrackProperty.cs | 43 +
.../Scripts/Kits/Track/TrackProperty.cs.meta | 3 +
.../NetKit/SGModule/Scripts/NetApi.cs | 136 ++
.../NetKit/SGModule/Scripts/NetApi.cs.meta | 3 +
627 files changed, 38546 insertions(+), 2 deletions(-)
create mode 100644 Assets/SGModule/ApplePay.meta
create mode 100644 Assets/SGModule/ApplePay/README.md
create mode 100644 Assets/SGModule/ApplePay/README.md.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Model.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs
create mode 100644 Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs.meta
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs
create mode 100644 Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs.meta
create mode 100644 Assets/SGModule/Common.meta
create mode 100644 Assets/SGModule/Common/README.md
create mode 100644 Assets/SGModule/Common/README.md.meta
create mode 100644 Assets/SGModule/Common/SGModule.meta
create mode 100644 Assets/SGModule/Common/SGModule/Editor.meta
create mode 100644 Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs
create mode 100644 Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs
create mode 100644 Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs
create mode 100644 Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs
create mode 100644 Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Plugins.meta
create mode 100644 Assets/SGModule/Common/SGModule/Plugins/iOS.meta
create mode 100644 Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm
create mode 100644 Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Base.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/GM.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Interface.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Keychain.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs.meta
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs
create mode 100644 Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader.meta
create mode 100644 Assets/SGModule/ConfigLoader/README.md
create mode 100644 Assets/SGModule/ConfigLoader/README.md.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Editor.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs.meta
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs
create mode 100644 Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs.meta
create mode 100644 Assets/SGModule/DataStorage.meta
create mode 100644 Assets/SGModule/DataStorage/README.md
create mode 100644 Assets/SGModule/DataStorage/README.md.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/TypesWindow.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/TypesWindow.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/PlayMaker.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/PlayMaker/ES3PlayMaker.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/PlayMaker/ES3PlayMaker.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Resources.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Resources/ES3.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Resources/ES3/ES3Defaults.asset
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Resources/ES3/ES3Defaults.asset.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Attributes.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Attributes/ES3Attributes.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Attributes/ES3Attributes.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Auto Save.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Auto Save/ES3AutoSave.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Auto Save/ES3AutoSave.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Auto Save/ES3AutoSaveMgr.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Auto Save/ES3AutoSaveMgr.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Debugging.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Debugging/ES3Debug.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Debugging/ES3Debug.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Crypto.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Crypto.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3File.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3File.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3GameObject.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3GameObject.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3IO.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3IO.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3InspectorInfo.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3InspectorInfo.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Prefab.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Prefab.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3ReferenceMgr.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3ReferenceMgr.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3ReferenceMgrBase.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3ReferenceMgrBase.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Reflection.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Reflection.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3SerializableDictionary.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3SerializableDictionary.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Spreadsheet.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/ES3Spreadsheet.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3JSONReader.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3JSONReader.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3Reader.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3Reader.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3XMLReader.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Readers/ES3XMLReader.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Referencing.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Referencing/ES3GlobalReferences.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Referencing/ES3GlobalReferences.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3CreateSlot.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3CreateSlot.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3Slot.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3Slot.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3SlotDialog.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3SlotDialog.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3SlotManager.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Save Slots/ES3SlotManager.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3DefaultSettings.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3DefaultSettings.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3Defaults.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3Defaults.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3Settings.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Settings/ES3Settings.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3FileStream.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3FileStream.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3PlayerPrefsStream.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3PlayerPrefsStream.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3ResourcesStream.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3ResourcesStream.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3Stream.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Streams/ES3Stream.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES32DArrayType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES32DArrayType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES33DArrayType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES33DArrayType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ArrayType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ArrayType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3CollectionType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3CollectionType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ConcurrentDictionaryType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ConcurrentDictionaryType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3DictionaryType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3DictionaryType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3HashSetType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3HashSetType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ListType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3ListType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3NativeArrayType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3NativeArrayType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3QueueType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3QueueType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3StackType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3StackType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3TupleType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3TupleType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3Type_ArrayList.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Collection Types/ES3Type_ArrayList.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ComponentType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ComponentType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3Property.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3Property.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ScriptableObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3ScriptableObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3Type.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3Type.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3TypeMgr.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3TypeMgr.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3UnityObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/ES3UnityObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_BigInteger.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_BigInteger.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_Random.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_Random.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_Type.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/NET Types/ES3Type_Type.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_DateTime.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_DateTime.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ES3Ref.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ES3Ref.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_UIntPtr.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_UIntPtr.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_bool.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_bool.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_byte.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_byte.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_byteArray.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_byteArray.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_char.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_char.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_decimal.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_decimal.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_double.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_double.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_enum.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_enum.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_float.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_float.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_int.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_int.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_intptr.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_intptr.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_long.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_long.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_sbyte.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_sbyte.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_short.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_short.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_string.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_string.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_uint.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_uint.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ulong.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ulong.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ushort.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Primitive Types/ES3Type_ushort.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedComponentType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedComponentType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedScriptableObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedScriptableObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedUnityObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedUnityObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedValueType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Reflected Types/ES3ReflectedValueType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_BoxCollider.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_BoxCollider.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_BoxCollider2D.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_BoxCollider2D.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Camera.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Camera.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_CapsuleCollider.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_CapsuleCollider.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_EventSystem.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_EventSystem.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Image.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Image.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshCollider.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshCollider.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshFilter.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshFilter.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshRenderer.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_MeshRenderer.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_ParticleSystem.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_ParticleSystem.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_PolygonCollider2D.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_PolygonCollider2D.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_RawImage.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_RawImage.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Rigidbody.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Rigidbody.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_SphereCollider.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_SphereCollider.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Text.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Text.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Transform.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/Component Types/ES3Type_Transform.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_AnimationCurve.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_AnimationCurve.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_AudioClip.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_AudioClip.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_BoneWeight.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_BoneWeight.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Bounds.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Bounds.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Burst.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Burst.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_CollisionModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_CollisionModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Color.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Color.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Color32.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Color32.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ColorBySpeedModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ColorBySpeedModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ColorOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ColorOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_EmissionModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_EmissionModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ExternalForcesModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ExternalForcesModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Flare.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Flare.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Font.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Font.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ForceOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ForceOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GameObject.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GameObject.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Gradient.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Gradient.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GradientAlphaKey.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GradientAlphaKey.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GradientColorKey.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_GradientColorKey.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Guid.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Guid.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_InheritVelocityModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_InheritVelocityModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Keyframe.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Keyframe.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LayerMask.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LayerMask.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Light.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Light.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LightsModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LightsModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LimitVelocityOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_LimitVelocityOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MainModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MainModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Material.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Material.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Matrix4x4.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Matrix4x4.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Mesh.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Mesh.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MinMaxCurve.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MinMaxCurve.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MinMaxGradient.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_MinMaxGradient.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_NoiseModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_NoiseModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_PhysicMaterial.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_PhysicMaterial.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_PhysicsMaterial2D.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_PhysicsMaterial2D.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Quaternion.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Quaternion.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Rect.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Rect.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RectTransform.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RectTransform.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RenderTexture.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RenderTexture.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RotationBySpeedModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RotationBySpeedModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RotationOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_RotationOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Shader.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Shader.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ShapeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_ShapeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SizeBySpeedModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SizeBySpeedModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SizeOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SizeOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SkinnedMeshRenderer.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SkinnedMeshRenderer.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Sprite.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Sprite.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SpriteRenderer.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SpriteRenderer.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SubEmittersModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_SubEmittersModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Texture.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Texture.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Texture2D.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Texture2D.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TextureSheetAnimationModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TextureSheetAnimationModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TrailModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TrailModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TriggerModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_TriggerModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector2.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector2.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector2Int.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector2Int.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector3.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector3.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector3Int.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector3Int.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector4.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_Vector4.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_VelocityOverLifetimeModule.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/ES3Type_VelocityOverLifetimeModule.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/UnityObjectType.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Types/Unity Types/UnityObjectType.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Web.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Web/ES3Cloud.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Web/ES3Cloud.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Web/ES3WebClass.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Web/ES3WebClass.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3Binary.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3Binary.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3BinaryWriter.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3BinaryWriter.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3CacheWriter.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3CacheWriter.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3JSONWriter.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3JSONWriter.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3Writer.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3Writer.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3XMLWriter.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Scripts/Writers/ES3XMLWriter.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataKey.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataKey.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataManager.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataManager.cs.meta
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataStorage.cs
create mode 100644 Assets/SGModule/DataStorage/SGModule/Scripts/DataStorage/DataStorage.cs.meta
create mode 100644 Assets/SGModule/MarkdownKit.meta
create mode 100644 Assets/SGModule/MarkdownKit/README.md
create mode 100644 Assets/SGModule/MarkdownKit/README.md.meta
create mode 100644 Assets/SGModule/MarkdownKit/SGModule.meta
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MakdownData.cs
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MakdownData.cs.meta
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MarkdownConvert.cs
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MarkdownConvert.cs.meta
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MarkdownKit.cs
create mode 100644 Assets/SGModule/MarkdownKit/SGModule/Scripts/MarkdownKit.cs.meta
create mode 100644 Assets/SGModule/Net.meta
create mode 100644 Assets/SGModule/Net/README.md
create mode 100644 Assets/SGModule/Net/README.md.meta
create mode 100644 Assets/SGModule/Net/SGModule.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/NetChecker.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/NetChecker.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/NetCore.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/NetCore.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/ServerClock.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/ServerClock.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/TokenManager.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Core/TokenManager.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Models.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Models/NetCoreModel.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Models/NetCoreModel.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Models/ResponseData.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/Models/ResponseData.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/ResponseData.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/ResponseData.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketData.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketData.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketEvent.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketEvent.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketService.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketService.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketTools.cs
create mode 100644 Assets/SGModule/Net/SGModule/Scripts/WebSocket/WebSocketTools.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/WebSocket.cs
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/WebSocket.cs.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/WebSocket.jslib
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/WebSocket.jslib.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/endel.nativewebsocket.asmdef
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocket/endel.nativewebsocket.asmdef.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/WebSocketExample.meta
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/package.json
create mode 100644 Assets/SGModule/Net/SGModule/com.endel.nativewebsocket/package.json.meta
create mode 100644 Assets/SGModule/NetKit.meta
create mode 100644 Assets/SGModule/NetKit/README.md
create mode 100644 Assets/SGModule/NetKit/README.md.meta
create mode 100644 Assets/SGModule/NetKit/SGModule.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/H5Model.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/H5Model.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/LoginModel.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/LoginModel.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/OrderModel.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/OrderModel.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestLoginData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestLoginData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestResultData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestResultData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestSavePlayData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestSavePlayData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestStageData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RequestStageData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RespDebugData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RespDebugData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RespLoginFunnelData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/RespLoginFunnelData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/TrackData.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Model/TrackData.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Core.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Core/NetKit.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Core/NetKit.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/ErrorLogKit.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/ErrorLogKit.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/HeartbeatKit.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/HeartbeatKit.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/LoginKit.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/LoginKit.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/NetGmTool.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/NetGmTool.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackEvent.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackEvent.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackKit.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackKit.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackProperty.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/Kits/Track/TrackProperty.cs.meta
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/NetApi.cs
create mode 100644 Assets/SGModule/NetKit/SGModule/Scripts/NetApi.cs.meta
diff --git a/.gitignore b/.gitignore
index b6f6517..4f06cb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,5 +30,3 @@ UserSettings/Layouts/*.dwlt
Assets/StreamingAssets.meta
**/.DS_Store
-Assets/SGModule/
-/Assets/SGModule
diff --git a/Assets/SGModule/ApplePay.meta b/Assets/SGModule/ApplePay.meta
new file mode 100644
index 0000000..bc11499
--- /dev/null
+++ b/Assets/SGModule/ApplePay.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0d950573b18d12a44b3432ed180749fb
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ApplePay/README.md b/Assets/SGModule/ApplePay/README.md
new file mode 100644
index 0000000..46e9e3b
--- /dev/null
+++ b/Assets/SGModule/ApplePay/README.md
@@ -0,0 +1,3 @@
+# ApplePay
+
+2025 年 05 月 24 日 V1.0.0 提交初始版本 applepay 模块,该模块功能依赖通用模块,网络模块和数据模块,请一起拉取
diff --git a/Assets/SGModule/ApplePay/README.md.meta b/Assets/SGModule/ApplePay/README.md.meta
new file mode 100644
index 0000000..173e892
--- /dev/null
+++ b/Assets/SGModule/ApplePay/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: f92f9691c788c414a82e03722722293e
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ApplePay/SGModule.meta b/Assets/SGModule/ApplePay/SGModule.meta
new file mode 100644
index 0000000..c1ff908
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 10ce64fc727c4edeb97e73ad29ef5eab
+timeCreated: 1747906541
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Model.meta b/Assets/SGModule/ApplePay/SGModule/Model.meta
new file mode 100644
index 0000000..23b0fbf
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Model.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f2da583c874f4b13acc3eb54eaf5a428
+timeCreated: 1747996053
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs b/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs
new file mode 100644
index 0000000..67722f5
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs
@@ -0,0 +1,43 @@
+using Newtonsoft.Json;
+
+namespace SGModule.ApplePay
+{
+ public class ApplePayData
+ {
+ [JsonProperty("innerOrderId")]
+ public string innerOrderId;
+ [JsonProperty("amount")]
+ public int amount;
+ [JsonProperty("sku")]
+ public string sku;
+ [JsonProperty("currency")]
+ public string currency = "USD";
+ [JsonProperty("shopName")]
+ public string shopName;
+ [JsonProperty("type")]
+ public string type;
+
+ }
+
+ public class AppleCheckData
+ {
+ [JsonProperty("signedPayload")]
+ public string signedPayload;
+ [JsonProperty("innerOrderId")]
+ public string innerOrderId;
+ }
+
+ public class AppleSubscribeData
+ {
+ [JsonProperty("signedPayload")]
+ public string signedPayload;
+ [JsonProperty("sku")]
+ public string sku;
+ [JsonProperty("currency")]
+ public string currency;
+ [JsonProperty("amount")]
+ public int amount;
+ [JsonProperty("expires_time")]
+ public long expires_time;
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs.meta b/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs.meta
new file mode 100644
index 0000000..9735972
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Model/ApplePayModel.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9dcbc72e1537449aaea5b71d67e7bf85
+timeCreated: 1747996070
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts.meta b/Assets/SGModule/ApplePay/SGModule/Scripts.meta
new file mode 100644
index 0000000..f90f3ee
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 69666ded8fdc4244a0d43d25f7831bca
+timeCreated: 1747906570
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs
new file mode 100644
index 0000000..96803fb
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs
@@ -0,0 +1,18 @@
+namespace SGModule.ApplePay
+{
+ public enum ApplePayBackType
+ {
+ ///
+ ///创建支付订单
+ ///
+ Create,
+ ///
+ ///验证支付订单
+ ///
+ Check,
+ ///
+ ///取消支付订单
+ ///
+ Cancel,
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs.meta b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs.meta
new file mode 100644
index 0000000..9a439fa
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayBackType.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e83ae38d5d0e4880836c55d708e7083c
+timeCreated: 1747995062
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs
new file mode 100644
index 0000000..9ae29b8
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs
@@ -0,0 +1,911 @@
+using SGModule.Common.Base;
+using System;
+using System.Collections.Generic;
+using SGModule.Common.Helper;
+using SGModule.NetKit;
+using LoveLegend;
+using Newtonsoft.Json.Linq;
+
+
+#if UNITY_IOS && UNITY_IAP
+using System.Collections;
+using System.Linq;
+using DG.Tweening;
+using SGModule.Common.Extensions;
+using Newtonsoft.Json;
+using SGModule.Net;
+using UnityEngine;
+using UnityEngine.Purchasing;
+using UnityEngine.Purchasing.Extension;
+
+namespace SGModule.ApplePay
+{
+ public class ApplePayManager : SingletonMonoBehaviour, IDetailedStoreListener
+ {
+ private IStoreController _storeController;
+ private static IExtensionProvider _extensionProvider;
+ private static IAppleExtensions _appleExtension;
+
+ private Action _failedCallback;
+
+ private Action _successCallback;
+
+ private Dictionary _products = new Dictionary();
+
+ private ApplePayData _payData;
+
+ private string _packageName;
+
+ private float _lastPayAttemptTime;
+ private Dictionary _innerData = new();
+
+
+ public void SendDebugToServer(string error, string stackTrace)
+ {
+
+ ErrorLogKit.Send("debug", error, stackTrace, SuperApplication.Instance.attribution);
+ }
+
+ private Dictionary _productConfigs = new Dictionary();
+
+ ///
+ /// 通过 ProductConfig 数组初始化商品
+ ///
+ public void InitProduct(List configs, string packageName, Action successCallback)
+ {
+ var module = StandardPurchasingModule.Instance();
+ ConfigurationBuilder builder = ConfigurationBuilder.Instance(module);
+
+ _successCallback = successCallback;
+ _packageName = packageName;
+ SendDebugToServer("[Apple pay] InitProduct 开始------", Environment.StackTrace);
+ try
+ {
+ foreach (var config in configs)
+ {
+ Debug.Log($"[Apple pay] InitProduct ------{config.sku} , {config.type} ");
+ if (Enum.TryParse(config.type, true, out var productType))
+ {
+ _productConfigs.Add(config.sku, config);
+
+ builder.AddProduct(config.sku, productType);
+ }
+ else
+ {
+ SendDebugToServer($"无法解析 ProductType: {config.type}", Environment.StackTrace);
+ Debug.LogError($"无法解析 ProductType: {config.type}");
+ // 可根据需要处理默认类型或跳过该商品
+ }
+ }
+
+ SendDebugToServer("[Apple pay] InitProduct 结束------", Environment.StackTrace);
+ UnityPurchasing.Initialize(this, builder);
+ }
+ catch (Exception e)
+ {
+ SendDebugToServer($" 初始化商品 失败 InitProduct: {e.Message}", Environment.StackTrace);
+
+ Console.WriteLine(e);
+ throw;
+ }
+
+ Debug.Log($"[Apple pay] InitProduct -----2 ");
+
+ }
+
+
+ private void SetPayData(string sku)
+ {
+ var payData = GetPayData(sku);
+ _payData = payData;
+
+ }
+
+ private ApplePayData GetPayData(string sku)
+ {
+ if (_productConfigs.TryGetValue(sku, out var data))
+ {
+ Debug.Log($"[Apple pay] InitProduct ------{data.sku} , {data.type} ");
+ return new ApplePayData
+ {
+ sku = sku,
+ currency = "USD",
+ amount = (int)Math.Round(data.price * 100),
+ };
+ }
+ Debug.LogError($" set _payData error------_payData is null ");
+ return null;
+ }
+
+ private Coroutine _payDataCheckCoroutine;
+
+ ///
+ /// 启动_payData超时检测协程
+ ///
+ private void StartPayDataTimeoutCheck()
+ {
+ if (_payDataCheckCoroutine != null)
+ {
+ StopCoroutine(_payDataCheckCoroutine);
+ }
+ _payDataCheckCoroutine = StartCoroutine(PayDataTimeoutCheck());
+ }
+
+ ///
+ /// 检测_payData是否超时的协程
+ ///
+ private IEnumerator PayDataTimeoutCheck()
+ {
+ float startTime = Time.time;
+ float timeout = 60f; // 1分钟超时
+
+ while (Time.time - startTime < timeout)
+ {
+ // 如果_payData已经为null,停止检测
+ if (_payData == null)
+ {
+ yield break;
+ }
+ yield return null;
+ }
+
+ // 1分钟后检查,如果_payData仍然不为null,则设为null
+ if (_payData != null)
+ {
+ _innerData = null;
+ _payData = null;
+ Debug.Log("[Apple Pay] _payData超时,已自动设为null");
+ }
+ }
+
+ ///
+ /// 购买接口
+ ///
+ /// 购买需要的字段存放
+ /// 成功回调(ApplePayBackType为订单返回的类型:具体看 ApplePayBackType 枚举),作用:用来打点
+ /// 失败回调 (string为失败原因)
+ public void Purchase(string sku, Action successCallback, Action failedCallback)
+ {
+ Debug.Log($"[Apple Pay] Purchase: {JsonConvert.SerializeObject(_payData)}");
+
+ SendDebugToServer("[Apple pay] 购买 Purchase ------", Environment.StackTrace);
+
+ if (Time.time - _lastPayAttemptTime < 5)
+ {
+ failedCallback?.Invoke("Clicks are too frequent");
+ return;
+ }
+
+ _lastPayAttemptTime = Time.time;
+ Debug.Log($"[Apple Pay] Purchase-00---------{JsonConvert.SerializeObject(_payData)}");
+ if (_payData != null)
+ {
+ if (_payData.sku.Contains("sub"))//假如是订阅直接清理
+ {
+ _payData = null;
+ }
+ else
+ {
+ // 启动超时检测
+ StartPayDataTimeoutCheck();
+ return;
+ }
+ }
+
+ Debug.Log($"[Apple Pay] Purchase-1---------");
+
+ if (!IsInitialized())
+ {
+ failedCallback?.Invoke("Not Initialized");
+ return;
+ }
+
+ Debug.Log($"[Apple Pay] Purchase-2---------");
+
+ var product = _storeController.products.WithID(sku);
+ if (product == null || !product.availableToPurchase)
+ {
+ failedCallback?.Invoke("Either is not found or is not available for purchase");
+ return;
+ }
+
+ _successCallback = successCallback;
+ _failedCallback = failedCallback;
+
+ SetPayData(sku);
+
+ _storeController.InitiatePurchase(product);
+
+ Debug.Log($"[Apple Pay] Purchase-3---------");
+
+ if (_payData != null)
+ {
+ var payData = new ApplePayData
+ {
+ sku = sku,
+ currency = "USD",
+ amount = _payData.amount,
+ };
+
+ ApplePayNet.ApplePayCreate(payData, (response) =>
+ {
+ Debug.Log($"[Apple Pay] Purchase-4---------");
+
+ if (response.IsSuccess)
+ {
+ _successCallback?.Invoke(ApplePayBackType.Create, null);
+
+ if (_innerData == null) _innerData = new();
+ Debug.Log($"[Apple pay] Purchase--5-innerOrderId-------{response.Data.innerOrderId}");
+ if (_payData != null && response.Data.innerOrderId != null)
+ {
+ Debug.Log($"[Apple pay] Purchase-555555-innerOrderId");
+ _payData.innerOrderId = response.Data.innerOrderId;
+ _innerData[response.Data.innerOrderId] = sku;
+ SaveInnerIdData(_innerData);
+ }
+ }
+
+ // if (_payData != null) _payData.innerOrderId = response.Data.innerOrderId;
+ SendDebugToServer($"[Apple Pay] Purchase-5-------创建内部ID innerOrderId--{_payData.innerOrderId}", Environment.StackTrace);
+
+ Debug.Log($"[Apple Pay] Purchase-5-------innerOrderId--{_payData.innerOrderId}");
+ if (payData.sku.Contains("sub") && DataMgr.VipLevel.Value >= 1)
+ {
+ // PlayerPrefs.SetInt("need_getvip", 1);
+ DOVirtual.DelayedCall(10, () =>
+ {
+ GetVipHistory();
+ }).SetLoops(3);
+ }
+ });
+ }
+ }
+ public static void GetVipHistory()
+ {
+ // if (PlayerPrefs.GetInt("need_getvip", 1) == 0) return;
+ // PlayerPrefs.DeleteAll();
+ string orig_tx_id = PlayerPrefs.GetString("orig_tx_id", "");
+ HistoryObject obj_ = new HistoryObject() { id = orig_tx_id };
+ if (string.IsNullOrEmpty(orig_tx_id))
+ {
+ ApplePayNet.ApplePaySubscriptionHistory>((response) =>
+ {
+ // Debug.Log(JsonConvert.SerializeObject(response.Data));
+ string tx_id_ = null;
+ for (int i = 0; i < response.Data.Count; i++)
+ {
+ PlayerPrefs.SetString("orig_tx_id", response.Data[i].orig_tx_id);
+ tx_id_ = response.Data[i].orig_tx_id;
+ }
+ if (!string.IsNullOrEmpty(tx_id_))
+ {
+ obj_.id = tx_id_;
+ SubscriptionCheck(obj_);
+ }
+ });
+
+ return;
+ }
+ else
+ {
+ SubscriptionCheck(obj_);
+ }
+
+ }
+ public static void SubscriptionCheck(HistoryObject obj_)
+ {
+ ApplePayNet.ApplePaySubscriptionCheck(obj_, (response) =>
+ {
+ int vip_level = -1;
+ long end_time = 0;
+ if (response != null && response.Data != null)
+ {
+ Debug.Log(JsonConvert.SerializeObject(response.Data));
+ if (response.Data.renew_time > end_time)
+ {
+ end_time = response.Data.renew_time;
+ if (response.Data.renew_sku == PurchasingManager.GetPaySku(PayType.yearly_subscription))
+ {
+ vip_level = 3;
+ }
+ else if (response.Data.renew_sku == PurchasingManager.GetPaySku(PayType.monthly_subscription))
+ {
+ vip_level = 2;
+ }
+ else if (response.Data.renew_sku == PurchasingManager.GetPaySku(PayType.weekly_subscription))
+ {
+ vip_level = 1;
+ }
+ DataMgr.VipExpirationTime.Value = end_time;
+ if (DataMgr.VipLevel.Value != vip_level)
+ {
+ DataMgr.VipLevel.Value = vip_level;
+ GameDispatcher.Instance.Dispatch(GameMsg.BuyVip);
+ }
+ }
+ }
+ });
+ }
+ ///
+ /// IOS恢复内购
+ /// 会在删除应用后,第一次安装是自动恢复
+ ///
+ /// 恢复回调
+ public void AppleRestore(Action restoreCallback)
+ {
+ if (!IsInitialized())
+ {
+ Debug.LogWarning("[ApplePay] IAppleExtensions 未初始化");
+ return;
+ }
+
+ Debug.Log("[ApplePay] 用户手动恢复购买");
+ _appleExtension.RestoreTransactions((success, error) =>
+ {
+ if (success)
+ {
+ Debug.Log("[Apple Pay] Restore Transactions 成功");
+ // 这里会触发 ProcessPurchase 回调
+ restoreCallback(true, error);
+ }
+ else
+ {
+ Debug.LogError($"[Apple Pay] Restore Transactions 失败: {error}");
+ // 可以提示用户重试
+ }
+ });
+ }
+
+ #region 购买成功回调
+
+ private Dictionary _pendingProducts = new Dictionary();
+ public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs purchaseEvent)
+ {
+ SendDebugToServer($"[Apple pay] 购买成功回调 Purchase ---{JsonConvert.SerializeObject(purchaseEvent.purchasedProduct)}---", Environment.StackTrace);
+
+ var product = purchaseEvent.purchasedProduct;
+ var productType = product.definition.type;
+ var sku = product.definition.id;
+ var receipt = product.receipt;
+
+ Debug.Log(
+ $" ProcessPurchase 1 Purchase: {JsonConvert.SerializeObject(purchaseEvent.purchasedProduct)}");
+
+
+ Debug.Log(
+ $" ProcessPurchase 1 receipt: {receipt}");
+
+ if (purchaseEvent is not { purchasedProduct: not null })
+ {
+ Debug.LogError("[Apple Pay] ProcessPurchase 2 : purchaseEvent 或 purchasedProduct 为 null");
+ return PurchaseProcessingResult.Complete;
+ }
+
+ Debug.Log($"购买商品类型: {productType}, SKU: {sku}");
+ if (productType == ProductType.NonConsumable)
+ {
+ Debug.Log(
+ $" 识别到非消耗性商品 ----{DataMgr.ApplePayTransactionID.Value.Contains(product.transactionID)}");
+ var innerdata = GetInnerIdData();
+ if (innerdata == null) // 重启情况
+ {
+ Debug.Log("innerdata----" + innerdata);
+ _successCallback(ApplePayBackType.Check, new AppleResponseData()
+ {
+ sku = sku
+ });
+ DataMgr.ApplePayTransactionID.Value.Add(product.transactionID);
+ return PurchaseProcessingResult.Complete;
+ }
+ Debug.Log("innerdata---2-");
+ if (DataMgr.ApplePayTransactionID.Value.Contains(product.transactionID))
+ {
+ return PurchaseProcessingResult.Complete;
+ }
+ DataMgr.ApplePayTransactionID.Value.Add(product.transactionID);
+ }
+
+ // if (DataMgr.clearAllOrder.Value)
+ // {
+ // _innerData = null;
+ // _payData = null;
+ // // 保存更新后的数据
+ // SaveApplePayData(null);
+ // SaveInnerIdData(null);
+ // return PurchaseProcessingResult.Complete;
+ // }
+
+ string txId = product.transactionID;
+ _pendingProducts[txId] = product; // ✅ 安全暂存
+
+ if (productType == ProductType.Subscription)
+ {
+ SendDebugToServer($"[Apple pay] 购买商品类型 Purchase ---{productType}-{sku}--", Environment.StackTrace);
+
+ // 服务器验证
+ UploadReceiptForValidation(sku, product.transactionID, isSuccess =>
+ {
+ if (isSuccess)
+ {
+ var product_temp = FindPendingProductByTransactionId(purchaseEvent.purchasedProduct.transactionID);
+ // 验证成功后的逻辑
+ // 验证成功,完成购买
+ _storeController.ConfirmPendingPurchase(product_temp);
+ }
+ });
+
+ return PurchaseProcessingResult.Pending;
+ }
+
+ // 普通商品直接处理
+ HandlePurchaseSuccess(purchaseEvent, isSuccess =>
+ {
+ if (isSuccess)
+ {
+ var product_temp = FindPendingProductByTransactionId(purchaseEvent.purchasedProduct.transactionID);
+ var productType = product_temp.definition.type;
+ Debug.Log(
+ $"ConfirmPendingPurchase : {purchaseEvent.purchasedProduct.transactionID}, sku: {product_temp.definition.id}");
+ // 验证成功,完成购买
+ _storeController.ConfirmPendingPurchase(product_temp);
+ }
+ });
+
+ return PurchaseProcessingResult.Pending;
+ }
+
+ private Product FindPendingProductByTransactionId(string txId)
+ {
+ _pendingProducts.TryGetValue(txId, out var product);
+ _pendingProducts.Remove(txId); // ✅ 用完即删,避免内存泄漏
+ return product;
+ }
+
+ ///
+ /// 支付测试代码
+ ///
+ ///
+ ///
+ ///
+ public void ApplePayTest(ProductType type, string sku, string transactionID, Action successCallback)
+ {
+
+ SetPayData(sku);
+ Debug.Log($"[ApplePay] 测试支付 type: {type}, sku: {sku}, transactionID: {transactionID}");
+
+ _successCallback = successCallback;
+
+ if (type == ProductType.Subscription)
+ {
+ // 服务器验证
+ UploadReceiptForValidation(sku, transactionID, isSuccess =>
+ {
+ if (isSuccess)
+ {
+ Debug.Log("订阅商品验证成功");
+ }
+ });
+
+ return;
+ }
+
+ if (type == ProductType.NonConsumable)
+ {
+ Debug.Log(
+ $" 识别到非消耗性商品 ----{DataMgr.ApplePayTransactionID.Value.Contains(transactionID)}");
+ if (DataMgr.ApplePayTransactionID.Value.Contains(transactionID))
+ {
+ return;
+ }
+
+ DataMgr.ApplePayTransactionID.Value.Add(transactionID);
+ }
+
+ // 普通商品直接处理
+ // HandlePurchaseSuccess(transactionID, isSuccess =>
+ // {
+ // if (isSuccess)
+ // {
+ // Debug.Log("普通商品验证成功");
+ // }
+ // }, true);
+ }
+
+ //服务器验证
+ private void UploadReceiptForValidation(string sku, string transactionID, Action onValidationComplete)
+ {
+ Debug.Log("识别到订阅商品,准备进行订阅验证");
+ SendDebugToServer($"[Apple pay] 识别到订阅商品,准备进行订阅验证", Environment.StackTrace);
+
+ var productConfig = GetPayData(sku);
+ if (productConfig != null)
+ {
+ Debug.Log($"订阅商品ID: {sku} transactionID: {transactionID} _payData.amount: {productConfig.amount}");
+
+ SendDebugToServer($"订阅商品ID: {sku} transactionID: {transactionID} _payData.amount: {productConfig.amount}", Environment.StackTrace);
+
+ ApplePayNet.AppleSubscribeCheck(
+ transactionID,
+ sku,
+ productConfig.amount,
+ _packageName,
+ response =>
+ {
+ bool isSuccess = response.IsSuccess;
+
+ // 在这里返回验证结果
+ onValidationComplete?.Invoke(isSuccess);
+ _payData = null;
+ if (isSuccess)
+ {
+ Debug.Log("订阅验证成功");
+ SendDebugToServer($"订阅验证成功", Environment.StackTrace);
+
+ _successCallback?.Invoke(ApplePayBackType.Check, new AppleResponseData()
+ {
+ expires_time = response.Data.expires_time,
+ sku = sku
+ });
+ }
+ else
+ {
+ Debug.LogWarning("[Apple Pay] 订阅验证失败");
+ }
+ });
+ }
+ }
+
+ ///
+ /// 支付成功后的本地处理(订阅和普通商品共用)
+ ///
+ private void HandlePurchaseSuccess(PurchaseEventArgs purchaseEvent, Action onValidationComplete, bool isTest = false)
+ {
+ var payDataJson = GetApplePayData();
+ Debug.Log($" HandlePurchaseSuccess payDataJson: {JsonConvert.SerializeObject(payDataJson)}");
+
+ var statusDictionary = JsonConvert.DeserializeObject>(payDataJson)
+ ?? new Dictionary();
+
+ string transactionID = purchaseEvent.purchasedProduct.transactionID;
+ string sku = purchaseEvent.purchasedProduct.definition.id;
+ Debug.Log($"[Apple pay] 购买成功: transactionID: {transactionID} sku: {sku}");
+ // var receiptObj = JObject.Parse(purchaseEvent.purchasedProduct.receipt);
+
+ // var payload = JObject.Parse((string)receiptObj["Payload"]);
+ // var jsonData = JObject.Parse((string)payload["json"]);
+
+ SendDebugToServer($"普通商品 HandlePurchaseSuccess: {transactionID}", Environment.StackTrace);
+
+ if (!statusDictionary.ContainsKey(transactionID))
+ {
+ Debug.Log($"记录新交易 transactionID: {transactionID}");
+ Debug.Log($"-----_payData: {JsonConvert.SerializeObject(_payData)}");
+
+ if (_payData == null || string.IsNullOrWhiteSpace(_payData.innerOrderId))
+ {
+ Debug.Log("[Apple pay] _payData 为空或 innerOrderId 无效");
+ var innerdata = GetInnerIdData();
+ var isFind = false;
+ Debug.Log($" HandlePurchaseSuccess innerdata: {JsonConvert.SerializeObject(innerdata)}");
+ if (innerdata != null)
+ {
+ foreach (var item in innerdata)
+ {
+ Debug.Log(
+ $" HandlePurchaseSuccess item: {item.Key} {item.Value} jsonData productId=={sku}");
+ if (item.Value == sku)
+ {
+ SetPayData(purchaseEvent.purchasedProduct.definition.id);
+ _payData.innerOrderId = item.Key;
+ // _payData = new()
+ // {
+ // innerOrderId = item.Key,
+ // };
+ isFind = true;
+ break;
+ }
+ }
+ }
+
+ if (!isFind)
+ {
+ Debug.LogWarning("[Apple pay] 内部订单ID 无效");
+ onValidationComplete?.Invoke(false);
+ return;
+ }
+ }
+
+ statusDictionary.Add(transactionID, _payData);
+ SaveApplePayData(statusDictionary);
+ _innerData = null;
+ _payData = null;
+ }
+
+ if (statusDictionary.TryGetValue(transactionID, out var cValue))
+ {
+ if (!string.IsNullOrWhiteSpace(cValue.innerOrderId) || isTest)
+ {
+ ApplePaySuccess(transactionID, onValidationComplete);
+ }
+ }
+ }
+
+ private void SaveApplePayData(Dictionary payData)
+ {
+ // 保存更新后的数据
+ string json = JsonConvert.SerializeObject(payData);
+ PlayerPrefs.SetString("SGModule_apple_pay_data", json);
+ }
+
+ private string GetApplePayData()
+ {
+ string json = PlayerPrefs.GetString("SGModule_apple_pay_data", "");
+ // GetString if (json == "")
+ // {
+ // json = DataWrapper.ApplePayData;
+ // }
+ return json;
+ }
+
+ private void SaveInnerIdData(Dictionary innerData)
+ {
+ // 保存更新后的数据
+ string json = JsonConvert.SerializeObject(innerData);
+ Debug.Log($"[Inner save Data] ==: {json}");
+ PlayerPrefs.SetString("SGModule_inner_order_id", json);
+ }
+
+ private Dictionary GetInnerIdData()
+ {
+ string json = PlayerPrefs.GetString("SGModule_inner_order_id", "");
+ Debug.Log($"[Inner get Data] ==: {json}");
+ return JsonConvert.DeserializeObject>(json);
+ }
+
+ private Queue<(string transactionID, Action onValidationComplete)> _pendingRequests = new Queue<(string, Action)>();
+ private bool _isProcessing = false; // 标记是否正在处理中
+ private HashSet _processedOrPendingTx = new HashSet();
+ private void ApplePaySuccess(string transactionID, Action onValidationComplete)
+ {
+ // 入队前去重
+ if (_processedOrPendingTx.Contains(transactionID))
+ {
+ Debug.LogWarning($"Duplicate TX ignored: {transactionID}");
+ onValidationComplete?.Invoke(false);
+ return;
+ }
+ _processedOrPendingTx.Add(transactionID);
+
+ Debug.Log($"[ApplePaySuccess] Received transaction: {transactionID}");
+ _pendingRequests.Enqueue((transactionID, onValidationComplete));
+ TryProcessNext();
+
+ }
+
+ private void TryProcessNext()
+ {
+ if (_isProcessing || _pendingRequests.Count == 0)
+ return;
+
+ var (txId, callback) = _pendingRequests.Dequeue();
+ _isProcessing = true;
+ Debug.Log("apple 支付 StartCoroutine------" + txId);
+ StartCoroutine(ProcessPayData(txId, callback));
+ }
+
+ private IEnumerator ProcessPayData(string orderId, Action onValidationComplete)
+ {
+ // 发起请求
+ ApplePayRequest(orderId, onValidationComplete);
+
+ yield return null; // 等待本次请求完成
+ }
+
+ private void ApplePayRequest(string transactionID, Action onValidationComplete)
+ {
+ var payDataJson = GetApplePayData();
+ Debug.Log($"ApplePayRequest 1 payDataJson: {JsonConvert.SerializeObject(payDataJson)}");
+ SendDebugToServer($"验单 普通商品: {transactionID}", Environment.StackTrace);
+
+ var statusDictionary = JsonConvert.DeserializeObject>(payDataJson);
+
+ if (statusDictionary.ContainsKey(transactionID))
+ {
+ var data = statusDictionary[transactionID];
+ Debug.Log($"ApplePayRequest 2 transactionID: {transactionID}, innerOrderId:{data.innerOrderId}");
+
+
+ ApplePayNet.ApplePayCheck(transactionID, data.innerOrderId, _packageName, (response) =>
+ {
+ Debug.Log(
+ $"ApplePayRequest 3 response.IsSuccess: {JsonConvert.SerializeObject(response)}");
+ _isProcessing = false;
+ TryProcessNext();
+
+ if (response.IsSuccess || response.Code == 1026 || (response.Code == 1007 && data.sku == PurchasingManager.GetPaySku(PayType.buy_one)))
+ {
+ onValidationComplete?.Invoke(true);
+ _processedOrPendingTx.Remove(transactionID);
+ _successCallback(ApplePayBackType.Check, new AppleResponseData()
+ {
+ sku = data.sku
+ });
+
+ var innerdata = GetInnerIdData();
+ innerdata.Remove(data.innerOrderId);
+ SaveInnerIdData(innerdata);
+
+ statusDictionary.Remove(transactionID);
+ // 保存更新后的数据
+ SaveApplePayData(statusDictionary);
+
+ _innerData = null;
+ _payData = null;
+ }
+ else if (response.Code == 1007)
+ {
+ GameHelper.ShowTips("no_network", true);
+ onValidationComplete?.Invoke(true);
+ }
+ else
+ {
+ onValidationComplete?.Invoke(response.IsSuccess);
+ }
+
+ if (!new List() { 1021, 1027, 1028 }.Contains(response.Code))
+ {
+ }
+ else
+ {
+ statusDictionary.Remove(transactionID);
+ // 保存更新后的数据
+ SaveApplePayData(statusDictionary);
+
+ var innerdata = GetInnerIdData();
+ innerdata.Remove(data.innerOrderId);
+ SaveInnerIdData(innerdata);
+ }
+ });
+ }
+ }
+
+ #endregion
+
+ #region 初始化
+
+ private bool IsInitialized()
+ {
+ Debug.Log("[barry] check IsInitialized======:");
+ return _storeController != null && _extensionProvider != null;
+ }
+
+ public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
+ {
+ _storeController = controller;
+ _extensionProvider = extensions;
+ _appleExtension = extensions.GetExtension();
+ GetVipHistory();
+ }
+
+ public void OnInitializeFailed(InitializationFailureReason error)
+ {
+ Debug.Log("[barry] OnInitializeFailed1 Reason:" + error);
+ // throw new NotImplementedException();
+ }
+
+ public void OnInitializeFailed(InitializationFailureReason error, string message)
+ {
+ Debug.Log("[barry] OnInitializeFailed2 Reason:" + error);
+ Debug.Log("[barry] OnInitializeFailed2 message:" + message);
+ // throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region 购买失败回调
+
+ public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
+ {
+ Debug.Log(" OnPurchaseFailed===1==:");
+ HandleOnPurchaseFail(failureReason);
+ }
+
+
+ public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
+ {
+ Debug.Log("OnPurchaseFailed===2==:");
+ HandleOnPurchaseFail(failureDescription.reason);
+ }
+
+ private void HandleOnPurchaseFail(PurchaseFailureReason failureReason)
+ {
+ Debug.Log($" HandleOnPurchaseFail 1 ");
+
+ if (_payData == null) return;
+
+ GameHelper.ShowTips("purchase_fail", true);
+ Debug.Log($" HandleOnPurchaseFail 2 ");
+
+ ApplePayNet.ApplePayCancel(_payData, (response) =>
+ {
+ string msg = ToFriendlyString(failureReason);
+ Debug.Log("[barry] HandleOnPurchaseFail:" + response.IsSuccess + " reason: " + msg);
+
+ if (!_payData.sku.Contains(".sub"))
+ {
+ var innerdata = GetInnerIdData();
+ Debug.Log(
+ $"[Apple pay] HandleOnPurchaseFail----- _payData.innerOrderId: {_payData.innerOrderId}");
+
+ innerdata.Remove(_payData.innerOrderId);
+ SaveInnerIdData(innerdata);
+ }
+
+ _failedCallback?.Invoke(msg);
+ _payData = null;
+ _innerData = null;
+
+ _successCallback?.Invoke(ApplePayBackType.Cancel, null);
+ });
+ }
+
+ private static string ToFriendlyString(PurchaseFailureReason reason)
+ {
+ Debug.Log($"ToFriendlyString 1 reason==={reason}");
+
+ return reason switch
+ {
+ PurchaseFailureReason.ProductUnavailable => "商品不可用",
+ PurchaseFailureReason.PurchasingUnavailable => "购买功能不可用",
+ PurchaseFailureReason.ExistingPurchasePending => "已有未完成的购买",
+ PurchaseFailureReason.SignatureInvalid => "签名验证失败",
+ PurchaseFailureReason.UserCancelled => "用户取消",
+ PurchaseFailureReason.PaymentDeclined => "支付被拒绝",
+ PurchaseFailureReason.DuplicateTransaction => "重复的交易ID",
+ PurchaseFailureReason.Unknown => "未知错误",
+ _ => $"未识别的错误: {(int)reason}"
+ };
+ }
+
+ #endregion
+ }
+}
+#else
+namespace SGModule.ApplePay {
+ public class ApplePayManager: SingletonMonoBehaviour{
+ public void StartPay() {
+ }
+
+ public string GetApplePayName(string key)
+ {
+ return "";
+ }
+
+ public void Purchase(ApplePayData payData, Action successCallback,
+ Action failedCallback) {
+ var msg = "Apple Pay: Purchase Failed, No plugin is installed.";
+ Log.Info("[Apple IOS]",msg);
+ failedCallback?.Invoke(msg);
+ }
+
+ public void AppleRestore(Action restoreCallback)
+ {
+
+ }
+ public void InitProduct(Listconfigs, string packageName)
+ {
+
+ }
+
+ }
+}
+
+#endif
+public class AppleResponseData
+{
+ [JsonProperty("expires_time")]
+ public long expires_time;
+ [JsonProperty("sku")]
+ public string sku;
+}
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs.meta b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs.meta
new file mode 100644
index 0000000..1d99d97
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8478e5310ad64f23a3805cd8a3fa024f
+timeCreated: 1747907338
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs
new file mode 100644
index 0000000..1550d92
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs
@@ -0,0 +1,95 @@
+using SGModule.Common.Helper;
+using SGModule.Net;
+using UnityEngine.Events;
+
+namespace SGModule.ApplePay
+{
+ public static class ApplePayNet
+ {
+ #region IOSPay
+ ///
+ /// ios支付创建订单
+ ///
+ ///
+ ///
+ public static void ApplePayCreate(ApplePayData data, UnityAction> onCompleted = null)
+ {
+ NetKit.NetKit.Instance.Post("shop/applePayCreate", data,
+ response => { onCompleted?.Invoke(response); });
+ }
+
+ ///
+ /// ios支付取消订单
+ ///
+ ///
+ ///
+ public static void ApplePayCancel(ApplePayData data, UnityAction> onCompleted = null)
+ {
+ NetKit.NetKit.Instance.Post("shop/applePayCancel", data,
+ response => { onCompleted?.Invoke(response); });
+ }
+ public static void ApplePaySubscriptionHistory(UnityAction> onCompleted = null)
+ {
+ NetKit.NetKit.Instance.Post("shop/subscribeHistory", null,
+ response => { onCompleted?.Invoke(response); });
+ }
+ public static void ApplePaySubscriptionCheck(HistoryObject obj,UnityAction> onCompleted = null)
+ {
+ NetKit.NetKit.Instance.Post("shop/subscribeCheck", obj,
+ response => { onCompleted?.Invoke(response); });
+ }
+
+
+ ///
+ /// ios支付验证订单
+ ///
+ /// apple支付返回的订单id
+ /// 内部订单id,创建订单时返回的
+ /// 包名
+ /// 回调
+ public static void ApplePayCheck(string transactionID, string innerOrderId,
+ string key, UnityAction> onCompleted = null)
+ {
+ var test = new AppleCheckData
+ {
+ signedPayload = Common.Helper.Cryptor.Encrypt(transactionID, key),
+ innerOrderId = innerOrderId
+ };
+
+ NetKit.NetKit.Instance.Post("shop/applePayCheck", test,
+ response => { onCompleted?.Invoke(response); });
+ }
+ ///
+ /// ios支付订阅
+ ///
+ /// apple支付返回的订单id
+ /// 商品id
+ /// 价格
+ /// 包名
+ /// 回调
+ public static void AppleSubscribeCheck(string transactionID, string sku, int amount,
+ string key, UnityAction> onCompleted = null)
+ {
+ var test = new AppleSubscribeData
+ {
+ signedPayload = Common.Helper.Cryptor.Encrypt(transactionID, key),
+ sku = sku,
+ amount = amount,
+ currency = "USD"
+ };
+ Log.Info("[Apple pay]", $" AppleSubscribeCheck 开始...{sku}");
+
+ NetKit.NetKit.Instance.Post(
+ "shop/appleSubscribe",
+ test,
+ response =>
+ {
+ Log.Info("[Apple pay]", $"AppleSubscribeCheck 结束...{response.IsSuccess}");
+ onCompleted?.Invoke(response);
+ });
+
+ }
+
+ #endregion
+ }
+}
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs.meta b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs.meta
new file mode 100644
index 0000000..c1467a0
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ApplePayNet.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 760f78942ee949a9af90bc8ac6710be7
+timeCreated: 1747996461
\ No newline at end of file
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs b/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs
new file mode 100644
index 0000000..1e959ec
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs
@@ -0,0 +1,22 @@
+#if UNITY_IOS && UNITY_IAP
+using Newtonsoft.Json;
+using UnityEngine;
+using UnityEngine.Purchasing;
+
+namespace SGModule.ApplePay
+{
+ [System.Serializable]
+ public class ProductConfig
+ {
+ [JsonProperty("name")]
+ public string name;
+ [JsonProperty("sku")]
+ public string sku;
+ [JsonProperty("price")]
+ public float price;
+ [JsonProperty("type")]
+ public string type;
+
+ }
+}
+#endif
diff --git a/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs.meta b/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs.meta
new file mode 100644
index 0000000..2fff9e6
--- /dev/null
+++ b/Assets/SGModule/ApplePay/SGModule/Scripts/ProductConfig.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: bab80a35d16a48e6856d995e175b82d3
+timeCreated: 1747911023
\ No newline at end of file
diff --git a/Assets/SGModule/Common.meta b/Assets/SGModule/Common.meta
new file mode 100644
index 0000000..f8b4c58
--- /dev/null
+++ b/Assets/SGModule/Common.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 091c2904b608b7e43a1b20fc88aaa3c4
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/README.md b/Assets/SGModule/Common/README.md
new file mode 100644
index 0000000..72cdafe
--- /dev/null
+++ b/Assets/SGModule/Common/README.md
@@ -0,0 +1,138 @@
+# 🧱 Common 公共模块
+
+------
+
+## 📖 概述
+
+Common 模块是项目中最基础、最核心的模块,包含通用工具类、配置文件、扩展方法及基础系统组件。**所有其他模块都应依赖此模块**,务必在拉取其他模块前先行安装。
+
+------
+
+## 📁 功能总览
+
+- ✅ 项目配置管理
+- ✅ 单例模式基类(支持非Mono与Mono行为)
+- ✅ 常用工具类(加解密、日志、时间、设备信息)
+- ✅ 扩展方法(数组、字符串、枚举等)
+- ✅ 编辑器工具(自动生成配置文件)
+- ✅ GM工具相关支持
+
+------
+
+## ⚙️ 核心系统详解
+
+### 🧩 配置文件系统(GameConfig, NetworkConfig)
+
+📌 通过菜单栏 `SwhiteGames > Create GameConfig` 可在 `Resources/` 目录下自动创建 `GameConfig` 文件,包含以下配置字段:
+
+| 字段名 | 含义说明 |
+| ------------- | ----------------------------------------- |
+| `PackageName` | 游戏包名 |
+| `IsRelease` | 是否为正式发布包(关联宏 `GAME_RELEASE`) |
+| `EnabledLog` | 是否启用日志打印 |
+
+📦 获取配置示例:
+
+```csharp
+var enabledLog = ConfigManager.GameConfig?.enabledLog;
+var packageName = ConfigManager.GameConfig?.packageName;
+```
+
+------
+
+
+📌 通过菜单栏 `SwhiteGames > Create NetworkConfig` 可在 `Resources/` 目录下自动创建 `NetworkConfig` 文件,包含以下配置字段:
+
+| 字段名 | 含义说明 |
+| ------------- |----------|
+| `showNetworkLog` | 是否启用日志打印 |
+| `debugHost` | 测试环境Host |
+| `releaseHost` | 正式环境Host |
+| `connectionMode` | 连接模式 |
+
+📦 获取配置示例:
+
+```csharp
+var connectionMode = ConfigManager.NetworkConfig?.connectionMode;
+var showNetworkLog = ConfigManager.NetworkConfig?.showNetworkLog;
+```
+
+------
+### 🔁 单例系统
+
+- **SingletonMonoBehaviour**:MonoBehaviour 单例,自动创建 GameObject,跨场景不销毁
+
+```csharp
+// MonoBehaviour
+public class AudioManager : SingletonMonoBehaviour { ... }
+```
+
+------
+
+### 🛠️ 工具类一览(Helper)
+
+| 类名 | 功能说明 |
+| ----------------- | ------------------------------------------- |
+| `Log` | ✅日志打印(开发调试利器) |
+| `Cryptor` | 🔐 加密解密支持(对称加密) |
+| `TimeHelper` | 🕒 时间戳转换与格式化处理 |
+| `DeviceHelper` | 📱 获取设备唯一标识 |
+| `RandomHelper` | 🎲 权重随机、随机打乱等 |
+| `SerializeHelper` | 🔄 JSON 序列化 / 反序列化(可使用As()替换) |
+| `MD5Helper` | 🔑 快速生成MD5签名 |
+| `Base64Helper` | 🧬 Base64编解码 |
+
+------
+
+### 📌 日志打印统一用法
+
+统一使用 `Log` 工具类进行日志输出,支持彩色分级,正式环境中可自动关闭日志输出。
+
+```csharp
+using SGModule.Common.Helper;
+
+Log.Info("标签", "信息内容"); // ✅绿色输出
+Log.Warning("标签", "警告内容"); // ⚠️橙色输出
+Log.Error("标签", "错误内容"); // ❌红色输出
+```
+
+------
+
+### ✨ 扩展方法一览
+
+- **EnumExtensions**:获取枚举描述 `GameState.Ready.GetDescription()`
+- **StringExtensions**:空值检查 `str.IsNullOrWhiteSpace()`
+- **ObjectExtensions**:类型安全转换 `"123".As()`
+- **ListExtensions**:列表随机元素 `items.Random()`
+- **ArrayExtensions**:数组相关操作
+
+------
+
+## 🧠 最佳实践
+
+| 模块 | 建议做法 |
+| ---------- | ------------------------------------------------------------ |
+| 管理器类 | Mono 类继承 `SingletonMonoBehaviour` |
+| 日志打印 | 全局使用 `Log` 统一管理,按模块分类 |
+| 类型转换 | 使用 `.As()` 替代传统强转,异常更少 |
+| 加密数据 | 所有敏感数据使用 `Cryptor` 加密后存储 |
+| 时间处理 | 使用 `TimeHelper` 保证时区一致性 |
+| 随机操作 | 使用 `RandomHelper` 替代 `UnityEngine.Random` |
+| 数据键管理 | 通过 `KeyRegistry` 注册和使用,避免硬编码 |
+
+------
+
+## ⚠️ 注意事项
+
+- ❗ `SingletonMonoBehaviour` 不要手动放入场景,会自动创建
+- 🔐 加密密钥需妥善保管,避免泄露
+- 🌏 时间处理请注意本地时区与 UTC 的转换
+- 🎲 请勿使用 `UnityEngine.Random`,统一使用 `RandomHelper`
+
+------
+
+## 💡 扩展建议
+
+- 🧩 新增扩展方法时,请分类放入 `Extensions/` 并补充完整 XML 注释
+- 🧰 新增工具类保持静态类设计,考虑线程安全
+- 📖 键系统支持从配置文件中加载,并支持按模块分组管理
\ No newline at end of file
diff --git a/Assets/SGModule/Common/README.md.meta b/Assets/SGModule/Common/README.md.meta
new file mode 100644
index 0000000..206e491
--- /dev/null
+++ b/Assets/SGModule/Common/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 0a5954894fd434e4f8726239c65e8497
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule.meta b/Assets/SGModule/Common/SGModule.meta
new file mode 100644
index 0000000..42c1d25
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1255dc405c83ca54ba0fe153fde0fd3c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Editor.meta b/Assets/SGModule/Common/SGModule/Editor.meta
new file mode 100644
index 0000000..6ae76ca
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c7910bd51ff93d347891de376c8c6d3c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs b/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs
new file mode 100644
index 0000000..93f017e
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs
@@ -0,0 +1,75 @@
+using System.IO;
+using SGModule.Common.Helper;
+using UnityEditor;
+using UnityEngine;
+
+namespace SwhiteGames.Editor {
+ public class GameConfigCreator : EditorWindow {
+ public string packName = "";
+ public bool enabledLog = true;
+ public bool hardwareAcceleration = true;
+
+ private string _configFileName = "GameConfig";
+
+ private void OnGUI() {
+ GUILayout.Label("GameConfig Settings", EditorStyles.boldLabel);
+ _configFileName = EditorGUILayout.TextField("Character Name", _configFileName);
+
+ packName = EditorGUILayout.TextField(string.IsNullOrEmpty(packName) ? "请输入包名..." : "包名",
+ packName);
+
+ enabledLog = EditorGUILayout.Toggle("开启日志", enabledLog);
+
+#if UNITY_ANDROID
+ hardwareAcceleration = EditorGUILayout.Toggle("硬件加速", hardwareAcceleration);
+#endif
+ if (GUILayout.Button("Create")) {
+ if (string.IsNullOrEmpty(packName)) {
+ EditorUtility.DisplayDialog("请填写正确配置",
+ $"packName {!string.IsNullOrEmpty(packName)}",
+ "确定");
+ return;
+ }
+
+ CreateGameConfig();
+ Close();
+ }
+ }
+
+ [MenuItem("SwhiteGames/Create GameConfig")]
+ public static void ShowWindow() {
+ GetWindow("Create GameConfig");
+ }
+
+ private void CreateGameConfig() {
+ // 确保 Resources 文件夹存在
+ var resourcesPath = Path.Combine("Assets", "Resources");
+ if (!Directory.Exists(resourcesPath)) {
+ Directory.CreateDirectory(resourcesPath);
+ AssetDatabase.Refresh(); // 刷新资源数据库
+
+ Log.Common.Info("Resources 文件夹已创建。");
+ }
+
+ // 检查同名文件
+ var assetPath = Path.Combine(resourcesPath, _configFileName + ".asset");
+ if (File.Exists(assetPath)) {
+ // 如果同名文件已存在,弹出提示并结束逻辑
+ EditorUtility.DisplayDialog("文件已存在", $"配置文件 '{_configFileName}' 已存在于 Resources 文件夹中。", "确定");
+ return;
+ }
+
+ // 创建并设置 config 实例
+ var gameConfig = CreateInstance();
+ gameConfig.packageName = packName;
+ gameConfig.enabledLog = enabledLog;
+ gameConfig.hardwareAcceleration = hardwareAcceleration;
+
+ // 将 ScriptableObject 实例保存到 Resources 文件夹中
+ AssetDatabase.CreateAsset(gameConfig, assetPath);
+ AssetDatabase.SaveAssets();
+
+ Log.Common.Info("GameConfig 配置文件已成功创建在 " + assetPath);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs.meta b/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs.meta
new file mode 100644
index 0000000..a40a096
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/GameConfigCreator.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 88d46a9d0224446fb77e9864ebe4d4f5
+timeCreated: 1731660781
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs b/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs
new file mode 100644
index 0000000..f792819
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs
@@ -0,0 +1,39 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace SwhiteGames.Editor {
+ [CustomEditor(typeof(GameConfig))]
+ public class GameConfigEditor : UnityEditor.Editor {
+ public override void OnInspectorGUI() {
+ DrawDefaultInspector(); // 可选:绘制默认 Inspector
+
+ var gameConfig = (GameConfig) target;
+
+ // 包名
+ gameConfig.packageName = EditorGUILayout.TextField("包名", gameConfig.packageName);
+
+ // isRelease 选项
+ EditorGUI.BeginDisabledGroup(true);
+
+ EditorGUILayout.Toggle(new GUIContent("isRelease", "是否为发布版本, 由玩家设置中脚本定义符 GAME_RELEASE 决定"),
+ gameConfig.isRelease);
+ EditorGUI.EndDisabledGroup();
+
+ // 启用日志(随 isRelease 联动)
+ EditorGUI.BeginDisabledGroup(gameConfig.isRelease);
+ gameConfig.enabledLog =
+ EditorGUILayout.Toggle(new GUIContent("启用日志", "发布版本默认不可启动日志"), gameConfig.enabledLog);
+ EditorGUI.EndDisabledGroup();
+
+#if UNITY_ANDROID
+ // 硬件加速
+ gameConfig.hardwareAcceleration = EditorGUILayout.Toggle("硬件加速", gameConfig.hardwareAcceleration);
+#endif
+
+ // 标记对象已修改,确保更改能保存
+ if (GUI.changed) {
+ EditorUtility.SetDirty(gameConfig);
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs.meta b/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs.meta
new file mode 100644
index 0000000..055e4ab
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/GameConfigEditor.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 3d35d44cfe6b42dd8abc4fcee72c69c8
+timeCreated: 1743589873
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs b/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs
new file mode 100644
index 0000000..1dc2007
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs
@@ -0,0 +1,94 @@
+#if UNITY_ANDROID && UNITY_EDITOR
+using System.IO;
+using System.Xml;
+using SGModule.Common;
+using SGModule.Common.Helper;
+using UnityEditor.Android;
+using UnityEngine;
+
+namespace SwhiteGames.Editor {
+ public class HardwareAccelerationManager : IPostGenerateGradleAndroidProject {
+ public int callbackOrder => 99;
+
+ private static bool EnableHardwareAcceleration => ConfigManager.GameConfig.hardwareAcceleration;
+
+ public void OnPostGenerateGradleAndroidProject(string basePath) {
+ var manifestPath = GetManifestPath(basePath);
+ if (!File.Exists(manifestPath)) {
+ Log.Warning("HardwareAcceleration", $"Manifest not found at {manifestPath}");
+ return;
+ }
+
+ var manifest = new AndroidManifestHelper(manifestPath);
+
+ var changed = manifest.SetHardwareAccelerated(EnableHardwareAcceleration);
+
+ if (changed) {
+ manifest.Save();
+ Log.Info("HardwareAcceleration", $"Updated manifest with hardwareAccelerated={EnableHardwareAcceleration}");
+ }
+ }
+
+ private string GetManifestPath(string basePath) {
+ return Path.Combine(basePath, "src/main/AndroidManifest.xml");
+ }
+ }
+
+ internal class AndroidManifestHelper {
+ private readonly XmlDocument _doc;
+ private readonly XmlNamespaceManager _nsMgr;
+ private const string AndroidNs = "http://schemas.android.com/apk/res/android";
+ private readonly string _manifestPath;
+
+ public AndroidManifestHelper(string path) {
+ _manifestPath = path;
+ _doc = new XmlDocument();
+ _doc.Load(path);
+
+ _nsMgr = new XmlNamespaceManager(_doc.NameTable);
+ _nsMgr.AddNamespace("android", AndroidNs);
+ }
+
+ public bool SetHardwareAccelerated(bool enabled) {
+ var activity = GetMainActivity();
+ if (activity == null) {
+ Debug.LogWarning("[HardwareAcceleration] Could not find main activity");
+ return false;
+ }
+
+ return SetHardwareAccelerated(activity, enabled);
+ }
+
+ private bool SetHardwareAccelerated(XmlNode activity, bool enabled) {
+ var value = enabled ? "true" : "false";
+ var attr = (activity as XmlElement)?.GetAttributeNode("hardwareAccelerated", AndroidNs);
+
+ if (attr == null) {
+ attr = _doc.CreateAttribute("android", "hardwareAccelerated", AndroidNs);
+ activity.Attributes?.Append(attr);
+ attr.Value = value;
+ return true;
+ }
+
+ if (attr.Value != value) {
+ attr.Value = value;
+ return true;
+ }
+
+ return false;
+ }
+
+ private XmlNode GetMainActivity() {
+ return _doc.SelectSingleNode(
+ "/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " +
+ "intent-filter/category/@android:name='android.intent.category.LAUNCHER']",
+ _nsMgr);
+ }
+
+ public void Save() {
+ _doc.Save(_manifestPath);
+ }
+ }
+}
+
+#endif
diff --git a/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs.meta b/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs.meta
new file mode 100644
index 0000000..9dfa214
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/HardwareAccelerationSetter.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: dffc1d0f59e04033a4372c6e86992176
+timeCreated: 1753164058
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs b/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs
new file mode 100644
index 0000000..6ba60bc
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs
@@ -0,0 +1,78 @@
+using System.IO;
+using SGModule.Common.Helper;
+using UnityEditor;
+using UnityEngine;
+
+namespace SGModule.Editor {
+ public class NetworkConfigCreator : EditorWindow {
+ private const string DefaultHost = "sandbox-api.swhitegames.tech";
+ private const string ConfigFileName = "NetworkConfig";
+
+ public bool showNetworkLog = true;
+ public string debugHost = DefaultHost;
+ public string releaseHost = "";
+
+ public ConnectionMode model = ConnectionMode.Http;
+
+ private void OnGUI() {
+ showNetworkLog = EditorGUILayout.Toggle("显示日志", showNetworkLog);
+
+ debugHost = EditorGUILayout.TextField("Debug Host:", debugHost);
+ releaseHost = EditorGUILayout.TextField("Release Host:", releaseHost);
+
+ model = (ConnectionMode) EditorGUILayout.EnumPopup("连接模式:", model);
+
+
+ if (GUILayout.Button("Create NetworkConfig")) {
+ if (string.IsNullOrEmpty(debugHost) || string.IsNullOrEmpty(releaseHost)) {
+ EditorUtility.DisplayDialog("请填写正确配置",
+ $"Debug Host {(string.IsNullOrEmpty(debugHost) ? "不存在" : "存在")}, Release Host {(string.IsNullOrEmpty(releaseHost) ? "不存在" : "存在")}",
+ "确定");
+ return;
+ }
+
+ CreateNetworkConfig();
+ Close();
+ }
+ }
+
+ [MenuItem("SwhiteGames/Create NetworkConfig")]
+ public static void ShowWindow() {
+ GetWindow("Create NetworkConfig");
+ }
+
+ private void CreateNetworkConfig() {
+ // 确保 Resources 文件夹存在
+ var resourcesPath = Path.Combine("Assets", "Resources");
+ if (!Directory.Exists(resourcesPath)) {
+ Directory.CreateDirectory(resourcesPath);
+ AssetDatabase.Refresh(); // 刷新资源数据库
+ Log.Common.Info("Resources 文件夹已创建。");
+ }
+
+ // 检查同名文件
+ var assetPath = Path.Combine(resourcesPath, ConfigFileName + ".asset");
+ if (File.Exists(assetPath)) {
+ // 如果同名文件已存在,弹出提示并结束逻辑
+ EditorUtility.DisplayDialog("文件已存在", $"配置文件 '{ConfigFileName}' 已存在于 Resources 文件夹中。", "确定");
+ return;
+ }
+ // 检查同名文件
+ // string assetPath = Path.Combine(resourcesPath, _configFileName + ".asset");
+ // string uniqueAssetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); // 生成唯一路径
+
+ // 创建并设置 config 实例
+ var networkConfig = CreateInstance();
+ networkConfig.showNetworkLog = showNetworkLog;
+ networkConfig.debugHost = debugHost;
+ networkConfig.releaseHost = releaseHost;
+ networkConfig.connectionMode = model;
+
+ // 将 ScriptableObject 实例保存到 Resources 文件夹中
+ AssetDatabase.CreateAsset(networkConfig, assetPath);
+ AssetDatabase.SaveAssets();
+
+ Log.Common.Info("NetworkConfig 配置文件已成功创建在 " + assetPath);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs.meta b/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs.meta
new file mode 100644
index 0000000..efbfb50
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Editor/NetworkConfigCreator.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 534fe38ef6ad460493d6cb0a852a7fb5
+timeCreated: 1731480153
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Plugins.meta b/Assets/SGModule/Common/SGModule/Plugins.meta
new file mode 100644
index 0000000..b20cda3
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Plugins.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 306dc076af5dda247803b0ad907f4968
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Plugins/iOS.meta b/Assets/SGModule/Common/SGModule/Plugins/iOS.meta
new file mode 100644
index 0000000..1377e4a
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Plugins/iOS.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3c18f1f3b9ea744f5b3d4a66286b726c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm b/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm
new file mode 100644
index 0000000..bcb7040
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm
@@ -0,0 +1,66 @@
+#import
+#import
+#import
+
+extern "C" {
+
+// 保存数据到 Keychain
+bool SaveToKeychain(const char* key, const char* value) {
+ NSString* keyString = [NSString stringWithUTF8String:key];
+ NSString* valueString = [NSString stringWithUTF8String:value];
+
+ NSData* valueData = [valueString dataUsingEncoding:NSUTF8StringEncoding];
+
+ NSDictionary* query = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : keyString,
+ };
+
+ SecItemDelete((__bridge CFDictionaryRef)query);
+
+ NSDictionary* attributes = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : keyString,
+ (__bridge id)kSecValueData : valueData,
+ };
+
+ OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
+ return status == errSecSuccess;
+}
+
+// 从 Keychain 中获取数据
+const char* GetFromKeychain(const char* key) {
+ NSString* keyString = [NSString stringWithUTF8String:key];
+
+ NSDictionary* query = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : keyString,
+ (__bridge id)kSecReturnData : @YES,
+ (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne,
+ };
+
+ CFTypeRef result = NULL;
+ OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
+
+ if (status == errSecSuccess) {
+ NSData* valueData = (__bridge_transfer NSData*)result;
+ NSString* valueString = [[NSString alloc] initWithData:valueData encoding:NSUTF8StringEncoding];
+ return strdup([valueString UTF8String]);
+ }
+
+ return NULL;
+}
+
+// 删除 Keychain 中的数据
+bool DeleteFromKeychain(const char* key) {
+ NSString* keyString = [NSString stringWithUTF8String:key];
+
+ NSDictionary* query = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : keyString,
+ };
+
+ OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
+ return status == errSecSuccess;
+}
+}
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm.meta b/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm.meta
new file mode 100644
index 0000000..17a8d58
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Plugins/iOS/KeychainPlugin.mm.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9bc4268c12974c68bd77c36016e019ed
+timeCreated: 1736750208
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts.meta b/Assets/SGModule/Common/SGModule/Scripts.meta
new file mode 100644
index 0000000..3533620
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 53a17396f989d874b9b047cca52f77f8
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Base.meta b/Assets/SGModule/Common/SGModule/Scripts/Base.meta
new file mode 100644
index 0000000..f3c4187
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Base.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f92c00a864347c945bec347302a061e0
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs b/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs
new file mode 100644
index 0000000..a9fde5f
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs
@@ -0,0 +1,57 @@
+using SGModule.Common.Helper;
+using UnityEngine;
+
+namespace SGModule.Common.Base {
+ public class SingletonMonoBehaviour : MonoBehaviour where T : MonoBehaviour {
+ private static T _instance;
+
+ ///
+ /// 初始化完成标记,有需要的地方可以使用
+ ///
+ protected static bool IsInitComplete;
+
+ // 存储所有单例的父对象
+ private static GameObject _singletonParent;
+
+ public static T Instance {
+ get {
+ if (_instance == null) {
+ // 尝试找到已存在的实例
+ _instance = FindObjectOfType();
+
+ // 如果没有找到,则创建一个新的实例
+ if (_instance == null) {
+ // 确保所有单例对象放到同一个父对象下
+ if (_singletonParent == null) {
+ _singletonParent = GameObject.Find("Singletons") ?? new GameObject("Singletons");
+ DontDestroyOnLoad(_singletonParent); // 不在场景切换时销毁
+ }
+
+ var singletonObject = new GameObject(typeof(T).Name);
+ singletonObject.transform.SetParent(_singletonParent.transform); // 设置父对象
+ _instance = singletonObject.AddComponent();
+ }
+ }
+
+ return _instance;
+ }
+ }
+
+ // 确保在场景中只存在一个实例
+ protected virtual void Awake() {
+ if (_instance == null) {
+ _instance = this as T;
+ }
+ else if (_instance != this) {
+ Log.Common.Warning($"An instance of {typeof(T)} already exists! Destroying this instance.");
+ Destroy(gameObject); // 如果有其他实例,销毁当前对象
+ }
+ }
+
+ protected virtual void OnDestroy() {
+ if (_instance == this) {
+ _instance = null; // 清除引用
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs.meta
new file mode 100644
index 0000000..23e33b2
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Base/SingletonMonoBehaviour.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 1a32d260789150d449d0313a73dcc5b1
+timeCreated: 1728986962
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs b/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs
new file mode 100644
index 0000000..65c27d3
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs
@@ -0,0 +1,30 @@
+using SGModule.Common.Helper;
+using UnityEngine;
+
+namespace SGModule.Common {
+ public static class ConfigManager {
+ private const string GameConfigFilePath = "GameConfig";
+ private const string NetworkConfigFilePath = "NetworkConfig";
+
+ static ConfigManager() {
+ GameConfig = Resources.Load(GameConfigFilePath);
+ if (GameConfig == null) {
+ Log.Common.Error($"加载失败:未找到配置文件 {GameConfigFilePath},请确保它放在 Resources 文件夹下并命名正确");
+ }
+
+ NetworkConfig = Resources.Load(NetworkConfigFilePath);
+ if (NetworkConfig == null) {
+ Log.Common.Error($"加载失败:未找到配置文件 {NetworkConfigFilePath},请确保它放在 Resources 文件夹下并命名正确");
+ }
+ }
+
+
+ public static GameConfig GameConfig {
+ get;
+ }
+
+ public static NetworkConfig NetworkConfig {
+ get;
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs.meta
new file mode 100644
index 0000000..a1e0945
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ConfigManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8639bb4e64f34c3db2c6537cfdac4974
+timeCreated: 1731316175
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions.meta
new file mode 100644
index 0000000..b30c881
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f468ddf1f1fc08446865eb4fb41b74aa
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs
new file mode 100644
index 0000000..5889f72
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs
@@ -0,0 +1,14 @@
+using SGModule.Common.Helper;
+using SGModule.Common.Interface;
+
+namespace SGModule.Common.Extensions {
+ public static class ArrayExtensions {
+ public static T Random(this T[] items, T fallback = default) where T : class, IWeighted {
+ if (items == null || items.Length == 0) {
+ return fallback;
+ }
+
+ return RandomHelper.RandomByWeight(items, fallback);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs.meta
new file mode 100644
index 0000000..254cb88
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ArrayExtensions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ea3b1bd83aa74285b19f87301391b906
+timeCreated: 1749197978
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs b/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs
new file mode 100644
index 0000000..b1945f5
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs
@@ -0,0 +1,12 @@
+using System;
+using System.ComponentModel;
+
+namespace SGModule.Common.Extensions {
+ public static class EnumExtensions {
+ public static string GetDescription(this Enum value) {
+ var field = value.GetType().GetField(value.ToString());
+ var attribute = (DescriptionAttribute) Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
+ return attribute?.Description ?? value.ToString(); // 如果没有描述,就使用枚举名称
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs.meta
new file mode 100644
index 0000000..7e13fef
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/EnumExtensions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 4fb5c1462c4f411bb8c08fec74c0bb60
+timeCreated: 1731403821
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs
new file mode 100644
index 0000000..caa7810
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Linq;
+using SGModule.Common.Helper;
+using SGModule.Common.Interface;
+
+namespace SGModule.Common.Extensions {
+ public static class ListExtensions {
+ public static T Random(this IEnumerable items, T fallback = default) where T : class, IWeighted {
+ if (items == null) {
+ return fallback;
+ }
+
+ var list = items as IList ?? items.ToList();
+
+ if (list.Count == 0) {
+ return fallback;
+ }
+
+ return RandomHelper.RandomByWeight(list, fallback);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs.meta
new file mode 100644
index 0000000..c455b8e
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ListExtensions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f42389145cf940a0b4202dbd516228c4
+timeCreated: 1749198436
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs
new file mode 100644
index 0000000..c45d46b
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs
@@ -0,0 +1,302 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Text;
+using Newtonsoft.Json;
+using SGModule.Common.Helper;
+
+namespace SGModule.Common.Extensions {
+ ///
+ /// 提供通用对象类型转换的扩展方法,支持数值类型、字符串、枚举、集合、时间等多种类型间的智能转换。
+ ///
+ public static class ObjectExtensions {
+ ///
+ /// 将对象强制转换为目标类型 ,转换失败时返回默认值。
+ ///
+ /// 目标类型
+ /// 待转换的对象
+ /// 转换失败时返回的默认值
+ /// 可选格式字符串(如用于时间或数值格式化)
+ /// 格式化提供者,默认为当前区域设置
+ /// 转换后的目标类型值,或 。
+ ///
+ /// 字符串到基本类型
+ ///
+ /// "123".As<int>(); // 输出 123
+ /// "45.67".As<float>(); // 输出 45.67f
+ /// "true".As<bool>(); // 输出 true
+ /// "2023-01-01".As<DateTime>(); // 输出 2023-01-01
+ /// "".As<int>(); // 输出 0
+ /// ((string)null).As<int>(); // 输出 0
+ /// "abc".As<int>(); // 输出 0(无法转换)
+ /// "1.23E+5".As<float>(); // 输出 123000f
+ /// .....
+ ///
+ ///
+ public static T As(this object value, T defaultValue = default, string format = null, IFormatProvider formatProvider = null) {
+ return (T) As(value, typeof(T), defaultValue, format, formatProvider);
+ }
+
+ ///
+ /// 将对象转换为指定的目标类型。
+ /// 支持基础类型转换、字符串与 JSON 互转、枚举解析、集合映射、Base64 处理等。
+ ///
+ /// 要转换的对象
+ /// 目标类型
+ /// 转换失败时的返回值
+ /// 可选的格式字符串(用于时间、数字格式化)
+ /// 格式提供者(区域信息),默认为当前区域
+ /// 转换结果或默认值
+ public static object As(this object value, Type targetType, object defaultValue = null, string format = null, IFormatProvider formatProvider = null) {
+ if (value == null || value == DBNull.Value) {
+ return defaultValue;
+ }
+
+ formatProvider ??= CultureInfo.CurrentCulture;
+
+ try {
+ // 1. 类型兼容直接返回
+ if (targetType.IsInstanceOfType(value)) {
+ return value;
+ }
+
+ // 2. 数值类型之间转换(int, float, decimal 等)
+ if (value.IsNumericType() && targetType.IsNumericType()) {
+ return Convert.ChangeType(value, targetType, formatProvider);
+ }
+
+ // 3. 字符串 ⇄ 字节数组
+ if (targetType == typeof(byte[]) && value is string str) {
+ return Encoding.UTF8.GetBytes(str);
+ }
+
+ if (targetType == typeof(string) && value is byte[] bytes) {
+ return Encoding.UTF8.GetString(bytes);
+ }
+
+ // 4. 转为字符串
+ if (targetType == typeof(string)) {
+ if (value is string s) {
+ return s;
+ }
+
+ if (value.IsNumericType()) {
+ return string.Format(formatProvider, format ?? "{0}", value);
+ }
+
+ if (value is DateTime dt) {
+ return string.IsNullOrEmpty(format) ? dt.ToString(formatProvider) : dt.ToString(format, formatProvider);
+ }
+
+ try {
+ return JsonConvert.SerializeObject(value);
+ }
+ catch {
+ return defaultValue;
+ }
+ }
+
+ // 5. 从字符串解析为目标类型
+ if (value is string strValue) {
+ if (string.IsNullOrWhiteSpace(strValue)) {
+ return defaultValue;
+ }
+
+ // 字符串 → 枚举
+ if (targetType.IsEnum) {
+ try {
+ return Enum.Parse(targetType, strValue, true);
+ }
+ catch {
+ return defaultValue;
+ }
+ }
+
+ // 字符串 → 数值
+ if (targetType.IsNumericType()) {
+ return Convert.ChangeType(strValue, targetType, formatProvider);
+ }
+
+ // 字符串 → 时间
+ if (targetType == typeof(DateTime)) {
+ return string.IsNullOrEmpty(format)
+ ? DateTime.Parse(strValue, formatProvider)
+ : DateTime.ParseExact(strValue, format, formatProvider);
+ }
+
+ // 字符串 → 自定义类(JSON)
+ if (targetType.IsClass && targetType != typeof(string)) {
+ try {
+ return JsonConvert.DeserializeObject(strValue, targetType);
+ }
+ catch {
+ return defaultValue;
+ }
+ }
+ }
+
+ // 6. 集合类型转换(如 List -> List)
+ if (targetType.IsGenericListOrArray() && value is IEnumerable enumerable) {
+ var elementType = targetType.GetElementType() ?? targetType.GetGenericArguments()[0];
+ var list = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType));
+
+ foreach (var item in enumerable) {
+ var converted = typeof(ObjectExtensions)
+ .GetMethod("As", new[] { typeof(object), typeof(Type), typeof(object), typeof(string), typeof(IFormatProvider) })
+ ?.Invoke(null, new[] { item, elementType, null, format, formatProvider });
+
+ list.Add(converted);
+ }
+
+ return targetType.IsArray ? list.ToArray(elementType) : list;
+ }
+
+ // 7. 尝试通过 TypeConverter 转换(主要处理结构体、基础类型)
+ if (targetType.IsValueType || targetType == typeof(string)) {
+ var strVal = value.ToString();
+ if (!string.IsNullOrWhiteSpace(strVal)) {
+ var converter = TypeDescriptor.GetConverter(targetType);
+ if (converter.CanConvertFrom(typeof(string))) {
+ return converter.ConvertFrom(null, formatProvider as CultureInfo, strVal);
+ }
+ }
+ }
+
+ // 8. Fallback:通过 JSON 转换
+ return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), targetType);
+ }
+ catch {
+ return defaultValue;
+ }
+ }
+
+ #region 🔧 辅助方法
+
+ private static bool IsNumericType(this Type type) {
+ return Type.GetTypeCode(type) switch {
+ TypeCode.Byte or TypeCode.SByte or TypeCode.UInt16 or TypeCode.UInt32 or
+ TypeCode.UInt64 or TypeCode.Int16 or TypeCode.Int32 or TypeCode.Int64 or
+ TypeCode.Decimal or TypeCode.Double or TypeCode.Single => true,
+ _ => false
+ };
+ }
+
+ private static bool IsNumericType(this object value) {
+ return value?.GetType().IsNumericType() ?? false;
+ }
+
+ private static bool IsGenericListOrArray(this Type type) {
+ return type != null && (type.IsArray ||
+ (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(List<>)
+ || type.GetGenericTypeDefinition() == typeof(IList<>))));
+ }
+
+ private static Array ToArray(this IList list, Type elementType) {
+ var array = Array.CreateInstance(elementType, list.Count);
+ list.CopyTo(array, 0);
+ return array;
+ }
+
+ #endregion
+ }
+
+ public static class ObjectExtensionsTest {
+ public static void AsTestRun() {
+ TestCase("int 到 int", 123.As(), 123);
+ TestCase("float 到 int", 123.1f.As(), 123);
+ TestCase("double 到 decimal", 99.99.As(), 99.99m);
+ TestCase("int 到 long", 100.As(), 100L);
+
+ TestCase("字符串 到 int", "123".As(), 123);
+ TestCase("字符串 到 float", "45.67".As(), 45.67f);
+ TestCase("字符串 到 bool", "true".As(), true);
+ TestCase("字符串 到 DateTime", "2023-01-01".As(), new DateTime(2023, 1, 1));
+ TestCase("空字符串 到 int", "".As(), 0);
+ TestCase("null字符串 到 int", ((string) null).As(), 0);
+ TestCase("非法字符串 到 int", "abc".As(), 0);
+ TestCase("科学计数法字符串 到 float", "1.23E+5".As(), 123000f);
+
+ TestCase("int 到 字符串", 42.As(), "42");
+ TestCase("float 到 字符串(en-US)", 3.14159f.As(formatProvider: new CultureInfo("en-US")), "3.14159");
+ TestCase("float 到 字符串(de-DE)", 3.14159f.As(formatProvider: new CultureInfo("de-DE")), "3,14159");
+ TestCase("DateTime 到 字符串(格式化)", new DateTime(2024, 5, 1).As(format: "yyyy-MM-dd"), "2024-05-01");
+
+ TestCase("null 到 int", ((object) null).As(), 0);
+ TestCase("null 到 string", ((object) null).As(), null);
+ TestCase("DBNull 到 int", DBNull.Value.As(), 0);
+
+ TestCase("枚举 到 string", Color.Red.As(), "Red");
+ TestCase("字符串 到 枚举", "Green".As(), Color.Green);
+
+ var json = "{\"Name\":\"Alice\",\"Age\":30}";
+ TestCase("JSON 字符串 到 Person", json.As().Name, "Alice");
+ TestCase("对象 到 JSON 字符串", new Person { Name = "Alice", Age = 30 }.As(), JsonConvert.SerializeObject(new Person { Name = "Alice", Age = 30 }));
+
+ TestCase("字符串数组 到 List", new[] { "1", "2", "3" }.As>(), new List { 1, 2, 3 });
+ TestCase("List 到 float[]", new List { 1.1f, 2.2f }.As(), new[] { 1.1f, 2.2f });
+ TestCase("空集合 到 int[]", new string[] { }.As(), new int[] { });
+
+ var str = "hello";
+ var bytes = Encoding.UTF8.GetBytes(str);
+ TestCase("byte[] 到 base64 string", bytes.As(), str);
+ TestCase("base64 string 到 byte[]", BitConverter.ToString(str.As()), BitConverter.ToString(bytes));
+
+ TestCase("字符串小数(德语) 到 float", "1,23".As(formatProvider: new CultureInfo("de-DE")), 1.23f);
+ TestCase("字符串小数(英语) 到 float", "1.23".As(formatProvider: new CultureInfo("en-US")), 1.23f);
+
+ TestCase("非法 JSON 到 Person(失败返回 null)", "{invalid}".As(), null);
+ TestCase("不能转的对象 到 int", new Person { Name = "A" }.As(), 0);
+ TestCase("不能转的对象 到 string(fallback 到 JsonConvert)", new Person { Name = "A", Age = 20 }.As(), JsonConvert.SerializeObject(new Person { Name = "A", Age = 20 }));
+ }
+
+ private static void TestCase(string description, T actual, T expected) {
+ var isSuccess = CommonUtils.DeepEquals(actual, expected);
+
+ var actualStr = FormatValue(actual);
+ var expectedStr = FormatValue(expected);
+ var msg = $"{description} => 结果: {actualStr}, 期望: {expectedStr}";
+ if (isSuccess) {
+ Log.Info("As()", msg);
+ }
+ else {
+ Log.Warning("As()", msg);
+ }
+ }
+
+ private static string FormatValue(T value) {
+ if (value == null) {
+ return "null";
+ }
+
+ if (value is byte[] byteArray) {
+ return $"[{string.Join(", ", byteArray)}]";
+ }
+
+ if (value is int[] intArray) {
+ return $"[{string.Join(", ", intArray)}]";
+ }
+
+ return value.ToString();
+ }
+
+ private enum Color {
+ Red,
+ Green,
+ Blue
+ }
+
+ private class Person {
+ public string Name {
+ get;
+ set;
+ }
+
+ public int Age {
+ get;
+ set;
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs.meta
new file mode 100644
index 0000000..e79aad7
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/ObjectExtensions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e6571543817d44e79cbd4f48a4d3616a
+timeCreated: 1749716272
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs b/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs
new file mode 100644
index 0000000..51547c5
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs
@@ -0,0 +1,7 @@
+namespace SGModule.Common.Extensions {
+ public static class StringExtensions {
+ public static bool IsNullOrWhiteSpace(this string str) {
+ return string.IsNullOrWhiteSpace(str);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs.meta
new file mode 100644
index 0000000..14eaada
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Extensions/StringExtensions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 562d871c5a8d49db9d78fb2921475549
+timeCreated: 1731309251
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/GM.meta b/Assets/SGModule/Common/SGModule/Scripts/GM.meta
new file mode 100644
index 0000000..36cee61
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/GM.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 483f1710e0c24e53a773d154310180e8
+timeCreated: 1731657933
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs b/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs
new file mode 100644
index 0000000..c7b08e2
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs
@@ -0,0 +1,367 @@
+using System;
+using System.Collections.Generic;
+using SGModule.Common;
+using SGModule.Common.Base;
+using SGModule.Common.Helper;
+using UnityEngine;
+
+public class GMTool : SingletonMonoBehaviour {
+ private readonly int buttonHeight = 50;
+ private readonly int fontSize = 35; // 字体大小
+
+ private readonly Dictionary inputFields = new();
+
+ private readonly List items = new();
+ private readonly int spacing = 10; // 控件之间的间距
+ private GUIStyle buttonStyle;
+ private int currentX; // 当前 X 坐标
+ private int currentY; // 当前 Y 坐标
+ private GUIStyle inputFieldStyle;
+ private GUIStyle labelStyle;
+
+ private bool toggleDisplay; // 控制显示与隐藏
+ private int windowWidth; // 屏幕宽度
+
+
+ protected override void Awake() {
+ base.Awake();
+ if (!ConfigManager.GameConfig.isRelease) {
+ IsInitComplete = true;
+ }
+ }
+
+ private void OnGUI() {
+ if (!IsInitComplete) {
+ return;
+ }
+
+ // 初始化样式
+ if (buttonStyle == null || labelStyle == null || inputFieldStyle == null) {
+ InitializeStyles();
+ }
+
+ // 初始化布局
+ StartLayout();
+
+ // 显示开关按钮
+ AddButton(toggleDisplay ? "关闭 GM 工具" : "打开 GM 工具", () => {
+ toggleDisplay = !toggleDisplay;
+ });
+
+ if (!toggleDisplay) {
+ return;
+ }
+
+
+ // 添加控件示例
+ AddLabel("GM 工具");
+ // AddButton("初始化网络模块", () =>
+ // {
+ // var gameConfig = ConfigManager.GetInstance.GetGameConfig();
+ // NetworkKit.Instance.InitData(gameConfig.packageName, gameConfig.isRelease);
+ // });
+ // AddButton("登录", () =>
+ // {
+ // NetworkKit.Instance.LoginRequest("Test", false, (arg0, model) =>
+ // {
+ // Debug.LogError($"登录结果 {arg0}");
+ // });
+ // });
+
+
+ // AddButton($"加载配置模块初始化", () =>
+ // {
+ // ConfigLoader.Instance.Init(NetworkKit.Instance.GetLoginModel().setting,
+ // NetworkKit.Instance.GetLoginModel().cdn_url, new List()
+ // {
+ // new CommonModel("Common"),
+ // new PrizeWheelDataModel("PrizeWheelData"),
+ // },
+ // state =>
+ // {
+ // Debug.LogError($"配置加载状态{state}");
+ // },
+ // (errorName, message) =>
+ // {
+ // Debug.LogError($"配置解析错误 {errorName} 错误信息:{message}");
+ // }
+ // );
+ // });
+ // AddButton($"读取Common配置", () =>
+ // {
+ // var model = ConfigLoader.Instance.GetConfig();
+ // Debug.LogError(model);
+ // });
+ // AddButton($"读取PrizeWheelDataModel配置", () =>
+ // {
+ // var model = ConfigLoader.Instance.GetConfig();
+ // Debug.LogError(model.DataList.Count);
+ // });
+ // AddButton($"测试解析为自定义配置", () =>
+ // {
+ // Debug.LogError(ConfigLoader.Instance.ParesPersonalizedConfig(new PrizeWheelDataModel("PrizeWheelData"), "prize"));
+ // });
+ // AddButton($"读取自定义配置", () =>
+ // {
+ // var personalizedConfig = ConfigLoader.Instance.GetPersonalizedConfig("prize");
+ // Debug.LogError(personalizedConfig.DataList.Count);
+ // });
+
+
+ UpdateItems();
+
+
+ // AddButton("退出游戏", Application.Quit);
+ }
+
+ private void InitializeStyles() {
+ buttonStyle = new GUIStyle(GUI.skin.button) {
+ fontSize = fontSize,
+ alignment = TextAnchor.MiddleCenter,
+ normal = { textColor = Color.green }
+ };
+
+ labelStyle = new GUIStyle(GUI.skin.label) {
+ fontSize = fontSize,
+ normal = { textColor = Color.red }
+ };
+
+ inputFieldStyle = new GUIStyle(GUI.skin.textField) {
+ fontSize = fontSize,
+ alignment = TextAnchor.MiddleLeft
+ };
+ }
+
+ private void StartLayout() {
+ currentX = spacing;
+ currentY = spacing;
+ windowWidth = Screen.width;
+ }
+
+ private void AddButton(string text, Action onClick) {
+ // 计算按钮宽度,基于标题内容自适应
+ var buttonWidth = Mathf.Max(150, Mathf.CeilToInt(buttonStyle.CalcSize(new GUIContent(text)).x) + 20);
+
+ // 换行检查
+ if (currentX + buttonWidth + spacing > windowWidth) {
+ currentX = spacing;
+ currentY += buttonHeight + spacing;
+ }
+
+ // 绘制按钮
+ if (GUI.Button(new Rect(currentX, currentY, buttonWidth, buttonHeight), text, buttonStyle)) {
+ onClick?.Invoke();
+ }
+
+ // 更新下一个控件的位置
+ currentX += buttonWidth + spacing;
+ }
+
+ private void AddLabel(string text) {
+ // // 计算标签宽度和高度
+ // Vector2 size = labelStyle.CalcSize(new GUIContent(text));
+ // int labelWidth = Mathf.CeilToInt(size.x);
+ // int labelHeight = Mathf.CeilToInt(size.y);
+ //
+ // // 换行检查
+ // if (currentX + labelWidth + spacing > windowWidth)
+ // {
+ // currentX = spacing;
+ // currentY += buttonHeight + spacing;
+ // }
+ //
+ // // 绘制标签
+ // GUI.Label(new Rect(currentX, currentY, labelWidth, labelHeight), text, labelStyle);
+ //
+ // // 更新下一个控件的位置
+ // currentX += labelWidth + spacing;
+
+ // 启用自动换行 可用
+ labelStyle.wordWrap = true;
+
+ var size = labelStyle.CalcSize(new GUIContent(text));
+ var labelWidth = Mathf.CeilToInt(size.x);
+ var labelHeight = Mathf.CeilToInt(size.y);
+
+ // 计算标签宽度和高度
+ var maxWidth = windowWidth - spacing * 2; // 标签最大宽度
+ // float labelWidth = maxWidth; // 长文本直接占满一行
+ var needNewRow = labelWidth / maxWidth > 0.6f;
+ if (needNewRow) {
+ labelWidth = maxWidth;
+ labelHeight = (int) labelStyle.CalcHeight(new GUIContent(text), labelWidth);
+ }
+
+ // 换行逻辑:如果当前行剩余宽度不足,提前换行
+ if (currentX + labelWidth + spacing > windowWidth) {
+ currentX = spacing; // 回到左侧
+ currentY += buttonHeight + spacing; // 换到下一行
+ }
+
+ // 绘制标签
+ GUI.Label(new Rect(currentX, currentY, labelWidth, labelHeight), text, labelStyle);
+
+ // 更新位置:占满一整行,因此重置到新行
+ if (needNewRow) {
+ currentX = spacing;
+ currentY += labelHeight + spacing;
+ }
+ else {
+ currentX += labelWidth + spacing;
+ }
+ }
+
+ private void AddInputField(string key, string placeholder, string buttonText, Action onSubmit) {
+ var inputFieldWidth = Mathf.Max(200, Mathf.CeilToInt(inputFieldStyle.CalcSize(new GUIContent(placeholder)).x) + 20);
+ var buttonWidth = Mathf.Max(100, Mathf.CeilToInt(buttonStyle.CalcSize(new GUIContent(buttonText)).x) + 20);
+
+ if (currentX + inputFieldWidth + buttonWidth + spacing * 2 > windowWidth) {
+ currentX = spacing;
+ currentY += buttonHeight + spacing;
+ }
+
+ if (!inputFields.TryGetValue(key, out var inputField)) {
+ inputFields.Add(key, "");
+ }
+
+
+ inputField = GUI.TextField(new Rect(currentX, currentY, inputFieldWidth, buttonHeight), inputField, inputFieldStyle);
+ currentX += inputFieldWidth + spacing;
+
+ if (GUI.Button(new Rect(currentX, currentY, buttonWidth, buttonHeight), buttonText, buttonStyle)) {
+ onSubmit?.Invoke(inputField);
+ }
+
+ inputFields[key] = inputField;
+
+ currentX += buttonWidth + spacing;
+ }
+
+ private void AddSeparator(string text = "") {
+ // 换行以确保分割线占据整行
+ currentX = spacing;
+ currentY += buttonHeight + spacing;
+
+ // // 分割线高度和宽度
+ // int separatorHeight = Mathf.CeilToInt(fontSize * 1.5f); // 动态设置高度
+ // int separatorWidth = windowWidth - spacing * 2;
+ //
+ // // 计算文字尺寸
+ // Vector2 textSize = labelStyle.CalcSize(new GUIContent(text));
+ // int textWidth = Mathf.CeilToInt(textSize.x);
+ //
+ // // 绘制分割线
+ // Rect lineRect = new Rect(currentX, currentY + separatorHeight / 2, separatorWidth, 1);
+ // GUI.Box(lineRect, GUIContent.none);
+ //
+ //
+ // // 绘制文字
+ // if (!string.IsNullOrEmpty(text))
+ // {
+ // GUI.Label(new Rect((windowWidth - textWidth) / 2, currentY, textWidth, separatorHeight), text, labelStyle);
+ // }
+
+ // 分割线宽度和高度
+ var separatorWidth = windowWidth - spacing * 2;
+ var separatorHeight = Mathf.CeilToInt(fontSize * 1.5f); // 分割线高度(文字高度)
+ var lineHeight = Mathf.CeilToInt(fontSize * 0.1f); // 线条高度
+
+ if (string.IsNullOrEmpty(text)) {
+ // 如果没有文字,绘制整行分割线
+ DrawLine(new Rect(currentX, currentY + separatorHeight / 2 - lineHeight / 2, separatorWidth, lineHeight));
+ }
+ else {
+ // 计算文字尺寸
+ var textSize = labelStyle.CalcSize(new GUIContent(text));
+ var textWidth = Mathf.CeilToInt(textSize.x);
+
+ // 计算分割线两侧长度
+ var lineWidth = (separatorWidth - textWidth - spacing * 2) / 2;
+
+ // 绘制左侧线条
+ DrawLine(new Rect(currentX, currentY + separatorHeight / 2 - lineHeight / 2, lineWidth, lineHeight));
+
+ // 绘制文字
+ GUI.Label(new Rect(currentX + lineWidth + spacing, currentY, textWidth, separatorHeight), text, labelStyle);
+
+ // 绘制右侧线条
+ DrawLine(new Rect(currentX + lineWidth + textWidth + spacing * 2, currentY + separatorHeight / 2 - lineHeight / 2, lineWidth,
+ lineHeight));
+ }
+
+ // 更新位置
+ currentY += separatorHeight + spacing;
+ }
+
+ private void DrawLine(Rect rect) {
+ // 设置线条颜色
+ var originalColor = GUI.color;
+ GUI.color = Color.white; // 可以改成其他颜色
+
+ // 绘制线条
+ GUI.DrawTexture(rect, Texture2D.whiteTexture);
+
+ // 恢复原始颜色
+ GUI.color = originalColor;
+ }
+
+ public void AddItem(GMToolItem item) {
+ items.Add(item);
+ }
+
+ private void UpdateItems() {
+ foreach (var item in items) {
+ switch (item.Type) {
+ case GUIType.Label:
+ AddLabel(item.TextFunc.Invoke());
+ break;
+ case GUIType.Button:
+ AddButton(item.TextFunc.Invoke(), () => {
+ item.OnClick?.Invoke(null);
+ });
+ break;
+ case GUIType.InputField:
+ AddInputField(item.Key, item.Placeholder, item.TextFunc.Invoke(), s => {
+ item.OnClick?.Invoke(s);
+ });
+ break;
+ case GUIType.Separator:
+ AddSeparator(item.TextFunc?.Invoke());
+ break;
+ default:
+ Log.Common.Error($"Unsupported GUIType: {item.Type}");
+ break;
+ }
+ }
+ }
+}
+
+public enum GUIType {
+ Label,
+ Button,
+ InputField,
+ Separator // 分割线类型
+}
+
+public class GMToolItem {
+ public string Key;
+ public Action OnClick;
+ public string Placeholder;
+ public Func TextFunc;
+ public GUIType Type;
+
+ ///
+ ///
+ /// 控件类型
+ /// 显示的文本,传入委托可以动态变化
+ /// 点击委托,只有Button与InputField有效,Button可忽略字符串参数,InputField输入的内容会传入
+ /// InputField 需要用到的key,记得保持唯一性,如果重复有可能会导致重复的输入框同步一样的内容
+ /// 提示占位文本
+ public GMToolItem(GUIType type, Func textFunc, Action onClick = null, string key = "", string placeholder = "") {
+ Type = type;
+ TextFunc = textFunc;
+ OnClick = onClick;
+ Key = key;
+ Placeholder = placeholder;
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs.meta
new file mode 100644
index 0000000..6fcce96
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/GM/GMTool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d06d4a3e6b703474f8fd425530b85b87
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper.meta
new file mode 100644
index 0000000..e970df5
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c8ac58d9307eb1c45849414a44d923ca
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs
new file mode 100644
index 0000000..0eb43cb
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Text;
+
+namespace SGModule.Common.Helper {
+ public static class Base64Helper {
+ public static string Encode(string source) {
+ return Base64Encode(Encoding.UTF8, source);
+ }
+
+ public static string Decode(string result) {
+ return Base64Decode(Encoding.UTF8, result);
+ }
+
+ private static string Base64Encode(Encoding encoding, string source) {
+ var bytes = encoding.GetBytes(source);
+ var encode = Convert.ToBase64String(bytes);
+ return encode;
+ }
+
+ private static string Base64Decode(Encoding encoding, string result) {
+ var bytes = Convert.FromBase64String(result);
+ var decode = encoding.GetString(bytes);
+ return decode;
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs.meta
new file mode 100644
index 0000000..67dbe2c
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Base64Helper.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0078c84c6f3f4d0ba79a2ef151bf0545
+timeCreated: 1731309598
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs
new file mode 100644
index 0000000..a44ae30
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs
@@ -0,0 +1,21 @@
+using Newtonsoft.Json.Linq;
+
+namespace SGModule.Common.Helper {
+ // 混合通用方法工具类(放置一些通用的静态函数)
+ public static class CommonUtils {
+ ///
+ /// 深度比较两个对象是否相等,支持复杂结构(如 List、Dictionary、嵌套对象)
+ ///
+ public static bool DeepEquals(T a, T b) {
+ if (a == null && b == null) {
+ return true;
+ }
+
+ if (a == null || b == null) {
+ return false;
+ }
+
+ return JToken.DeepEquals(JToken.FromObject(a), JToken.FromObject(b));
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs.meta
new file mode 100644
index 0000000..bc2a70c
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/CommonUtils.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: cb253d0247f54d55b83685a0e7c51b70
+timeCreated: 1749455481
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs
new file mode 100644
index 0000000..39e3c65
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs
@@ -0,0 +1,35 @@
+using System.Text;
+
+namespace SGModule.Common.Helper {
+ public class Cryptor {
+ public static string Encrypt(string data, string key) {
+ var keyMD5 = MD5Helper.MD5String1(key);
+ var str = Base64Helper.Encode(data + keyMD5);
+
+ var bytes = Encoding.UTF8.GetBytes(str);
+ for (int i = 0, j = bytes.Length - 1; i < j; i += 1, j -= 1) {
+ if (i % 2 == 0) {
+ (bytes[i], bytes[j]) = (bytes[j], bytes[i]);
+ }
+ }
+
+ var loginData = Encoding.UTF8.GetString(bytes);
+ return loginData;
+ }
+
+ public static string Decrypt(string data, string key) {
+ var bytes = Encoding.UTF8.GetBytes(data);
+ for (int i = 0, j = bytes.Length - 1; i < j; i += 1, j -= 1) {
+ if (i % 2 == 0) {
+ (bytes[i], bytes[j]) = (bytes[j], bytes[i]);
+ }
+ }
+
+ var str = Encoding.UTF8.GetString(bytes);
+ var str1 = Base64Helper.Decode(str);
+ var keyMD5 = MD5Helper.MD5String1(key);
+ var result = str1.Replace(keyMD5, string.Empty);
+ return result;
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs.meta
new file mode 100644
index 0000000..9c7ab26
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Cryptor.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 957dffab93b34167b72cdfd2b0e709fe
+timeCreated: 1731309567
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs
new file mode 100644
index 0000000..835715e
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+namespace SGModule.Common.Helper {
+ public static class DeviceHelper {
+ private const string Idfv = "IDFV";
+
+ public static string GetDeviceID(string deviceName = "TestUser002") {
+#if UNITY_IOS && !UNITY_EDITOR
+ deviceName = Keychain.Get(Idfv);
+ if (string.IsNullOrEmpty(deviceName))
+ {
+ deviceName = SystemInfo.deviceUniqueIdentifier;
+ Keychain.Save(Idfv, deviceName);
+ }
+
+ return deviceName;
+#elif UNITY_EDITOR
+ return deviceName;
+#endif
+ return SystemInfo.deviceUniqueIdentifier;
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs.meta
new file mode 100644
index 0000000..b8ecf02
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/DeviceHelper.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 121d8e1769529b440bc85f03a485ec10
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs
new file mode 100644
index 0000000..c4274bc
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs
@@ -0,0 +1,115 @@
+using System;
+using UnityEngine;
+
+namespace SGModule.Common.Helper {
+ public static class Log {
+ // 预定义模块实例
+ public static readonly ModuleLogger Common = new("Common");
+ public static readonly ModuleLogger Net = new("Net", ConfigManager.NetworkConfig?.showNetworkLog ?? false);
+ public static readonly ModuleLogger MarkdownKit = new("MarkdownKit");
+ public static readonly ModuleLogger ApplePay = new("ApplePay");
+ public static readonly ModuleLogger ConfigLoader = new("ConfigLoader");
+ public static readonly ModuleLogger NetKit = new("NetKit");
+ public static readonly ModuleLogger DataStorage = new("DataStorage");
+ public static readonly ModuleLogger IAP = new("IAP");
+
+ private static bool IsEnabled => ConfigManager.GameConfig?.enabledLog ?? false;
+
+ public static void Info(string label, string msg, bool showStack = true) {
+ if (IsEnabled) {
+ InternalLog(LogType.Log, label, msg, LogColors.Info, showStack);
+ }
+ }
+
+ public static void Warning(string label, string msg, bool showStack = true) {
+ if (IsEnabled) {
+ InternalLog(LogType.Warning, label, msg, LogColors.Warning, showStack);
+ }
+ }
+
+ public static void Error(string label, string msg, bool showStack = true) {
+ if (IsEnabled) {
+ InternalLog(LogType.Error, label, msg, LogColors.Error, showStack);
+ }
+ }
+
+ public static void Exception(string label, Exception ex, bool showStack = true) {
+ if (!IsEnabled || ex == null) {
+ return;
+ }
+
+
+ var msg = $"Exception: {ex.Message}";
+ if (showStack && !string.IsNullOrEmpty(ex.StackTrace)) {
+ msg += $"\n{ex.StackTrace}";
+ }
+
+ InternalLog(LogType.Error, label, msg, LogColors.Exception, showStack);
+ }
+
+ internal static void InternalLog(LogType type, string label, string msg, string color, bool showStack) {
+ var formattedMsg = $"[{label}] {msg}";
+
+ var original = Application.GetStackTraceLogType(type);
+ if (!showStack) {
+ Application.SetStackTraceLogType(type, StackTraceLogType.None);
+ }
+
+ Debug.unityLogger.Log(type, formattedMsg);
+
+ if (!showStack) {
+ Application.SetStackTraceLogType(type, original);
+ }
+ }
+ }
+
+ public class ModuleLogger {
+ private readonly bool _isEnabled;
+ private readonly string _label;
+
+ public ModuleLogger(string label, bool isEnabled = true) {
+ _label = label;
+ _isEnabled = isEnabled;
+ }
+
+ private bool IsEnabled => (ConfigManager.GameConfig?.enabledLog ?? false) && _isEnabled;
+
+ public void Info(string msg, bool showStack = true) {
+ if (IsEnabled) {
+ Log.InternalLog(LogType.Log, _label, msg, LogColors.Info, showStack);
+ }
+ }
+
+ public void Warning(string msg, bool showStack = true) {
+ if (IsEnabled) {
+ Log.InternalLog(LogType.Warning, _label, msg, LogColors.Warning, showStack);
+ }
+ }
+
+ public void Error(string msg, bool showStack = true) {
+ if (IsEnabled) {
+ Log.InternalLog(LogType.Error, _label, msg, LogColors.Error, showStack);
+ }
+ }
+
+ public void Exception(Exception ex, bool showStack = true) {
+ if (!IsEnabled || ex == null) {
+ return;
+ }
+
+ var msg = $"Exception: {ex.Message}";
+ if (showStack && !string.IsNullOrEmpty(ex.StackTrace)) {
+ msg += $"\n{ex.StackTrace}";
+ }
+
+ Log.InternalLog(LogType.Error, _label, msg, LogColors.Exception, showStack);
+ }
+ }
+
+ public static class LogColors {
+ public const string Info = "#4CAF50";
+ public const string Warning = "#CC9A06";
+ public const string Error = "#CC423B";
+ public const string Exception = "red"; // 可选保留原文
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs.meta
new file mode 100644
index 0000000..08c60c5
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/Log.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 451867446e034f4194f1319933be9cdd
+timeCreated: 1748248695
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs
new file mode 100644
index 0000000..ecd2405
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs
@@ -0,0 +1,60 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace SGModule.Common.Helper {
+ public class MD5Helper {
+ public static string GetFileMD5(string file) {
+ try {
+ var fs = new FileStream(file, FileMode.Open);
+ MD5 md5 = new MD5CryptoServiceProvider();
+ var retVal = md5.ComputeHash(fs);
+ fs.Close();
+ var sb = new StringBuilder();
+ foreach (var str in retVal) {
+ sb.Append(str.ToString("X2"));
+ }
+
+ return sb.ToString();
+ }
+ catch (Exception ex) {
+ throw new Exception("GetFileMD5 fail error: " + ex.Message);
+ }
+ }
+
+ ///
+ /// 获取字符串的MD5值
+ ///
+ public static string GetStringMD5(string str) {
+ if (string.IsNullOrEmpty(str)) {
+ return null;
+ }
+
+ MD5 md5 = new MD5CryptoServiceProvider();
+ var bytResult = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
+ var strResult = BitConverter.ToString(bytResult);
+ strResult = strResult.Replace("-", string.Empty);
+ return strResult;
+ }
+
+ public static string MD5String1(string text) {
+ var buffer = Encoding.Default.GetBytes(text);
+ var check = new MD5CryptoServiceProvider();
+ var somme = check.ComputeHash(buffer);
+ var result = new StringBuilder();
+ foreach (var a in somme) {
+ var value = a.ToString("X");
+ if (a < 16) {
+ result.Append(0);
+ result.Append(value);
+ }
+ else {
+ result.Append(value);
+ }
+ }
+
+ return result.ToString().ToLower();
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs.meta
new file mode 100644
index 0000000..4f46bc4
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/MD5Helper.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0d8c3bafdc1d41ee87e8c72f54f42007
+timeCreated: 1731309631
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs
new file mode 100644
index 0000000..7a07421
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+namespace SGModule.Common.Helper {
+ public static class ModuleVersion {
+ public static void Show() {
+ var path = Path.Combine(Application.dataPath, "../gupm.toml");
+
+ if (!File.Exists(path)) {
+ Log.Warning("Submodules", $"找不到配置文件: {path}");
+ return;
+ }
+
+ var insideSubmodules = false;
+ var submodules = new Dictionary();
+ var lines = File.ReadAllLines(path);
+
+ foreach (var rawLine in lines) {
+ var line = rawLine.Trim();
+
+ // 进入 [Submodules] 区块
+ if (!insideSubmodules) {
+ if (line.Equals("[Submodules]", StringComparison.OrdinalIgnoreCase)) {
+ insideSubmodules = true;
+ }
+
+ continue;
+ }
+
+ // 如果遇到下一个区块就退出(可选)
+ if (line.StartsWith("[") && line.EndsWith("]")) {
+ break;
+ }
+
+ // 忽略空行和注释
+ if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#")) {
+ continue;
+ }
+
+ // 使用 = 来切分
+ var parts = line.Split(new[] { '=' }, 2);
+ if (parts.Length != 2) {
+ continue;
+ }
+
+ var key = parts[0].Trim();
+ var value = parts[1].Trim().Trim('"');
+
+ submodules[key] = value;
+ }
+
+ foreach (var kv in submodules) {
+ Log.Info("Submodules", $"{kv.Key} : {kv.Value}");
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs.meta
new file mode 100644
index 0000000..62727d7
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/ModuleVersion.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: b578d006bf7b47b8a7ec2d5b48a53c2b
+timeCreated: 1748947020
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs
new file mode 100644
index 0000000..c81b7d4
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using SGModule.Common.Interface;
+
+namespace SGModule.Common.Helper {
+ public static class RandomHelper {
+ private static readonly Random _random = new();
+
+ public static T RandomByWeight(IList items, T fallback) where T : class, IWeighted {
+ var totalWeight = items.Sum(item => item.Weight);
+ if (totalWeight <= 0) {
+ return fallback;
+ }
+
+ var roll = _random.Next(0, totalWeight);
+ var cumulative = 0;
+
+ foreach (var item in items) {
+ cumulative += item.Weight;
+ if (roll < cumulative) {
+ return item;
+ }
+ }
+
+ return items.Last();
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs.meta
new file mode 100644
index 0000000..7856ebe
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/RandomHelper.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 45bcdda204c1483c84aaaf0d6ec0f251
+timeCreated: 1749198281
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs
new file mode 100644
index 0000000..ea39b61
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs
@@ -0,0 +1,40 @@
+using System;
+using Newtonsoft.Json;
+
+namespace SGModule.Common.Helper {
+ public static class SerializeHelper {
+ private static readonly JsonSerializerSettings _defaultUseJsonSettings = new() {
+ Formatting = Formatting.None,
+ DateFormatString = "yyyy/MM/dd HH:mm:ss"
+ };
+
+ private static readonly JsonSerializerSettings _jsonIndentedSettings = new() {
+ Formatting = Formatting.Indented,
+ DateFormatString = "yyyy/MM/dd HH:mm:ss"
+ };
+
+ static SerializeHelper() {
+ JsonConvert.DefaultSettings = () => _defaultUseJsonSettings;
+ }
+
+ public static string ToJson(object obj) {
+ return JsonConvert.SerializeObject(obj, _defaultUseJsonSettings);
+ }
+
+ public static string ToJsonIndented(object obj) {
+ return JsonConvert.SerializeObject(obj, _jsonIndentedSettings);
+ }
+
+ public static string ToJson(object obj, Type type) {
+ return JsonConvert.SerializeObject(obj, type, _defaultUseJsonSettings);
+ }
+
+ public static string ToJson(object obj) {
+ return ToJson(obj, typeof(T));
+ }
+
+ public static T ToObject(string json) {
+ return JsonConvert.DeserializeObject(json);
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs.meta
new file mode 100644
index 0000000..0804aa8
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/SerializeHelper.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9879900ede554789a516d519840ef577
+timeCreated: 1731311911
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs b/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs
new file mode 100644
index 0000000..2596739
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs
@@ -0,0 +1,54 @@
+using System;
+
+namespace SGModule.Common.Helper {
+ public static class TimeHelper {
+ ///
+ /// 将 Unix 时间戳转换为本地时间
+ ///
+ /// 时间戳(秒)
+ /// 可读的本地时间字符串
+ public static string ConvertToLocalTime(long timestamp) {
+ // Unix 时间戳起始时间
+ var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ // 转换为本地时间
+ var localTime = epoch.AddSeconds(timestamp).ToLocalTime();
+
+ return localTime.ToString("yyyy-MM-dd HH:mm:ss");
+ }
+
+ ///
+ /// 将 Unix 时间戳转换为 UTC 时间
+ ///
+ /// 时间戳(秒)
+ /// 可读的 UTC 时间字符串
+ public static string ConvertToUTCTime(long timestamp) {
+ // Unix 时间戳起始时间
+ var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ // 转换为 UTC 时间
+ var utcTime = epoch.AddSeconds(timestamp);
+
+ return utcTime.ToString("yyyy-MM-dd HH:mm:ss");
+ }
+
+ public static string FormatTime(int totalSeconds) {
+ if (totalSeconds < 60) {
+ return $"{totalSeconds}s"; // 小于60秒,直接显示秒
+ }
+
+ if (totalSeconds < 3600) {
+ var minutes = totalSeconds / 60;
+ var seconds = totalSeconds % 60;
+ return $"{minutes}m {seconds}s"; // 小于1小时,显示分秒
+ }
+ else {
+ var hours = totalSeconds / 3600;
+ var remainingSeconds = totalSeconds % 3600;
+ var minutes = remainingSeconds / 60;
+ var seconds = remainingSeconds % 60;
+ return $"{hours}h {minutes}m {seconds}s"; // 超过1小时,显示时分秒
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs.meta
new file mode 100644
index 0000000..ababd77
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Helper/TimeHelper.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f65b3d4cbd7c456bb9373c261aef0932
+timeCreated: 1731662312
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Interface.meta b/Assets/SGModule/Common/SGModule/Scripts/Interface.meta
new file mode 100644
index 0000000..5001e38
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Interface.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f8e5eb462e8045f19663f3e4bb29c5e6
+timeCreated: 1749198053
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs b/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs
new file mode 100644
index 0000000..e6938c6
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs
@@ -0,0 +1,7 @@
+namespace SGModule.Common.Interface {
+ public interface IWeighted {
+ int Weight {
+ get;
+ }
+ }
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs.meta
new file mode 100644
index 0000000..7ba79fa
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Interface/IWeighted.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: c91fe8993478411f8d6a81ce2074a336
+timeCreated: 1749198110
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Keychain.meta b/Assets/SGModule/Common/SGModule/Scripts/Keychain.meta
new file mode 100644
index 0000000..626e213
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Keychain.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 26e8d993c96816f42bf326d832cd0f68
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs b/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs
new file mode 100644
index 0000000..9933e8f
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Runtime.InteropServices;
+using SGModule.Common.Helper;
+
+public static class Keychain {
+ public static bool Save(string key, string value) {
+#if UNITY_IOS
+ return SaveToKeychain(key, value);
+#endif
+ Log.Common.Warning("Keychain is only supported on iOS.");
+ return false;
+ }
+
+ public static string Get(string key) {
+#if UNITY_IOS
+ var resultPtr = GetFromKeychain(key);
+ if (resultPtr != IntPtr.Zero) {
+ var result = Marshal.PtrToStringAuto(resultPtr);
+ return result;
+ }
+
+ return null;
+#endif
+ Log.Common.Warning("Keychain is only supported on iOS.");
+ return null;
+ }
+
+ public static bool Delete(string key) {
+#if UNITY_IOS
+ return DeleteFromKeychain(key);
+#endif
+ Log.Common.Warning("Keychain is only supported on iOS.");
+ return false;
+ }
+#if UNITY_IOS
+
+ [DllImport("__Internal")]
+ private static extern bool SaveToKeychain(string key, string value);
+
+ [DllImport("__Internal")]
+ private static extern IntPtr GetFromKeychain(string key);
+
+ [DllImport("__Internal")]
+ private static extern bool DeleteFromKeychain(string key);
+#endif
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs.meta
new file mode 100644
index 0000000..924e33c
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/Keychain/Keychain.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: acd6a7aa2034443549cb53d6ae963143
\ No newline at end of file
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects.meta b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects.meta
new file mode 100644
index 0000000..799cc04
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5d82ad3c27862f549a7cd0bc3f5b4e9a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs
new file mode 100644
index 0000000..f2cba7e
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs
@@ -0,0 +1,24 @@
+using UnityEngine;
+
+// [CreateAssetMenu(fileName = "GameConfig", menuName = "GameData/GameConfig")]
+public class GameConfig : ScriptableObject {
+ [Header("全局配置")] [HideInInspector] public string packageName;
+
+
+#if GAME_RELEASE
+ private const bool _isRelease = true;
+#else
+ private const bool _isRelease = false;
+#endif
+
+ public bool isRelease => _isRelease;
+
+ private bool _enabledLog = true;
+
+ public bool enabledLog {
+ get => !isRelease && _enabledLog;
+ set => _enabledLog = !isRelease && value;
+ }
+
+ [HideInInspector] public bool hardwareAcceleration = true;
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs.meta
new file mode 100644
index 0000000..d7b22ee
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/GameConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c836612725633cc4093d7ac06e7d9ef1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs
new file mode 100644
index 0000000..13db33c
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+// [CreateAssetMenu(fileName = "NetworkConfig", menuName = "GameData/NetworkConfig")]
+public class NetworkConfig : ScriptableObject {
+ [Header("Network Config")] [Header("显示日志")]
+ public bool showNetworkLog = true;
+
+ [Header("Url配置")] public string debugHost;
+
+ public string releaseHost;
+
+ [Header("连接模式")] public ConnectionMode connectionMode = ConnectionMode.Http;
+}
+
+public enum ConnectionMode {
+ Http, // 基于 HTTP 协议的链接
+ WebSocket // 基于 WebSocket 协议的链接
+}
diff --git a/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs.meta b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs.meta
new file mode 100644
index 0000000..ff90ba4
--- /dev/null
+++ b/Assets/SGModule/Common/SGModule/Scripts/ScriptableObjects/NetworkConfig.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6161e194ecfb437f89a55349867a492e
+timeCreated: 1731317249
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader.meta b/Assets/SGModule/ConfigLoader.meta
new file mode 100644
index 0000000..441b64c
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eab4c61ff4ae48d42a77deb7f47e2dd1
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/README.md b/Assets/SGModule/ConfigLoader/README.md
new file mode 100644
index 0000000..fe316e7
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/README.md
@@ -0,0 +1,70 @@
+# ⚙️ ConfigLoader 配置加载模块
+
+此模块负责配置文件的加载与检测,依赖于 `Common` 通用模块,请确保已安装该模块。
+
+### 主要功能
+
+- 📂 配置文件加载
+- 🔍 配置字段缺失检测
+- ❌ 配置字段冗余检测
+- ⚙️ 自动化插件安装
+- 📝 日志标准化输出
+
+------
+
+## ⚠️ 注意事项
+
+导入项目后,会弹出插件安装提示框。点击“确定”后,插件将自动安装;若点击“取消”,脚本重新编译时仍会再次弹出提示。
+
+- 插件安装需要一定时间,请耐心等待。安装完成后会有弹窗提示。
+- 安装完成后,会自动生成配置文件夹 `Configs`,请将游戏配置文件复制到此文件夹中。
+- **请勿修改配置文件名**。如需替换配置文件,请先删除旧文件,确保文件夹中每个配置只有一份。
+- 游戏首次运行时,会自动将该文件夹复制到游戏的数据存储位置。
+
+------
+
+## 🚀 使用指南
+
+在登录成功后,调用 `ConfigLoader` 的 `Init` 方法传入所需参数,具体参数请查看方法注释。
+
+> 注意:
+>
+> - **List 类型**的配置需继承 `ConfigModel`,不再需要之前的 `IDataList` 接口。
+> - **非 List 类型**配置继承 `ConfigModel`。
+
+### 初始化示例
+
+```csharp
+var loginModel = NetworkKit.Instance.GetLoginModel();
+ConfigLoader.Instance.Init(
+ loginModel.setting,
+ loginModel.cdn_url,
+ new List {
+ new CommonModel("Common"),
+ new SignDailyRewardModel("SignDailyReward"),
+ new TurntableModel("turntable"),
+ // 其它配置...
+ },
+ state => {
+ Debug.Log($"配置加载状态: {state}");
+ },
+ (errorName, message) => {
+ Debug.LogError($"配置解析错误: {errorName},错误信息:{message}");
+ });
+```
+
+------
+
+## 🔍 读取配置示例
+
+```csharp
+// 读取基础配置
+var model = ConfigLoader.Instance.GetConfig();
+
+// 解析自定义配置
+ConfigLoader.Instance.ParesPersonalizedConfig(new PrizeWheelDataModel("PrizeWheelData"), "prize");
+
+// 获取自定义配置
+var personalizedConfig = ConfigLoader.Instance.GetPersonalizedConfig("prize");
+```
+
diff --git a/Assets/SGModule/ConfigLoader/README.md.meta b/Assets/SGModule/ConfigLoader/README.md.meta
new file mode 100644
index 0000000..0a6c16c
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: b25e03cedceda0f4db9aebc261a5bf0a
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/SGModule.meta b/Assets/SGModule/ConfigLoader/SGModule.meta
new file mode 100644
index 0000000..5f9d9f7
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2c34977ebbc9d4440826289429a2adc3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Editor.meta b/Assets/SGModule/ConfigLoader/SGModule/Editor.meta
new file mode 100644
index 0000000..9b48cdb
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c03491d9ce1584a408c18056b93f91d2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs b/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs
new file mode 100644
index 0000000..574f2a0
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs
@@ -0,0 +1,188 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using SGModule.Common.Helper;
+using UnityEditor;
+using UnityEditor.PackageManager;
+using UnityEditor.PackageManager.Requests;
+using PackageInfo = UnityEditor.PackageManager.PackageInfo;
+#if USE_ADDRESSABLES
+using UnityEditor.AddressableAssets;
+#endif
+
+namespace SGModule.Editor {
+ [InitializeOnLoad]
+ public static class AddressablesManager {
+ private const string AddressablesPackageName = "com.unity.addressables";
+ private const string AddressablesSymbol = "USE_ADDRESSABLES";
+ private static AddRequest _addRequest;
+
+ // 安装标记,避免重复弹窗
+ private static bool _isInstallingAddressables;
+
+ static AddressablesManager() {
+ EditorApplication.projectChanged += OnProjectChanged; // 监听项目变更
+
+ CheckAndSetupAddressables();
+ }
+
+ private static string DefaultConfigsPath => "Assets/Configs"; // 默认的 Addressables 配置路径
+
+ private static void CheckAndSetupAddressables() {
+ if (IsAddressablesInstalled()) {
+ Log.Info("ConfigLoader", "Addressables 已安装,正在初始化...");
+
+ AddScriptingDefineSymbol(AddressablesSymbol);
+
+#if USE_ADDRESSABLES
+ EnsureAddressablesConfigured();
+#endif
+ }
+ else {
+ RemoveScriptingDefineSymbol(AddressablesSymbol);
+ if (!_isInstallingAddressables) {
+ PromptToInstallAddressables();
+ }
+ }
+ }
+
+ private static bool IsAddressablesInstalled() {
+ return PackageInfo.GetAllRegisteredPackages().Any(package => package.name == AddressablesPackageName);
+ }
+
+ private static void PromptToInstallAddressables() {
+ var install = EditorUtility.DisplayDialog(
+ "Addressables 未安装",
+ "当前插件依赖 Addressables 功能,请安装以确保正常使用。\n\n是否立即安装 Addressables?",
+ "安装",
+ "取消");
+
+ if (install) {
+ InstallAddressables();
+ }
+ else {
+ Log.Warning("ConfigLoader", "用户取消安装 Addressables,部分功能可能无法正常使用!");
+ }
+ }
+
+ private static void InstallAddressables() {
+ if (_isInstallingAddressables) {
+ return; // 防止重复安装
+ }
+
+ Log.Info("ConfigLoader", "开始安装 Addressables...");
+
+ _isInstallingAddressables = true; // 标记正在安装,避免重复弹窗
+ _addRequest = Client.Add(AddressablesPackageName);
+
+ EditorApplication.update += MonitorAddRequest;
+ }
+
+ private static void MonitorAddRequest() {
+ if (_addRequest == null || !_addRequest.IsCompleted) {
+ return;
+ }
+
+ EditorApplication.update -= MonitorAddRequest;
+
+ if (_addRequest.Status == StatusCode.Success) {
+ Log.Info("ConfigLoader", "Addressables 安装成功!");
+
+ EditorUtility.DisplayDialog("安装完成", "Addressables 安装成功,请稍候等待 Unity 刷新。", "确定");
+
+ CheckAndSetupAddressables();
+ }
+ else if (_addRequest.Status >= StatusCode.Failure) {
+ Log.Error("ConfigLoader", $"安装 Addressables 失败:{_addRequest.Error.message}");
+
+ EditorUtility.DisplayDialog("安装失败", $"安装 Addressables 失败:{_addRequest.Error.message}", "确定");
+ }
+
+ _isInstallingAddressables = false; // 重置标记
+ }
+
+ private static void AddScriptingDefineSymbol(string symbol) {
+ var symbols = new List(PlayerSettings
+ .GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(';'));
+ if (symbols.Contains(symbol)) {
+ return;
+ }
+
+
+ symbols.Add(symbol);
+ PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup,
+ string.Join(";", symbols));
+ Log.Info("ConfigLoader", $"已添加脚本定义符号: {symbol}");
+ }
+
+ private static void RemoveScriptingDefineSymbol(string symbol) {
+ var symbols = new List(PlayerSettings
+ .GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(';'));
+ if (symbols.Contains(symbol)) {
+ symbols.Remove(symbol);
+ PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup,
+ string.Join(";", symbols));
+
+ Log.Info("ConfigLoader", $"已移除脚本定义符号: {symbol}");
+ }
+ }
+
+ private static void OnProjectChanged() {
+ Log.Info("ConfigLoader", "检测到项目变更,重新检查 Addressables 状态...");
+
+ CheckAndSetupAddressables();
+ }
+
+#if USE_ADDRESSABLES
+ private static void EnsureAddressablesConfigured() {
+ var settings = AddressableAssetSettingsDefaultObject.Settings;
+
+ if (settings == null) {
+ Log.Info("ConfigLoader", "正在初始化 Addressables 设置...");
+
+ settings = AddressableAssetSettingsDefaultObject.GetSettings(true); // 自动创建配置
+ }
+
+ // 确保默认的 Configs 文件夹存在并被添加到 Addressables
+ var needRefresh = false;
+ if (!Directory.Exists(DefaultConfigsPath)) {
+ Directory.CreateDirectory(DefaultConfigsPath);
+ Log.Info("ConfigLoader", $"已创建文件夹: {DefaultConfigsPath}");
+
+ needRefresh = true;
+ }
+
+ if (!IsFolderInAddressables(DefaultConfigsPath)) {
+ var guid = AssetDatabase.AssetPathToGUID(DefaultConfigsPath);
+ var group = settings.DefaultGroup;
+ settings.CreateOrMoveEntry(guid, group)?.SetLabel("config", true, true);
+ needRefresh = true;
+ }
+
+ if (needRefresh) {
+ AssetDatabase.Refresh();
+ }
+ }
+
+ private static bool IsFolderInAddressables(string folderPath) {
+ var settings = AddressableAssetSettingsDefaultObject.Settings;
+ foreach (var group in settings.groups)
+ {
+ if (group)
+ {
+ foreach (var entry in group.entries)
+ {
+ if (AssetDatabase.GUIDToAssetPath(entry.guid) == folderPath)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+
+ return false;
+ }
+#endif
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs.meta
new file mode 100644
index 0000000..784773a
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Editor/AddressablesManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 383ac67f695b4c6e94ba988c9303cd5b
+timeCreated: 1733734050
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts.meta
new file mode 100644
index 0000000..91bf863
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 34c8928adac69ec44ac63b385ef330d1
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader.meta
new file mode 100644
index 0000000..84dbf2c
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 53a14b320d93d7c439c59c8190a874ab
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs
new file mode 100644
index 0000000..d36db5a
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using SGModule.Common.Helper;
+
+namespace SGModule.ConfigLoader {
+ public class ConfigDataManager {
+ private readonly Dictionary _configData = new();
+ private readonly HashSet _usedKeys = new();
+ private Dictionary _jsonDictionary = new();
+
+
+ public void SetJsonDictionary(string json) {
+ _jsonDictionary = SerializeHelper.ToObject>(json);
+ _usedKeys.Clear();
+ }
+
+ public void AddConfig(Type type, object instance) {
+ _configData[type] = instance;
+ }
+
+ public void AddConfig(object configModel) {
+ var type = configModel.GetType();
+ _configData[type] = configModel;
+ }
+
+ public T GetConfig() where T : class {
+ if (_configData.TryGetValue(typeof(T), out var obj)) {
+ return obj as T;
+ }
+
+ Log.ConfigLoader.Error($"未找到类型 {typeof(T).FullName} 的配置");
+ return null;
+ }
+
+ public bool TryGetJsonValue(string key, out object value) {
+ if (!_jsonDictionary.TryGetValue(key, out value)) {
+ return false;
+ }
+
+ _usedKeys.Add(key);
+ return true;
+ }
+
+ public IEnumerable GetUnusedKeys() {
+ return _jsonDictionary.Keys.Except(_usedKeys);
+ }
+
+ public IEnumerable GetJsonKeys() {
+ return _jsonDictionary.Keys;
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs.meta
new file mode 100644
index 0000000..786fe08
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigDataManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 223b606b799d46c2a7e684cba7c5df6a
+timeCreated: 1753950649
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs
new file mode 100644
index 0000000..9c8598f
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs
@@ -0,0 +1,167 @@
+using System;
+using System.IO;
+using SGModule.Common.Helper;
+using UnityEngine;
+
+namespace SGModule.ConfigLoader {
+ public class ConfigFileManager {
+ private const int MaxErrorCount = 6;
+ private const string ConfigFileNameKey = "ConfigFileName";
+ private const string FirstLaunchKey = "FirstLaunch";
+
+ private int _initConfigErrorCount;
+
+ private bool HasExceededMaxErrors => _initConfigErrorCount > MaxErrorCount;
+ private static bool IsFirstLaunch => !PlayerPrefs.HasKey(FirstLaunchKey);
+ private static string SavedConfigFileName => PlayerPrefs.GetString(ConfigFileNameKey);
+
+ private static void SetFirstLaunch() {
+ PlayerPrefs.SetInt(FirstLaunchKey, 1);
+ }
+
+ private static void SetSavedConfigFileName(string name) {
+ PlayerPrefs.SetString(ConfigFileNameKey, name);
+ }
+
+ private void IncrementErrorCount() {
+ _initConfigErrorCount++;
+ }
+
+ // 检查是否需要下载新配置,基于传入的期望配置文件名setting
+ private static bool HasNewConfig(string expectedSetting) {
+ if (string.IsNullOrEmpty(SavedConfigFileName)) {
+ return true;
+ }
+
+ return !SavedConfigFileName.Equals(expectedSetting);
+ }
+
+ private void FirstLaunchCopyConfig(Action callback) {
+ SetFirstLaunch();
+
+ FileNetworkManager.Instance.CopyStreamingAssetsToPersistentDataPath(result => {
+ var isSuccess = false;
+ if (result) {
+ var names = FileNetworkManager.Instance.GetFileNamesFromPersistentDataPath(FileNetworkManager.FolderName);
+ if (names.Length > 0) {
+ SetSavedConfigFileName(names[0]);
+ isSuccess = true;
+ }
+ }
+ else {
+ Log.ConfigLoader.Error("拷贝文件失败 请检查Configs文件夹是否有配置文件");
+ }
+
+ if (!isSuccess) {
+ IncrementErrorCount();
+ }
+
+ callback?.Invoke(isSuccess);
+ });
+ }
+
+ private void DownloadConfig(string cdnUrl, string setting, Action callback) {
+ var url = $"{cdnUrl}/config/{setting}";
+ Log.ConfigLoader.Info($"开始下载配置文件 {url}", false);
+ FileNetworkManager.Instance.ReadData(url, result => {
+ if (!string.IsNullOrEmpty(result)) {
+ SetSavedConfigFileName(setting);
+ FileNetworkManager.Instance.WriteToPersistentData(FileNetworkManager.Instance.GetConfigFOlderPath(), setting, result);
+ callback?.Invoke(true, result);
+ }
+ else {
+ Log.ConfigLoader.Error("下载配置文件失败");
+ IncrementErrorCount();
+ callback?.Invoke(false, null);
+ }
+ });
+ }
+
+ private void ReadLocalConfig(Action callback) {
+ var savedCfgName = SavedConfigFileName;
+ Log.ConfigLoader.Info($"开始读取本地配置文件 {savedCfgName}", false);
+ if (string.IsNullOrEmpty(savedCfgName)) {
+ IncrementErrorCount();
+ callback?.Invoke(false, null);
+ return;
+ }
+
+ var path = Path.Combine(FileNetworkManager.Instance.GetConfigFOlderPath(), savedCfgName);
+ FileNetworkManager.Instance.ReadData(path, result => {
+ if (!string.IsNullOrEmpty(result)) {
+ callback?.Invoke(true, result);
+ }
+ else {
+ Log.ConfigLoader.Error("读取本地数据异常");
+ IncrementErrorCount();
+ callback?.Invoke(false, null);
+ }
+ });
+ }
+
+ ///
+ /// 配置文件检查与加载流程
+ ///
+ public void CheckAndLoadConfig(ConfigInitOptions initOptions, Action onConfigLoaded, Action callback) {
+ if (HasExceededMaxErrors) {
+ callback?.Invoke(ConfigLoaderState.Failed);
+ return;
+ }
+
+ if (IsFirstLaunch) {
+ FirstLaunchCopyConfig(success => {
+ if (!success) {
+ IncrementErrorCount();
+ }
+
+ CheckAndLoadConfig(initOptions, onConfigLoaded, callback);
+ });
+ return;
+ }
+
+ if (HasNewConfig(initOptions.Setting)) {
+ DownloadConfig(initOptions.CdnUrl, initOptions.Setting, (success, json) => {
+ if (success) {
+ ReloadConfig(json, onConfigLoaded, callback);
+ }
+ else {
+ ReadLocalConfig((readSuccess, localJson) => {
+ if (readSuccess) {
+ ReloadConfig(localJson, onConfigLoaded, callback);
+ }
+ else {
+ callback?.Invoke(ConfigLoaderState.Failed);
+ }
+ });
+ }
+ });
+ return;
+ }
+
+ ReadLocalConfig((success, json) => {
+ if (success) {
+ ReloadConfig(json, onConfigLoaded, callback);
+ }
+ else {
+ FirstLaunchCopyConfig(result => {
+ if (!result) {
+ IncrementErrorCount();
+ }
+
+ CheckAndLoadConfig(initOptions, onConfigLoaded, callback);
+ });
+ }
+ });
+ }
+
+ private static void ReloadConfig(string json, Action onConfigLoaded, Action callback) {
+ if (string.IsNullOrWhiteSpace(json)) {
+ callback?.Invoke(ConfigLoaderState.JsonEmptyError);
+ return;
+ }
+
+ onConfigLoaded?.Invoke(json);
+ callback?.Invoke(ConfigLoaderState.Successful);
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs.meta
new file mode 100644
index 0000000..3f46ec9
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigFileManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ecda816ab1fc4edaa3948be9e79fbdd2
+timeCreated: 1753950339
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs
new file mode 100644
index 0000000..75d836b
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace SGModule.ConfigLoader {
+ public enum ConfigLoaderState {
+ None,
+ Failed,
+ JsonEmptyError,
+ Successful
+ }
+
+ public class ConfigInitOptions {
+ // 配置文件名
+ public string Setting {
+ get;
+ set;
+ }
+
+ // 下载配置的地址
+ public string CdnUrl {
+ get;
+ set;
+ }
+
+ // 配置加载回调
+ public Action OnComplete {
+ get;
+ set;
+ }
+
+ // 配置解析错误回调
+ public Action OnError {
+ get;
+ set;
+ }
+
+ // 处理未标记的配置
+ public Action OnHandleUnmarkedConfig {
+ get;
+ set;
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs.meta
new file mode 100644
index 0000000..01458de
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigInitOptions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f04e729bc4b34a4c8a44785e9aef732b
+timeCreated: 1753946665
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs
new file mode 100644
index 0000000..826fca4
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using SGModule.Common;
+using SGModule.Common.Base;
+using SGModule.Common.Helper;
+
+namespace SGModule.ConfigLoader {
+ public class ConfigLoader : SingletonMonoBehaviour {
+ private readonly ConfigDataManager _dataManager = new();
+ private readonly ConfigFileManager _fileManager = new();
+ private ConfigInitOptions _initOptions;
+ private bool _isConfigLoaded;
+
+
+ public void Init(ConfigInitOptions options) {
+ _initOptions = options ?? throw new ArgumentNullException(nameof(options));
+ IsInitComplete = true;
+
+ Log.ConfigLoader.Info("Setting: " + _initOptions.Setting);
+
+ _fileManager.CheckAndLoadConfig(_initOptions, ReloadConfig, state => {
+ if (state == ConfigLoaderState.Successful) {
+ Log.ConfigLoader.Info($"Data read successfully: {SerializeHelper.ToJsonIndented(GetJsonKeys())}", false);
+ ConfigParser.ParseAllConfigs(new ParseConfigOptions {
+ OnParsed = (type, instance) => _dataManager.AddConfig(type, instance),
+ OnError = _initOptions.OnError,
+ OnHandleUnmarkedConfig = _initOptions.OnHandleUnmarkedConfig
+ });
+ }
+
+ _initOptions.OnComplete?.Invoke(state);
+ });
+ }
+
+ private void ReloadConfig(string json) {
+ if (string.IsNullOrWhiteSpace(json)) {
+ return;
+ }
+
+ if (!json.StartsWith("{")) {
+ json = Cryptor.Decrypt(json, ConfigManager.GameConfig.packageName);
+ }
+
+ _dataManager.SetJsonDictionary(json);
+ _isConfigLoaded = true;
+ }
+
+
+ public T GetConfig() where T : class {
+ return _dataManager.GetConfig();
+ }
+
+ public void AddConfig(object configModel) {
+ _dataManager.AddConfig(configModel);
+ }
+
+ public bool TryGetJsonValue(string key, out object value) {
+ return _dataManager.TryGetJsonValue(key, out value);
+ }
+
+ public IEnumerable GetUnusedKeys() {
+ return _dataManager.GetUnusedKeys();
+ }
+
+ public IEnumerable GetJsonKeys() {
+ return _dataManager.GetJsonKeys();
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs.meta
new file mode 100644
index 0000000..969a44e
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/ConfigLoader.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9336c81edc514b209f5d055056dbee52
+timeCreated: 1753950686
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs
new file mode 100644
index 0000000..5d07883
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs
@@ -0,0 +1,235 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using SGModule.Common.Base;
+using SGModule.Common.Helper;
+using UnityEngine;
+using UnityEngine.AddressableAssets;
+using UnityEngine.Networking;
+using UnityEngine.ResourceManagement.AsyncOperations;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+#if USE_ADDRESSABLES
+#endif
+
+namespace SGModule.ConfigLoader {
+ public class FileNetworkManager : SingletonMonoBehaviour {
+ public const string FolderName = "Configs";
+ private const string FolderLabel = "config";
+ private string _configFolderPath;
+
+ protected override void Awake() {
+ base.Awake();
+
+ _configFolderPath = Path.Combine(Application.persistentDataPath, FolderName);
+ }
+
+ public string GetConfigFOlderPath() {
+ return _configFolderPath;
+ }
+
+ // 示例解析文件列表方法(你可以根据实际需求实现)
+ private List ParseFileList(string data) {
+ // 假设 data 是文件列表的文本,解析文件名
+ // 根据实际情况解析,例如通过换行符分割
+ return data.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToList();
+ }
+
+ public void CopyStreamingAssetsToPersistentDataPath(Action onComplete = null) {
+ // 如果目标文件夹不存在,创建它
+ if (!Directory.Exists(_configFolderPath)) {
+ Directory.CreateDirectory(_configFolderPath);
+ }
+
+ StartCoroutine(CopyFile(onComplete));
+ }
+
+ private void HandleInitializationError() {
+ // 检查文件是否存在
+ var path = $"{Application.dataPath}/Library/com.unity.addressables/aa/Android/settings.json";
+ if (!File.Exists(path)) {
+ Log.ConfigLoader.Warning(
+ $"Settings file not found at: {path}. Rebuilding Addressables may be required.");
+ }
+
+
+ // 提示用户或执行其他逻辑
+ // 比如:显示弹窗或退出程序
+ }
+
+ private IEnumerator CopyFile(Action onComplete = null) {
+#if USE_ADDRESSABLES
+ var handle = Addressables.LoadResourceLocationsAsync(FolderLabel);
+
+ yield return handle;
+
+ if (handle.Status == AsyncOperationStatus.Succeeded) {
+ // 查找以 ".json" 结尾的文件
+ var jsonLocation = handle.Result.FirstOrDefault(loc => loc.PrimaryKey.EndsWith(".json"));
+
+ if (jsonLocation != null) {
+ var jsonFileName = Path.GetFileName(jsonLocation.PrimaryKey);
+ // 加载 JSON 文件
+ var textAssetAsync = Addressables.LoadAssetAsync(jsonLocation);
+
+ yield return textAssetAsync;
+
+ if (textAssetAsync.Status == AsyncOperationStatus.Succeeded) {
+ var jsonFile = textAssetAsync.Result;
+ Log.ConfigLoader.Info($"Loaded JSON Name:{jsonFileName} content: " + jsonFile.text);
+
+
+ var destFilePath = Path.Combine(_configFolderPath, jsonFileName);
+ File.WriteAllBytes(destFilePath, jsonFile.bytes);
+ onComplete?.Invoke(true);
+ }
+ else {
+ Log.ConfigLoader.Error("Failed to load JSON file");
+
+ onComplete?.Invoke(false);
+ }
+ }
+ else {
+ Log.ConfigLoader.Error("No JSON file found in folder");
+
+ onComplete?.Invoke(false);
+ }
+ }
+ else {
+ Log.ConfigLoader.Error("Failed to load folder resources");
+
+ onComplete?.Invoke(false);
+ }
+#else
+ Log.Error( "没有 Addressables 插件,请检查 ");
+ yield break;
+#endif
+ }
+
+ private IEnumerator CopyFile(string sourceFile, string destFile, Action onComplete = null) {
+ var filePath = "file://" + sourceFile;
+
+ using (var www = UnityWebRequest.Get(filePath)) {
+ yield return www.SendWebRequest();
+
+ if (www.result == UnityWebRequest.Result.Success) {
+ File.WriteAllBytes(destFile, www.downloadHandler.data);
+ Log.ConfigLoader.Info($"File copied to {destFile}");
+ onComplete?.Invoke(true);
+ }
+ else {
+ Log.ConfigLoader.Error("Failed to copy file: " + www.error);
+
+ onComplete?.Invoke(false);
+ }
+ }
+ }
+
+ ///
+ /// 读取或下载
+ ///
+ ///
+ ///
+ public void ReadData(string path, Action callback) {
+ StartCoroutine(ReadDataEnumerator(path, callback));
+ }
+
+ ///
+ /// 读取或下载
+ ///
+ ///
+ ///
+ ///
+ private IEnumerator ReadDataEnumerator(string path, Action callback) {
+ string fullPath;
+
+ // 判断是网络URL还是本地文件路径
+ if (path.StartsWith("http://") || path.StartsWith("https://")) {
+ fullPath = path; // 网络URL
+#if UNITY_EDITOR
+ if (path.StartsWith("http://") && PlayerSettings.insecureHttpOption == InsecureHttpOption.NotAllowed) {
+ Log.ConfigLoader.Error("发起了 HTTP 链接,但设置了不允许非Https连接,请检查设置!!!");
+
+ callback?.Invoke(null);
+ yield break;
+ }
+#endif
+ }
+ else {
+ // 本地文件路径
+ fullPath = "file://" + path;
+ }
+
+ // 使用UnityWebRequest读取数据
+ using (var webRequest = UnityWebRequest.Get(fullPath)) {
+ yield return webRequest.SendWebRequest();
+
+ if (webRequest.result == UnityWebRequest.Result.ConnectionError ||
+ webRequest.result == UnityWebRequest.Result.ProtocolError) {
+ Log.ConfigLoader.Error($"Error while reading file: {webRequest.error} path: {fullPath}");
+
+ callback?.Invoke(null); // 返回null表示出错
+ }
+ else {
+ var data = webRequest.downloadHandler.text;
+ callback?.Invoke(data); // 通过回调传出数据
+ }
+ }
+ }
+
+ ///
+ /// 将内容写入指定文件,并删除原有文件。
+ ///
+ /// 文件夹名称
+ /// 文件名称
+ /// 要写入的内容
+ public void WriteToPersistentData(string folderName, string fileName, string content) {
+ // 获取持久化数据路径
+ var folderPath = Path.Combine(Application.persistentDataPath, folderName);
+
+ // 如果文件夹不存在,则创建它
+ if (!Directory.Exists(folderPath)) {
+ Directory.CreateDirectory(folderPath);
+ }
+
+ // 删除原有文件
+ var existingFiles = Directory.GetFiles(folderPath);
+ foreach (var file in existingFiles) {
+ File.Delete(file);
+ }
+
+ // 完整文件路径
+ var filePath = Path.Combine(folderPath, fileName);
+
+ // 写入新文件
+ File.WriteAllText(filePath, content);
+
+ Log.ConfigLoader.Info($"File written to: {filePath}");
+ }
+
+
+ ///
+ /// 提取指定目录下所有文件文件名
+ ///
+ ///
+ ///
+ public string[] GetFileNamesFromPersistentDataPath(string subdirectory) {
+ var directoryPath = Path.Combine(Application.persistentDataPath, subdirectory);
+
+ if (Directory.Exists(directoryPath))
+ // 获取目录中的所有文件名
+ {
+ return Directory.GetFiles(directoryPath)
+ .Select(Path.GetFileName) // 只提取文件名
+ .ToArray();
+ }
+
+ Log.ConfigLoader.Warning($"Directory does not exist: {directoryPath}");
+ return Array.Empty(); // 返回空数组
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs.meta
new file mode 100644
index 0000000..34ce11b
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigLoader/FileNetworkManager.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 35da25a8aaf547b8accde3b52c38a887
+timeCreated: 1731982304
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser.meta
new file mode 100644
index 0000000..15279c2
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: f15ea40a5b634081a8b21a4af531f8b5
+timeCreated: 1753869849
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs
new file mode 100644
index 0000000..140ca5c
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace SGModule.ConfigLoader {
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ public class ConfigKeyAttribute : Attribute {
+ public ConfigKeyAttribute(string key, bool isList = true) {
+ Key = key;
+ IsList = isList;
+ }
+
+ public string Key {
+ get;
+ }
+
+ public bool IsList {
+ get;
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs.meta
new file mode 100644
index 0000000..a5113d1
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigKeyAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 93c57a91da9d46baba3feb3a46719bb2
+timeCreated: 1753869869
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs
new file mode 100644
index 0000000..3916a02
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using SGModule.Common.Helper;
+
+namespace SGModule.ConfigLoader {
+ public static class ConfigParser {
+ public static void ParseAllConfigs(ParseConfigOptions options) {
+ var onParsed = options.OnParsed;
+ var errorCallback = options.OnError;
+ var onHandleUnmarkedConfig = options.OnHandleUnmarkedConfig;
+
+ var configTypes = Assembly.GetExecutingAssembly().GetTypes()
+ .Where(t => t.GetCustomAttribute() != null);
+
+
+ foreach (var type in configTypes) {
+ var attr = type.GetCustomAttribute();
+ var key = attr.Key;
+
+
+ if (!ConfigLoader.Instance.TryGetJsonValue(key, out var jsonData)) {
+ errorCallback?.Invoke(key, "未找到对应配置数据");
+ continue;
+ }
+
+ try {
+ var json = jsonData.ToString();
+ var targetType = attr.IsList ? typeof(List<>).MakeGenericType(type) : type;
+ var parsedInstance = JsonConvert.DeserializeObject(json, targetType);
+
+ if (parsedInstance == null) {
+ errorCallback?.Invoke(key, "解析返回空");
+ continue;
+ }
+
+#if !GAME_RELEASE
+ RunFieldCheck(json, type, key, attr.IsList);
+#endif
+
+ // 把结果交还给调用方
+ onParsed?.Invoke(targetType, parsedInstance);
+ }
+ catch (Exception ex) {
+ errorCallback?.Invoke(key, $"反序列化异常: {ex.Message}");
+ Log.ConfigLoader.Error($"配置 {key} 反序列化异常: {ex}");
+ }
+ }
+
+ // 处理未标记的配置
+ onHandleUnmarkedConfig?.Invoke();
+
+ // 打印未使用的 jsonDict 中的 key
+ var unusedKeys = ConfigLoader.Instance.GetUnusedKeys().ToList();
+ if (unusedKeys.Count > 0) {
+ Log.ConfigLoader.Warning($"未使用的配置表: {string.Join(", ", unusedKeys)};", false);
+ }
+ }
+
+
+#if !GAME_RELEASE
+ private static void RunFieldCheck(string json, Type type, string key, bool isList) {
+ var objectsToCheck = new List();
+
+ try {
+ if (isList) {
+ var jsonArray = JArray.Parse(json);
+ objectsToCheck.AddRange(jsonArray.OfType());
+ }
+ else {
+ var singleObj = JObject.Parse(json);
+ objectsToCheck.Add(singleObj);
+ }
+ }
+ catch (Exception ex) {
+ Log.ConfigLoader.Warning($"[{key}] JSON 解析失败: {ex.Message}");
+ return;
+ }
+
+ var classFields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
+ .Select(f => f.Name)
+ .ToHashSet();
+
+ var allMissingFields = new HashSet();
+ var allExtraFields = new HashSet();
+
+ foreach (var obj in objectsToCheck) {
+ var jsonKeys = obj.Properties().Select(p => p.Name).ToHashSet();
+
+ allMissingFields.UnionWith(classFields.Except(jsonKeys));
+ allExtraFields.UnionWith(jsonKeys.Except(classFields));
+ }
+
+ if (allMissingFields.Count > 0 || allExtraFields.Count > 0) {
+ var msg = $"[{key}]";
+ if (allMissingFields.Count > 0) {
+ msg += $" 缺少字段: {string.Join(", ", allMissingFields.OrderBy(f => f))};";
+ }
+
+ if (allExtraFields.Count > 0) {
+ msg += $" 多余字段: {string.Join(", ", allExtraFields.OrderBy(f => f))};";
+ }
+
+ var shortJson = json.Length > 1000 ? json.Substring(0, 1000) + "..." : json;
+ Log.ConfigLoader.Warning($"[{key}] Json: {shortJson}", false);
+ Log.ConfigLoader.Warning(msg, false);
+ }
+ }
+#endif
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs.meta
new file mode 100644
index 0000000..fc31535
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ConfigParser.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ddad7a16d91d4f48901b7217aa6af0e9
+timeCreated: 1753870514
\ No newline at end of file
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs
new file mode 100644
index 0000000..a0be806
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace SGModule.ConfigLoader {
+ public class ParseConfigOptions {
+ public Action OnParsed {
+ get;
+ set;
+ }
+
+ public Action OnError {
+ get;
+ set;
+ }
+
+ public Action OnHandleUnmarkedConfig {
+ get;
+ set;
+ }
+ }
+}
diff --git a/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs.meta b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs.meta
new file mode 100644
index 0000000..db7f76d
--- /dev/null
+++ b/Assets/SGModule/ConfigLoader/SGModule/Scripts/ConfigParser/ParseConfigOptions.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: c27fb301f6224b778cdfd006ca12d7e5
+timeCreated: 1753947404
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage.meta b/Assets/SGModule/DataStorage.meta
new file mode 100644
index 0000000..9c105ab
--- /dev/null
+++ b/Assets/SGModule/DataStorage.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3d214ea84d314b64d8cbc659cd3912f3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/README.md b/Assets/SGModule/DataStorage/README.md
new file mode 100644
index 0000000..6e07f3d
--- /dev/null
+++ b/Assets/SGModule/DataStorage/README.md
@@ -0,0 +1,139 @@
+# 📦 DataStorage 数据存储模块
+
+## ✨ 简介
+
+该模块是一个基于 Unity + Easy Save 的本地数据存储系统,具备:
+
+- ✅ 本地缓存机制(避免频繁磁盘 IO)
+- ✅ 自动保存机制(按时间间隔或调用次数)
+- ✅ 云同步支持(支持上传 JSON,或导入云端数据)
+- ✅ 数据版本控制
+- ✅ 类型安全的 `DataStorage` 封装
+- ✅ 可调试的 GM 工具接口
+
+------
+
+## 📁 使用说明
+
+### 🔹 1. 定义数据键
+
+在模块初始化之前,使用 `DataKeyDic.Register` 注册数据键名(通常在 `DataStorage` 构造时自动完成):
+
+```c#
+var playerName = new DataStorage("PlayerName", "Guest");
+playerName.Value = "Pius123";
+```
+
+或使用保存回调监听值变化:
+
+```c#
+var coins = new DataStorage("CoinAmount", 0, (oldVal, newVal) => {
+ Debug.Log($"金币变化:{oldVal} -> {newVal}");
+});
+```
+
+### 🔹 2. 保存和读取数据
+
+```c#
+coins.Value = 100; // 保存数据(自动缓存 + 标记待保存)
+var coinAmount = coins.Value; // 从缓存读取(或回退至本地/云端)
+coins.Save(); // 强制保存(即使值没变)
+```
+
+也可直接使用底层 API 操作(不建议):
+
+```c#
+DataManager.Instance.SaveData("Level", 5);
+int level = DataManager.Instance.LoadData("Level", 1);
+```
+
+### 🔹 3. 自动保存逻辑
+
+模块会在以下时机自动保存数据到磁盘(使用 Easy Save):
+
+- ⏱ 每隔 15 秒(可配置)
+- 🔁 累积 `SaveData` 达到 20 次(可配置)
+- 🚫 App 暂停、退出时
+- 📡 数据版本每增加两次触发一次 `_saveCallback`(用于云上传)
+
+------
+
+## 🌐 云同步支持
+
+### ✅ 导出 JSON 上传云端
+
+```c#
+DataManager.Instance.AddSaveCallback((json, version, onQuit) => {
+ // 上传 json 到云端,携带版本 version
+});
+```
+
+每次本地数据保存时(根据频率控制)会自动回调此方法。
+
+### ✅ 从云端导入数据
+
+```c#
+DataManager.Instance.ImportFromJson(jsonFromServer, versionFromServer);
+```
+
+- 若云端版本 > 本地版本:自动覆盖并保存到本地
+- 若云端版本 < 本地版本:会自动触发 `_saveCallback` 上传本地数据覆盖云端
+
+------
+
+## 🔧 GM 调试接口(可选)
+
+调用 `DataManager.Instance.Init()` 可注册 GM 工具按钮:
+
+- 🧹 清空所有数据
+- 🗂 打印所有缓存键值对
+
+------
+
+## 🧠 数据结构概览
+
+| 类名 | 说明 |
+| ---------------------------- | ---------------------------------------------- |
+| `DataManager` | 核心数据存储与调度管理(自动保存、版本、缓存) |
+| `DataStorage` | 泛型数据封装,提供属性式访问与变更通知 |
+| `DataKeyDic` / `DataKeyBase` | 注册键名与云同步标记支持 |
+| `ES3` | 第三方 Easy Save 工具(需另行导入) |
+
+
+
+------
+
+## 📝 配置项
+
+| 名称 | 默认值 | 说明 |
+| ------------------------- | ------ | -------------------- |
+| `InitialAutoSaveInterval` | `15s` | 自动保存时间间隔 |
+| `SaveThreshold` | `20次` | 自动保存调用次数阈值 |
+| `DataVersion` | `1` | 数据版本号,内部递增 |
+
+
+
+------
+
+## 🔍 调试建议
+
+- 使用 `DebugAllKeys()` 打印所有持久化键值
+- 使用 `DebugCache()` 打印当前缓存数据
+- 检查 `Log.Info/Error` 输出(默认已集成日志标记)
+
+------
+
+## 📦 依赖项
+
+- **Easy Save 3**:第三方持久化框架
+- **Newtonsoft.Json**:JSON 序列化与反序列化
+- **自定义框架组件**(如 `SingletonMonoBehaviour`、`Log`、`CommonUtils`、`GMTool` 等)
+
+------
+
+## 📌 注意事项
+
+- 云同步仅同步标记为 `CloudSave = true` 的键
+- `DataStorage` 会自动触发注册,但手动操作建议提前注册
+- 非线程安全,不建议多线程并发调用
+- 建议在游戏入口或登录成功后初始化模块并导入云数据
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/README.md.meta b/Assets/SGModule/DataStorage/README.md.meta
new file mode 100644
index 0000000..d0199a4
--- /dev/null
+++ b/Assets/SGModule/DataStorage/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: ce8e2605318941745b94c3ef79611bf6
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule.meta b/Assets/SGModule/DataStorage/SGModule.meta
new file mode 100644
index 0000000..cfaed58
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 030532982443d94449af00fc7ebcaf95
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins.meta b/Assets/SGModule/DataStorage/SGModule/Plugins.meta
new file mode 100644
index 0000000..dc423ac
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a855501e0627ebc49add798f2f023815
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3.meta
new file mode 100644
index 0000000..58db944
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8174a0d08146bad4dad3838c423e1d5a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor.meta
new file mode 100644
index 0000000..9e30c2e
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1a8ecc2f6a355324ab2d92ace768db6b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs
new file mode 100644
index 0000000..9277e27
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs
@@ -0,0 +1,88 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using ES3Internal;
+using System.Linq;
+using UnityEngine.SceneManagement;
+
+namespace ES3Editor
+{
+ public class AddES3Prefab : Editor
+ {
+ [MenuItem("GameObject/Easy Save 3/Enable Easy Save for Prefab(s)", false, 1001)]
+ [MenuItem("Assets/Easy Save 3/Enable Easy Save for Prefab(s)", false, 1001)]
+ public static void Enable()
+ {
+ if (Selection.gameObjects == null || Selection.gameObjects.Length == 0)
+ return;
+
+ foreach (var obj in Selection.gameObjects)
+ {
+ // Don't add the Component to a GameObject which already has it.
+ if (obj == null || (obj.GetComponent() != null))
+ continue;
+
+ var go = obj;
+
+ #if UNITY_2018_3_OR_NEWER
+ if (PrefabUtility.GetPrefabInstanceStatus(go) != PrefabInstanceStatus.NotAPrefab)
+ {
+ go = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(go);
+ if (go == null)
+ continue;
+ }
+ #else
+ if(PrefabUtility.GetPrefabType(go) != PrefabType.Prefab)
+ {
+ go = (GameObject)PrefabUtility.GetPrefabParent(go);
+ if(go == null)
+ continue;
+ }
+ #endif
+
+ var es3Prefab = Undo.AddComponent(go);
+ es3Prefab.GeneratePrefabReferences();
+
+ var mgr = ES3ReferenceMgr.GetManagerFromScene(SceneManager.GetActiveScene());
+ if (mgr != null)
+ {
+ mgr.AddPrefab(es3Prefab);
+ EditorUtility.SetDirty(mgr);
+ }
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Enable Easy Save for Prefab(s)", true, 1001)]
+ [MenuItem("Assets/Easy Save 3/Enable Easy Save for Prefab(s)", true, 1001)]
+ public static bool Validate()
+ {
+ return Selection.gameObjects != null && Selection.gameObjects.Length > 0;
+ }
+ }
+
+ public class RemoveES3Prefab : Editor
+ {
+ [MenuItem("GameObject/Easy Save 3/Disable Easy Save for Prefab(s)", false, 1001)]
+ [MenuItem("Assets/Easy Save 3/Disable Easy Save for Prefab(s)", false, 1001)]
+ public static void Enable()
+ {
+ if (Selection.gameObjects == null || Selection.gameObjects.Length == 0)
+ return;
+
+ foreach (var obj in Selection.gameObjects)
+ {
+ var es3prefab = obj.GetComponent();
+ if (es3prefab != null)
+ Undo.DestroyObjectImmediate(es3prefab);
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Disable Easy Save for Prefab(s)", true, 1001)]
+ [MenuItem("Assets/Easy Save 3/Disable Easy Save for Prefab(s)", true, 1001)]
+ public static bool Validate()
+ {
+ return Selection.gameObjects != null && Selection.gameObjects.Length > 0;
+ }
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs.meta
new file mode 100644
index 0000000..745029b
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AddES3Prefab.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 337c3be705d1942b3bf318b5b29aa7cb
+timeCreated: 1519132282
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs
new file mode 100644
index 0000000..ffb2ff3
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs
@@ -0,0 +1,369 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using ES3Internal;
+using UnityEngine.SceneManagement;
+using UnityEditor.SceneManagement;
+
+namespace ES3Editor
+{
+ [System.Serializable]
+ public class AutoSaveWindow : SubWindow
+ {
+ public bool showAdvancedSettings = false;
+
+ public ES3AutoSaveMgr mgr = null;
+
+ private HierarchyItem[] hierarchy = null;
+ public HierarchyItem selected = null;
+
+ private Vector2 hierarchyScrollPosition = Vector2.zero;
+
+ private bool sceneOpen = true;
+
+ private string searchTerm = "";
+
+ public AutoSaveWindow(EditorWindow window) : base("Auto Save", window)
+ {
+ EditorSceneManager.activeSceneChangedInEditMode += ChangedActiveScene;
+ }
+
+ private void ChangedActiveScene(Scene current, Scene next)
+ {
+ mgr = null;
+ Init();
+ }
+
+ public override void OnGUI()
+ {
+ Init();
+
+ if(mgr == null)
+ {
+ EditorGUILayout.Space();
+ if (GUILayout.Button("Enable Auto Save for this scene"))
+ mgr = ES3Postprocessor.AddManagerToScene().GetComponent();
+ else
+ return;
+ }
+
+ var style = EditorStyle.Get;
+
+ using (var changeCheck = new EditorGUI.ChangeCheckScope())
+ {
+ using (var vertical = new EditorGUILayout.VerticalScope(style.areaPadded))
+ {
+ //GUILayout.Label("Settings for current scene", style.heading);
+ mgr.saveEvent = (ES3AutoSaveMgr.SaveEvent)EditorGUILayout.EnumPopup("Save Event", mgr.saveEvent);
+ mgr.loadEvent = (ES3AutoSaveMgr.LoadEvent)EditorGUILayout.EnumPopup("Load Event", mgr.loadEvent);
+
+ EditorGUILayout.Space();
+
+ showAdvancedSettings = EditorGUILayout.Foldout(showAdvancedSettings, "Show Advanced Settings");
+ if (showAdvancedSettings)
+ {
+ EditorGUI.indentLevel++;
+ mgr.key = EditorGUILayout.TextField("Key", mgr.key);
+ ES3SettingsEditor.Draw(mgr.settings);
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ // Display the menu.
+ using (var horizontal = new EditorGUILayout.HorizontalScope())
+ {
+ if (GUILayout.Button("Scene", sceneOpen ? style.menuButtonSelected : style.menuButton))
+ {
+ sceneOpen = true;
+ OnFocus();
+ }
+ if (GUILayout.Button("Prefabs", sceneOpen ? style.menuButton : style.menuButtonSelected))
+ {
+ sceneOpen = false;
+ OnFocus();
+ }
+ }
+
+ //EditorGUILayout.HelpBox("Select the Components you want to be saved.\nTo maximise performance, only select the Components with variables which need persisting.", MessageType.None, true);
+
+ if (hierarchy == null || hierarchy.Length == 0)
+ {
+ EditorGUILayout.LabelField("Right-click a prefab and select 'Easy Save 3 > Enable Easy Save for Scene' to enable Auto Save for it.\n\nYour scene will also need to reference this prefab for it to be recognised.", style.area);
+ return;
+ }
+
+ using (var scrollView = new EditorGUILayout.ScrollViewScope(hierarchyScrollPosition, style.areaPadded))
+ {
+ hierarchyScrollPosition = scrollView.scrollPosition;
+
+ using (new EditorGUILayout.HorizontalScope(GUILayout.Width(200)))
+ {
+ var searchTextFieldSkin = GUI.skin.FindStyle("ToolbarSearchTextField");
+ if (searchTextFieldSkin == null)
+ searchTextFieldSkin = GUI.skin.FindStyle("ToolbarSeachTextField");
+
+ var searchButtonSkin = GUI.skin.FindStyle("ToolbarSearchCancelButton");
+ if (searchButtonSkin == null)
+ searchButtonSkin = GUI.skin.FindStyle("ToolbarSeachCancelButton");
+
+ searchTerm = GUILayout.TextField(searchTerm, searchTextFieldSkin);
+ if (GUILayout.Button("", searchButtonSkin))
+ {
+ // Remove focus if cleared
+ searchTerm = "";
+ GUI.FocusControl(null);
+ }
+ }
+
+ EditorGUILayout.Space();
+ EditorGUILayout.Space();
+
+ foreach (var go in hierarchy)
+ if (go != null)
+ go.DrawHierarchy(searchTerm.ToLowerInvariant());
+ }
+ if (changeCheck.changed)
+ EditorUtility.SetDirty(mgr);
+ }
+ }
+
+ public void Init()
+ {
+ if (mgr == null)
+ foreach (var thisMgr in Resources.FindObjectsOfTypeAll())
+ if (thisMgr != null && thisMgr.gameObject.scene == SceneManager.GetActiveScene())
+ mgr = thisMgr;
+
+ if (hierarchy == null)
+ OnFocus();
+ }
+
+ public override void OnFocus()
+ {
+
+ GameObject[] parentObjects;
+ if (sceneOpen)
+ parentObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
+ else // Prefabs
+ {
+ var mgr = ES3ReferenceMgr.GetManagerFromScene(SceneManager.GetActiveScene(), false);
+ var prefabs = mgr.prefabs;
+ parentObjects = new GameObject[prefabs.Count];
+ for (int i = 0; i < prefabs.Count; i++)
+ if(prefabs[i] != null)
+ parentObjects[i] = prefabs[i].gameObject;
+ }
+ hierarchy = new HierarchyItem[parentObjects.Length];
+ for (int i = 0; i < parentObjects.Length; i++)
+ if(parentObjects[i] != null)
+ hierarchy[i] = new HierarchyItem(parentObjects[i].transform, null, this);
+ }
+
+ public class HierarchyItem
+ {
+ private ES3AutoSave autoSave;
+ private Transform t;
+ private Component[] components = null;
+ // Immediate children of this GameObject
+ private HierarchyItem[] children = new HierarchyItem[0];
+ private bool showComponents = false;
+ //private AutoSaveWindow window;
+
+ public HierarchyItem(Transform t, HierarchyItem parent, AutoSaveWindow window)
+ {
+ this.autoSave = t.GetComponent();
+ this.t = t;
+ this.components = t.GetComponents();
+
+ children = new HierarchyItem[t.childCount];
+ for (int i = 0; i < t.childCount; i++)
+ children[i] = new HierarchyItem(t.GetChild(i), this, window);
+
+ //this.window = window;
+ }
+
+ public void MergeDown(ES3AutoSave autoSave)
+ {
+ if (this.autoSave != autoSave)
+ {
+ if (this.autoSave != null)
+ {
+ autoSave.componentsToSave.AddRange(autoSave.componentsToSave);
+ Object.DestroyImmediate(this.autoSave);
+ }
+ this.autoSave = autoSave;
+ }
+
+ foreach (var child in children)
+ MergeDown(autoSave);
+ }
+
+ public void DrawHierarchy(string searchTerm)
+ {
+ bool containsSearchTerm = false;
+
+ if (t != null)
+ {
+ // Filter by tag if it's prefixed by "tag:"
+ if (searchTerm.StartsWith("tag:") && t.tag.ToLowerInvariant().Contains(searchTerm.Remove(0,4)))
+ containsSearchTerm = true;
+ // Else filter by name
+ else
+ containsSearchTerm = t.name.ToLowerInvariant().Contains(searchTerm);
+
+ if (containsSearchTerm)
+ {
+ GUIContent saveIcon;
+ EditorGUIUtility.SetIconSize(new Vector2(16, 16));
+
+ if (HasSelectedComponentsOrFields())
+ saveIcon = new GUIContent(t.name, EditorStyle.Get.saveIconSelected, "There are Components on this GameObject which will be saved.");
+ else
+ saveIcon = new GUIContent(t.name, EditorStyle.Get.saveIconUnselected, "No Components on this GameObject will be saved");
+
+ GUIStyle style = GUI.skin.GetStyle("Foldout");
+ if (Selection.activeTransform == t)
+ {
+ style = new GUIStyle(style);
+ style.fontStyle = FontStyle.Bold;
+ }
+
+ var open = EditorGUILayout.Foldout(showComponents, saveIcon, style);
+ if (open)
+ {
+ // Ping the GameObject if this was previously closed
+ if (showComponents != open)
+ EditorGUIUtility.PingObject(t.gameObject);
+ DrawComponents();
+ }
+ showComponents = open;
+
+ EditorGUI.indentLevel += 1;
+ }
+ }
+
+ // Draw children
+ if (children != null)
+ foreach (var child in children)
+ if (child != null)
+ child.DrawHierarchy(searchTerm);
+
+ if (containsSearchTerm)
+ EditorGUI.indentLevel -= 1;
+ }
+
+ public void DrawComponents()
+ {
+ EditorGUI.indentLevel += 3;
+ using (var scope = new EditorGUILayout.VerticalScope())
+ {
+ bool toggle;
+ toggle = EditorGUILayout.ToggleLeft("active", autoSave != null ? autoSave.saveActive : false);
+ if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent() : autoSave) != null)
+ ApplyBool("saveActive", toggle);
+
+ toggle = EditorGUILayout.ToggleLeft("hideFlags", autoSave != null ? autoSave.saveHideFlags : false);
+ if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent() : autoSave) != null)
+ ApplyBool("saveHideFlags", toggle);
+
+ toggle = EditorGUILayout.ToggleLeft("layer", autoSave != null ? autoSave.saveLayer : false);
+ if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent() : autoSave) != null)
+ ApplyBool("saveLayer", toggle);
+
+ toggle = EditorGUILayout.ToggleLeft("name", autoSave != null ? autoSave.saveName : false);
+ if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent() : autoSave) != null)
+ ApplyBool("saveName", toggle);
+
+ toggle = EditorGUILayout.ToggleLeft("tag", autoSave != null ? autoSave.saveTag : false);
+ if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent() : autoSave) != null)
+ ApplyBool("saveTag", toggle);
+
+ foreach (var component in components)
+ {
+ if (component == null)
+ continue;
+
+ using (var horizontalScope = new EditorGUILayout.HorizontalScope())
+ {
+ bool saveComponent = false;
+ if (autoSave != null)
+ saveComponent = autoSave.componentsToSave.Contains(component);
+
+ var newValue = EditorGUILayout.ToggleLeft(EditorGUIUtility.ObjectContent(component, component.GetType()), saveComponent);
+ // If the checkbox has changed, we want to save or not save a Component
+ if (newValue != saveComponent)
+ {
+ if (autoSave == null)
+ {
+ autoSave = Undo.AddComponent(t.gameObject);
+ var so = new SerializedObject(autoSave);
+ so.FindProperty("saveChildren").boolValue = false;
+ so.ApplyModifiedProperties();
+ }
+ // If we've unchecked the box, remove the Component from the array.
+ if (newValue == false)
+ {
+ var so = new SerializedObject(autoSave);
+ var prop = so.FindProperty("componentsToSave");
+ var index = autoSave.componentsToSave.IndexOf(component);
+ prop.DeleteArrayElementAtIndex(index);
+ so.ApplyModifiedProperties();
+ }
+ // Else, add it to the array.
+ else
+ {
+ var so = new SerializedObject(autoSave);
+ var prop = so.FindProperty("componentsToSave");
+ prop.arraySize++;
+ prop.GetArrayElementAtIndex(prop.arraySize - 1).objectReferenceValue = component;
+ so.ApplyModifiedProperties();
+ }
+ }
+ if (GUILayout.Button(EditorGUIUtility.IconContent("_Popup"), new GUIStyle("Label")))
+ ES3Window.InitAndShowTypes(component.GetType());
+ }
+ }
+ }
+
+ /*if(autoSave != null && isDirty)
+ {
+ EditorUtility.SetDirty(autoSave);
+ if (PrefabUtility.IsPartOfPrefabInstance(autoSave))
+ PrefabUtility.RecordPrefabInstancePropertyModifications(autoSave.gameObject);
+ }*/
+
+ if (autoSave != null && (autoSave.componentsToSave == null || autoSave.componentsToSave.Count == 0) && !autoSave.saveActive && !autoSave.saveChildren && !autoSave.saveHideFlags && !autoSave.saveLayer && !autoSave.saveName && !autoSave.saveTag)
+ {
+ Undo.DestroyObjectImmediate(autoSave);
+ autoSave = null;
+ }
+ EditorGUI.indentLevel -= 3;
+ }
+
+ public void ApplyBool(string propertyName, bool value)
+ {
+ var so = new SerializedObject(autoSave);
+ so.FindProperty(propertyName).boolValue = value;
+ so.ApplyModifiedProperties();
+ }
+
+ public bool HasSelectedComponentsOrFields()
+ {
+ if (autoSave == null)
+ return false;
+
+
+ foreach (var component in components)
+ if (component != null && autoSave.componentsToSave.Contains(component))
+ return true;
+
+ if (autoSave.saveActive || autoSave.saveHideFlags || autoSave.saveLayer || autoSave.saveName || autoSave.saveTag)
+ return true;
+
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs.meta
new file mode 100644
index 0000000..9958209
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/AutoSaveWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6065cc5492e9f49728674de9a0c1fe84
+timeCreated: 1519132286
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs
new file mode 100644
index 0000000..534010e
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs
@@ -0,0 +1,93 @@
+using UnityEngine;
+using UnityEditor;
+using UnityEngine.SceneManagement;
+
+namespace ES3Internal
+{
+ public class SetReferenceID : EditorWindow
+ {
+ private long id = 0;
+ public UnityEngine.Object obj;
+
+ [MenuItem("GameObject/Easy Save 3/Set Reference ID..", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Set Reference ID..", false, 33)]
+
+ public static void ShowWindow()
+ {
+ var selected = Selection.GetFiltered(SelectionMode.TopLevel);
+
+ if (selected == null || selected.Length == 0)
+ EditorUtility.DisplayDialog("Could not set reference ID", "No reference was selected to set the ID of.", "Ok");
+ else if (selected.Length > 1)
+ EditorUtility.DisplayDialog("Could not set reference ID", "Multiple references are selected. Please select a single reference.", "Ok");
+ else
+ EditorWindow.GetWindow("Set Reference ID").obj = selected[0];
+ }
+
+ [MenuItem("CONTEXT/Component/Easy Save 3/Set Reference ID..", false, 33)]
+ public static void ShowWindowContext(MenuCommand command)
+ {
+ EditorWindow.GetWindow("Set Reference ID").obj = command.context;
+ }
+
+ private void OnGUI()
+ {
+ GUILayout.Label("Enter new reference ID:", EditorStyles.boldLabel);
+ id = EditorGUILayout.LongField("Reference ID", id);
+
+ if (GUILayout.Button("Apply"))
+ {
+ int setCount = 0;
+
+ string sceneName = null;
+
+ // If this is a scene object, only set the reference ID for the manager in the scene it belongs to.
+ if (!EditorUtility.IsPersistent(obj))
+ {
+ if (obj is GameObject go)
+ sceneName = go.scene.name;
+ else if (obj is Component c)
+ sceneName = c.gameObject.scene.name;
+ }
+
+ for (int i = 0; i < SceneManager.sceneCount; i++)
+ {
+ var loadedScene = SceneManager.GetSceneAt(i);
+
+ if (loadedScene != null && loadedScene.IsValid())
+ {
+ if (sceneName != null && loadedScene.name != sceneName)
+ continue;
+
+ var mgr = ES3ReferenceMgr.GetManagerFromScene(loadedScene, false);
+ if (mgr != null)
+ {
+ Undo.RecordObject(mgr, "Changed reference ID in manager");
+ mgr.Remove(obj);
+ mgr.Add(obj, id);
+ setCount++;
+ }
+ }
+ }
+
+ if (setCount == 0)
+ {
+ this.Close();
+ EditorUtility.DisplayDialog("Could not set reference ID", "No open scenes contain reference managers. Add a reference manager by going to Tools > Easy Save 3 > Add Manager to Scene.", "Ok");
+ }
+
+ this.Close();
+ EditorUtility.DisplayDialog($"Reference ID successfully changed", $"Reference ID changed to {id} in {setCount} managers.", "Ok");
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Set Reference ID..", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Set Reference ID..", true, 33)]
+ private static bool CanSetReference()
+ {
+ var selected = Selection.GetFiltered(SelectionMode.TopLevel);
+
+ return selected != null && selected.Length == 1 && ES3ReferenceMgr.Current != null;
+ }
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs.meta
new file mode 100644
index 0000000..ca83970
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ChangeReferenceID.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3c119866c01ca0044a7e5e08b8d22692
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs
new file mode 100644
index 0000000..a6786f4
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs
@@ -0,0 +1,21 @@
+using UnityEditor;
+using UnityEngine;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ES3Internal
+{
+ [CustomEditor(typeof(ES3AutoSave))]
+ public class ES3AutoSaveEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ if (target == null)
+ return;
+
+ if (GUILayout.Button("Manage Auto Save Settings"))
+ ES3Editor.ES3Window.InitAndShowAutoSave();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs.meta
new file mode 100644
index 0000000..6b4bf60
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 54ded3aeb20a94008a877da330bfc45f
+timeCreated: 1519132285
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs
new file mode 100644
index 0000000..854e218
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs
@@ -0,0 +1,20 @@
+using UnityEditor;
+using UnityEngine;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ES3Internal
+{
+ [CustomEditor(typeof(ES3AutoSaveMgr))]
+ public class ES3AutoSaveMgrEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ EditorGUILayout.HelpBox("This manages the saving and loading of GameObjects which have the Auto Save component attached to them.\n\nIf there are no Auto Save components in your scene, this component will do nothing.", MessageType.Info);
+ if(GUILayout.Button("Settings..."))
+ ES3Editor.ES3Window.InitAndShowAutoSave();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs.meta
new file mode 100644
index 0000000..8983ad6
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3AutoSaveMgrEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f440317f3fd444daf83c27a3381af17c
+timeCreated: 1519132300
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs
new file mode 100644
index 0000000..fa5e9b4
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs
@@ -0,0 +1,84 @@
+using System.Collections;
+using UnityEngine;
+using UnityEditor;
+
+namespace ES3Editor
+{
+ public class EditorStyle
+ {
+ private static EditorStyle style = null;
+
+ public GUIStyle area;
+ public GUIStyle areaPadded;
+
+ public GUIStyle menuButton;
+ public GUIStyle menuButtonSelected;
+ public GUIStyle smallSquareButton;
+
+ public GUIStyle heading;
+ public GUIStyle subheading;
+ public GUIStyle subheading2;
+
+ public GUIStyle boldLabelNoStretch;
+
+ public GUIStyle link;
+
+ public GUIStyle toggle;
+
+ public Texture2D saveIconSelected;
+ public Texture2D saveIconUnselected;
+
+ public static EditorStyle Get { get{ if(style == null) style = new EditorStyle(); return style; } }
+
+ public EditorStyle()
+ {
+ // An area with padding.
+ area = new GUIStyle();
+ area.padding = new RectOffset(10, 10, 10, 10);
+ area.wordWrap = true;
+
+ // An area with more padding.
+ areaPadded = new GUIStyle();
+ areaPadded.padding = new RectOffset(20, 20, 20, 20);
+ areaPadded.wordWrap = true;
+
+ // Unselected menu button.
+ menuButton = new GUIStyle(EditorStyles.toolbarButton);
+ menuButton.fontStyle = FontStyle.Normal;
+ menuButton.fontSize = 14;
+ menuButton.fixedHeight = 24;
+
+ // Selected menu button.
+ menuButtonSelected = new GUIStyle(menuButton);
+ menuButtonSelected.fontStyle = FontStyle.Bold;
+
+ // Main Headings
+ heading = new GUIStyle(EditorStyles.label);
+ heading.fontStyle = FontStyle.Bold;
+ heading.fontSize = 24;
+
+ subheading = new GUIStyle(heading);
+ subheading.fontSize = 18;
+
+ subheading2 = new GUIStyle(heading);
+ subheading2.fontSize = 14;
+
+ boldLabelNoStretch = new GUIStyle(EditorStyles.label);
+ boldLabelNoStretch.stretchWidth = false;
+ boldLabelNoStretch.fontStyle = FontStyle.Bold;
+
+ link = new GUIStyle();
+ link.fontSize = 16;
+ if(EditorGUIUtility.isProSkin)
+ link.normal.textColor = new Color (0.262f, 0.670f, 0.788f);
+ else
+ link.normal.textColor = new Color (0.129f, 0.129f, 0.8f);
+
+ toggle = new GUIStyle(EditorStyles.toggle);
+ toggle.stretchWidth = false;
+
+ saveIconSelected = AssetDatabase.LoadAssetAtPath(ES3Settings.PathToEasySaveFolder() + "Editor/es3Logo16x16.png");
+ saveIconUnselected = AssetDatabase.LoadAssetAtPath(ES3Settings.PathToEasySaveFolder() + "Editor/es3Logo16x16-bw.png");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs.meta
new file mode 100644
index 0000000..62aeda3
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorStyle.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f556addc6753344019137cbc45d2c4ff
+timeCreated: 1519132301
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs
new file mode 100644
index 0000000..126d436
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs
@@ -0,0 +1,60 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using System.IO;
+using System.Linq;
+using ES3Internal;
+
+public class ES3EditorUtility : Editor
+{
+ public static void DisplayLink(string label, string url)
+ {
+ var style = ES3Editor.EditorStyle.Get;
+ if(GUILayout.Button(label, style.link))
+ Application.OpenURL(url);
+
+ var buttonRect = GUILayoutUtility.GetLastRect();
+ buttonRect.width = style.link.CalcSize(new GUIContent(label)).x;
+
+ EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
+ }
+
+ public static bool IsPrefabInAssets(UnityEngine.Object obj)
+ {
+ #if UNITY_2018_3_OR_NEWER
+ return PrefabUtility.IsPartOfPrefabAsset(obj);
+ #else
+ return (PrefabUtility.GetPrefabType(obj) == PrefabType.Prefab);
+ #endif
+ }
+
+ /*
+ * Gets all children and components from a GameObject or GameObjects.
+ * We create our own method for this because EditorUtility.CollectDeepHierarchy isn't thread safe in the Editor.
+ */
+ public static IEnumerable CollectDeepHierarchy(IEnumerable gos)
+ {
+ var deepHierarchy = new HashSet();
+ foreach (var go in gos)
+ {
+ deepHierarchy.Add(go);
+ deepHierarchy.UnionWith(go.GetComponents());
+ foreach (Transform t in go.transform)
+ deepHierarchy.UnionWith( CollectDeepHierarchy( new GameObject[] { t.gameObject } ) );
+ }
+ return deepHierarchy;
+ }
+
+ [MenuItem("Tools/Easy Save 3/Getting Started...", false, 0)]
+ public static void DisplayGettingStarted()
+ {
+ Application.OpenURL("https://docs.moodkie.com/easy-save-3/getting-started/");
+ }
+
+ [MenuItem("Tools/Easy Save 3/Manual...", false, 0)]
+ public static void DisplayManual()
+ {
+ Application.OpenURL("https://docs.moodkie.com/product/easy-save-3/");
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs.meta
new file mode 100644
index 0000000..f0d8af7
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3EditorUtility.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 501719249e8124990973182985feaeb8
+timeCreated: 1519132285
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs
new file mode 100644
index 0000000..08dc8b0
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs
@@ -0,0 +1,46 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace ES3Internal
+{
+ [CustomEditor(typeof(ES3GameObject))]
+ public class ES3GameObjectEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ if (target == null)
+ return;
+
+ var es3Go = (ES3GameObject)target;
+
+ EditorGUILayout.HelpBox("This Component allows you to choose which Components are saved when this GameObject is saved using code.", MessageType.Info);
+
+ if (es3Go.GetComponent() != null)
+ {
+ EditorGUILayout.HelpBox("This Component cannot be used on GameObjects which are already managed by Auto Save.", MessageType.Error);
+ return;
+ }
+
+ foreach (var component in es3Go.GetComponents())
+ {
+ var markedToBeSaved = es3Go.components.Contains(component);
+ var newMarkedToBeSaved = EditorGUILayout.Toggle(component.GetType().Name, markedToBeSaved);
+
+ if(markedToBeSaved && !newMarkedToBeSaved)
+ {
+ Undo.RecordObject(es3Go, "Marked Component to save");
+ es3Go.components.Remove(component);
+ }
+
+ if (!markedToBeSaved && newMarkedToBeSaved)
+ {
+ Undo.RecordObject(es3Go, "Unmarked Component to save");
+ es3Go.components.Add(component);
+ }
+ }
+
+ if (es3Go.components.RemoveAll(t => t == null) > 0)
+ Undo.RecordObject(es3Go, "Removed null Component from ES3GameObject");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs.meta
new file mode 100644
index 0000000..6fe8ba3
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GameObjectEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b7d54ef20554e354eb3c0d40d2a6debe
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs
new file mode 100644
index 0000000..d11c5c6
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs
@@ -0,0 +1,91 @@
+#if !ES3GLOBAL_DISABLED
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ES3Internal
+{
+ [CustomEditor(typeof(ES3Internal.ES3GlobalReferences))]
+ [System.Serializable]
+ public class ES3GlobalReferencesEditor : Editor
+ {
+ private bool isDraggingOver = false;
+ private bool openReferences = false;
+
+ private ES3Internal.ES3GlobalReferences _globalRefs = null;
+ private ES3Internal.ES3GlobalReferences globalRefs
+ {
+ get
+ {
+ if (_globalRefs == null)
+ _globalRefs = (ES3Internal.ES3GlobalReferences)serializedObject.targetObject;
+ return _globalRefs;
+ }
+ }
+
+ public override void OnInspectorGUI()
+ {
+ EditorGUILayout.HelpBox("This stores references to objects in Assets, allowing them to be referenced with the same ID between scenes.", MessageType.Info);
+
+ if (EditorGUILayout.Foldout(openReferences, "References") != openReferences)
+ {
+ openReferences = !openReferences;
+ if (openReferences == true)
+ openReferences = EditorUtility.DisplayDialog("Are you sure?", "Opening this list will display every reference in the manager, which for larger projects can cause the Editor to freeze\n\nIt is strongly recommended that you save your project before continuing.", "Open References", "Cancel");
+ }
+
+ // Make foldout drag-and-drop enabled for objects.
+ if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
+ {
+ Event evt = Event.current;
+
+ switch (evt.type)
+ {
+ case EventType.DragUpdated:
+ case EventType.DragPerform:
+ isDraggingOver = true;
+ break;
+ case EventType.DragExited:
+ isDraggingOver = false;
+ break;
+ }
+
+ if (isDraggingOver)
+ {
+ DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
+
+ if (evt.type == EventType.DragPerform)
+ {
+ DragAndDrop.AcceptDrag();
+ Undo.RecordObject(globalRefs, "Add References to Easy Save 3 Reference List");
+ foreach (UnityEngine.Object obj in DragAndDrop.objectReferences)
+ globalRefs.GetOrAdd(obj);
+ // Return now because otherwise we'll change the GUI during an event which doesn't allow it.
+ return;
+ }
+ }
+ }
+
+ if (openReferences)
+ {
+ EditorGUI.indentLevel++;
+
+ foreach (var kvp in globalRefs.refId)
+ {
+ EditorGUILayout.BeginHorizontal();
+
+ EditorGUILayout.ObjectField(kvp.Key, typeof(UnityEngine.Object), true);
+ EditorGUILayout.LongField(kvp.Value);
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ EditorGUI.indentLevel--;
+ }
+ }
+ }
+}
+#endif
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs.meta
new file mode 100644
index 0000000..0203979
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3GlobalReferencesEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 286fb0c3863779e4d96bc682edb324ce
+timeCreated: 1519132283
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs
new file mode 100644
index 0000000..efea1d9
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs
@@ -0,0 +1,14 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using System;
+using System.Collections;
+
+[CustomEditor(typeof(ES3InspectorInfo))]
+public class ES3InspectorInfoEditor : Editor
+{
+ public override void OnInspectorGUI()
+ {
+ EditorGUILayout.HelpBox(((ES3InspectorInfo)target).message, MessageType.Info);
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs.meta
new file mode 100644
index 0000000..2bb545f
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3InspectorInfoEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b344d685b614044aebf5285c5f59f52d
+timeCreated: 1519132294
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs
new file mode 100644
index 0000000..f69c850
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs
@@ -0,0 +1,803 @@
+#if PLAYMAKER_1_8_OR_NEWER
+
+using UnityEngine;
+using UnityEditor;
+using HutongGames.PlayMaker;
+using HutongGames.PlayMaker.Actions;
+using HutongGames.PlayMakerEditor;
+using System.Text.RegularExpressions;
+
+namespace ES3PlayMaker
+{
+ #region Base Actions
+
+ public abstract class BaseEditor : CustomActionEditor
+ {
+ bool showErrorHandling = false;
+
+ public abstract void DrawGUI();
+
+ public override bool OnGUI()
+ {
+ DrawGUI();
+
+ EditorGUILayout.Separator();
+
+ showErrorHandling = EditorGUILayout.Foldout(showErrorHandling, "Error Handling");
+ if (showErrorHandling)
+ {
+ EditorGUI.indentLevel++;
+ EditField("errorEvent");
+ EditField("errorMessage");
+ EditorGUI.indentLevel--;
+ }
+
+ return GUI.changed;
+ }
+
+ // Displays the FsmVar field without the unnecessary Type field.
+ protected void FsmVarField(string fieldName)
+ {
+ if (target == null || target.State == null)
+ return;
+
+ var fsmVar = (FsmVar)ES3Internal.ES3Reflection.GetField(target.GetType(), fieldName).GetValue(target);
+
+ if (fsmVar == null)
+ {
+ fsmVar = new FsmVar();
+ ES3Internal.ES3Reflection.GetField(target.GetType(), fieldName).SetValue(target, fsmVar);
+ }
+
+ EditorGUILayout.BeginHorizontal();
+ var label = Regex.Replace(fieldName, @"\p{Lu}", m => " " + m.Value.ToLowerInvariant());
+ EditorGUILayout.PrefixLabel(char.ToUpperInvariant(label[0]) + label.Substring(1));
+
+ var localVariables = target.Fsm.Variables.GetAllNamedVariablesSorted();
+ var globalVariables = FsmVariables.GlobalVariables.GetAllNamedVariablesSorted();
+
+ var variableNames = new string[localVariables.Length + globalVariables.Length];
+ int selected = -1;
+
+ for(int i=0; i= localVariables.Length ? globalVariables[i - localVariables.Length] : localVariables[i];
+ variableNames[i] = i >= localVariables.Length ? "Globals/"+variable.Name : variable.Name;
+ if (fsmVar.NamedVar == variable)
+ selected = i;
+ }
+
+ var newSelected = EditorGUILayout.Popup(selected, variableNames);
+
+
+ EditorGUILayout.EndHorizontal();
+
+ if (newSelected == -1)
+ return;
+
+ if (selected != newSelected)
+ {
+ if (newSelected >= localVariables.Length)
+ fsmVar.NamedVar = globalVariables[newSelected - localVariables.Length];
+ else
+ fsmVar.NamedVar = localVariables[newSelected];
+ }
+ }
+ }
+
+ public abstract class SettingsEditor : BaseEditor
+ {
+ public override bool OnGUI()
+ {
+ base.OnGUI();
+ return DrawSettingsEditor();
+ }
+
+ public bool DrawSettingsEditor()
+ {
+ var action = target as ES3PlayMaker.SettingsAction;
+ if (action == null)
+ return false;
+ action.overrideDefaultSettings.Value = EditorGUILayout.ToggleLeft("Override Default Settings", action.overrideDefaultSettings.Value);
+
+ if (action.overrideDefaultSettings.Value)
+ {
+ EditorGUI.indentLevel++;
+
+ EditField("path");
+ EditField("location");
+ EditField("encryptionType");
+ EditField("encryptionPassword");
+ EditField("compressionType");
+ EditField("directory");
+ EditField("format");
+ EditField("bufferSize");
+
+ EditorGUI.indentLevel--;
+ EditorGUILayout.Space();
+ }
+ return GUI.changed;
+ }
+ }
+
+ public abstract class KeyValueSettingsEditor : SettingsEditor
+ {
+ public override bool OnGUI()
+ {
+ EditField("key");
+ EditField("value");
+
+ base.OnGUI();
+
+ return GUI.changed;
+ }
+
+ public override void DrawGUI(){}
+ }
+
+ public abstract class ES3FileActionEditor : BaseEditor
+ {
+ public override bool OnGUI()
+ {
+ EditField("fsmES3File");
+
+ base.OnGUI();
+
+ var action = target as ES3PlayMaker.ES3FileAction;
+ if (action == null)
+ return false;
+
+ return GUI.changed;
+ }
+ }
+#endregion
+
+#if !PLAYMAKER_1_9_OR_NEWER
+#region Save Actions
+
+ /*[CustomActionEditor(typeof(ES3PlayMaker.Save))]
+ public class SaveEditor : KeyValueSettingsEditor{}*/
+
+ /*[CustomActionEditor(typeof(ES3PlayMaker.SaveMultiple))]
+ public class SaveMultipleEditor : SettingsEditor
+ {
+ public override bool OnGUI()
+ {
+ return base.OnGUI();
+ }
+
+ public override void DrawGUI()
+ {
+ DrawDefaultInspector();
+ }
+ }*/
+
+ [CustomActionEditor(typeof(ES3PlayMaker.SaveAll))]
+ public class SaveAllEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("key");
+ EditField("saveFsmVariables");
+ EditField("saveGlobalVariables");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.SaveRaw))]
+ public class SaveRawEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("str");
+ EditField("useBase64Encoding");
+ EditField("appendNewline");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.AppendRaw))]
+ public class AppendRawEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("str");
+ EditField("useBase64Encoding");
+ EditField("appendNewline");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.SaveImage))]
+ public class SaveImageEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("imagePath");
+ EditField("texture2D");
+ EditField("quality");
+ }
+ }
+
+#endregion
+
+#region Load Actions
+
+ [CustomActionEditor(typeof(ES3PlayMaker.Load))]
+ public class LoadEditor : KeyValueSettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditorGUILayout.Space();
+ EditField("defaultValue");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.LoadInto))]
+ public class LoadIntoEditor : KeyValueSettingsEditor{}
+
+ [CustomActionEditor(typeof(ES3PlayMaker.LoadAll))]
+ public class LoadAllEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("key");
+ EditField("loadFsmVariables");
+ EditField("loadGlobalVariables");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.LoadAudio))]
+ public class LoadAudioEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("audioFilePath");
+ EditField("audioClip");
+#if UNITY_2018_3_OR_NEWER
+ EditField("audioType");
+#endif
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.LoadImage))]
+ public class LoadImageEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("imagePath");
+ EditField("texture2D");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.LoadRawString))]
+ public class LoadRawStringEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("str");
+ EditField("useBase64Encoding");
+ }
+ }
+
+#endregion
+
+#region Exists Actions
+
+ [CustomActionEditor(typeof(ES3PlayMaker.KeyExists))]
+ public class KeyExistsEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("key");
+ EditField("exists");
+ EditorGUILayout.Separator();
+ EditField("existsEvent");
+ EditField("doesNotExistEvent");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.FileExists))]
+ public class FileExistsEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ EditField("exists");
+ EditorGUILayout.Separator();
+ EditField("existsEvent");
+ EditField("doesNotExistEvent");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.DirectoryExists))]
+ public class DirectoryExistsEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("directoryPath");
+ EditField("exists");
+ EditorGUILayout.Separator();
+ EditField("existsEvent");
+ EditField("doesNotExistEvent");
+ }
+ }
+
+#endregion
+
+#region Delete Actions
+
+ [CustomActionEditor(typeof(ES3PlayMaker.DeleteKey))]
+ public class DeleteKeyEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("key");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.DeleteFile))]
+ public class DeleteFileEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.DeleteDirectory))]
+ public class DeleteDirectoryEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("directoryPath");
+ }
+ }
+
+#endregion
+
+#region Backup Actions
+
+ [CustomActionEditor(typeof(ES3PlayMaker.CreateBackup))]
+ public class CreateBackupEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.RestoreBackup))]
+ public class RestoreBackupEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ EditField("backupWasRestored");
+ }
+ }
+
+#endregion
+
+#region Key, File and Directory methods
+
+ [CustomActionEditor(typeof(ES3PlayMaker.RenameFile))]
+ public class RenameFileEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("oldFilePath");
+ EditField("newFilePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.CopyFile))]
+ public class CopyFileEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("oldFilePath");
+ EditField("newFilePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.CopyDirectory))]
+ public class CopyDirectoryEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("oldDirectoryPath");
+ EditField("newDirectoryPath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.GetKeys))]
+ public class GetKeysEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ EditField("keys");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.GetKeyCount))]
+ public class GetKeyCountEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ EditField("keyCount");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.GetFiles))]
+ public class GetFilesEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("directoryPath");
+ EditField("files");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.GetDirectories))]
+ public class GetDirectoriesEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("directoryPath");
+ EditField("directories");
+ }
+ }
+
+#endregion
+
+#region ES3File Actions
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileCreate))]
+ public class ES3FileCreateEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ EditField("filePath");
+ EditField("syncWithFile");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileSync))]
+ public class ES3FileSyncEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ }
+ }
+
+ /*[CustomActionEditor(typeof(ES3PlayMaker.ES3FileSave))]
+ public class ES3FileSaveEditor : SaveEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ base.DrawGUI();
+ }
+ }*/
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileLoad))]
+ public class ES3FileLoadEditor : LoadEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ base.DrawGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileLoadInto))]
+ public class ES3FileLoadIntoEditor : LoadIntoEditor
+ {
+ public override void DrawGUI()
+ {
+ base.DrawGUI();
+ EditField("fsmES3File");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileDeleteKey))]
+ public class ES3FileDeleteKeyEditor : DeleteKeyEditor
+ {
+ public override void DrawGUI()
+ {
+ base.DrawGUI();
+ EditField("fsmES3File");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileKeyExists))]
+ public class ES3FileKeyExistsEditor : KeyExistsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ base.DrawGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileGetKeys))]
+ public class ES3FileGetKeysEditor : ES3FileActionEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("keys");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileClear))]
+ public class ES3FileClearEditor : BaseEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3FileSize))]
+ public class ES3FileSizeEditor : BaseEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("size");
+ EditField("fsmES3File");
+ }
+ }
+
+
+#endregion
+
+#region ES3Cloud Actions
+#if !DISABLE_WEB
+
+ public abstract class ES3CloudEditor : SettingsEditor
+ {
+ protected abstract void DrawChildGUI();
+
+ public override void DrawGUI()
+ {
+ EditField("url");
+ EditField("apiKey");
+ EditorGUILayout.Space();
+ DrawChildGUI();
+ EditorGUILayout.Space();
+ EditField("errorCode");
+ }
+ }
+
+ public abstract class ES3CloudUserEditor : ES3CloudEditor
+ {
+ public bool showUser = false;
+
+ protected override void DrawChildGUI()
+ {
+ if((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
+ {
+ EditorGUI.indentLevel++;
+ EditField("user");
+ EditField("password");
+ EditorGUI.indentLevel--;
+ }
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudSync))]
+ public class ES3CloudSyncEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadFile))]
+ public class ES3CloudDownloadFileEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadES3File))]
+ public class ES3CloudDownloadES3FileEditor : BaseEditor
+ {
+ public bool showUser = false;
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ EditField("url");
+ EditField("apiKey");
+ EditField("errorCode");
+ if ((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
+ {
+ EditorGUI.indentLevel++;
+ EditField("user");
+ EditField("password");
+ EditorGUI.indentLevel--;
+ }
+ }
+ }
+
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudUploadFile))]
+ public class ES3CloudUploadFileEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudUploadES3File))]
+ public class ES3CloudUploadES3FileEditor : BaseEditor
+ {
+ public bool showUser = false;
+ public override void DrawGUI()
+ {
+ EditField("fsmES3File");
+ EditField("url");
+ EditField("apiKey");
+ EditField("errorCode");
+ if((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
+ {
+ EditorGUI.indentLevel++;
+ EditField("user");
+ EditField("password");
+ EditorGUI.indentLevel--;
+ }
+ }
+ }
+
+
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDeleteFile))]
+ public class ES3CloudDeleteFileEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudRenameFile))]
+ public class ES3CloudRenameFileEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ EditField("newFilename");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadFilenames))]
+ public class ES3CloudDownloadFilenamesEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("filenames");
+ EditField("searchPattern");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudSearchFilenames))]
+ public class ES3CloudSearchFilenamesEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("filenames");
+ EditField("searchPattern");
+ base.DrawChildGUI();
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadTimestamp))]
+ public class ES3CloudDownloadTimestampEditor : ES3CloudUserEditor
+ {
+ protected override void DrawChildGUI()
+ {
+ EditField("path");
+ EditField("timestamp");
+ base.DrawChildGUI();
+ }
+ }
+
+#endif
+
+#endregion
+
+#region ES3SpreadsheetActions
+
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetCreate))]
+ public class ES3SpreadsheetCreateEditor : BaseEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3Spreadsheet");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetSetCell))]
+ public class ES3SpreadsheetSetCellEditor : BaseEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3Spreadsheet");
+ EditField("col");
+ EditField("row");
+ EditField("value");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetGetCell))]
+ public class ES3SpreadsheetGetCellEditor : BaseEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3Spreadsheet");
+ EditField("col");
+ EditField("row");
+ EditField("value");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetLoad))]
+ public class ES3SpreadsheetLoadEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3Spreadsheet");
+ EditField("filePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetSave))]
+ public class ES3SpreadsheetSaveEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("fsmES3Spreadsheet");
+ EditField("filePath");
+ EditField("append");
+ }
+ }
+
+#endregion
+
+#region Caching
+
+ [CustomActionEditor(typeof(ES3PlayMaker.CacheFile))]
+ public class CacheFileEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ }
+ }
+
+ [CustomActionEditor(typeof(ES3PlayMaker.StoreCachedFile))]
+ public class StoreCachedFileEditor : SettingsEditor
+ {
+ public override void DrawGUI()
+ {
+ EditField("filePath");
+ }
+ }
+
+#endregion
+#endif
+}
+#endif
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs.meta
new file mode 100644
index 0000000..4b91200
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PlayMakerEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 61838eb75b8164d699b0f54416e0f0bc
+timeCreated: 1497347459
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs
new file mode 100644
index 0000000..5788d48
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs
@@ -0,0 +1,269 @@
+using UnityEngine;
+using UnityEditor;
+using UnityEditor.Callbacks;
+using UnityEditor.SceneManagement;
+using UnityEngine.SceneManagement;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using ES3Internal;
+
+
+/*
+ * ---- How Postprocessing works for the reference manager ----
+ * - When the manager is first added to the scene, all top-level dependencies are added to the manager (AddManagerToScene).
+ * - When the manager is first added to the scene, all prefabs with ES3Prefab components are added to the manager (AddManagerToScene).
+ * - All GameObjects and Components in the scene are added to the reference manager when we enter Playmode or the scene is saved (PlayModeStateChanged, OnWillSaveAssets -> AddGameObjectsAndComponentstoManager).
+ * - When a UnityEngine.Object field of a Component is modified, the new UnityEngine.Object reference is added to the reference manager (PostProcessModifications)
+ * - All prefabs with ES3Prefab Components are added to the reference manager when we enter Playmode or the scene is saved (PlayModeStateChanged, OnWillSaveAssets -> AddGameObjectsAndComponentstoManager).
+ * - Local references for prefabs are processed whenever a prefab with an ES3Prefab Component is deselected (SelectionChanged -> ProcessGameObject)
+ */
+[InitializeOnLoad]
+public class ES3Postprocessor : UnityEditor.AssetModificationProcessor
+{
+ public static GameObject lastSelected = null;
+
+
+ // This constructor is also called once when playmode is activated and whenever recompilation happens
+ // because we have the [InitializeOnLoad] attribute assigned to the class.
+ static ES3Postprocessor()
+ {
+#if UNITY_2020_2_OR_NEWER
+ ObjectChangeEvents.changesPublished += Changed;
+#endif
+ ObjectFactory.componentWasAdded += ComponentWasAdded;
+
+ // Open the Easy Save 3 window the first time ES3 is installed.
+ //ES3Editor.ES3Window.OpenEditorWindowOnStart();
+
+ EditorApplication.playModeStateChanged -= PlayModeStateChanged;
+ EditorApplication.playModeStateChanged += PlayModeStateChanged;
+
+ EditorSceneManager.sceneOpened += OnSceneOpened;
+ }
+
+ #region Reference Updating
+
+ private static void PlayModeStateChanged(PlayModeStateChange state)
+ {
+ if (state == PlayModeStateChange.ExitingEditMode)
+ UpdateAssembliesContainingES3Types();
+ }
+
+ private static void OnSceneOpened(Scene scene, OpenSceneMode mode)
+ {
+ if (mode == OpenSceneMode.AdditiveWithoutLoading || Application.isPlaying)
+ return;
+
+ if (ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences && ES3Settings.defaultSettingsScriptableObject.updateReferencesWhenSceneIsOpened)
+ RefreshScene(scene);
+ }
+
+ private static void RefreshReferences(bool isEnteringPlayMode = false)
+ {
+ /*if (refreshed) // If we've already refreshed, do nothing.
+ return;*/
+
+ if (ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
+ for (int i = 0; i < SceneManager.sceneCount; i++)
+ RefreshScene(SceneManager.GetSceneAt(i));
+ //refreshed = true;
+ }
+
+ static void RefreshScene(Scene scene, bool isEnteringPlayMode = false)
+ {
+ if (scene != null && scene.isLoaded)
+ {
+ var mgr = (ES3ReferenceMgr)ES3ReferenceMgr.GetManagerFromScene(scene, false);
+ if (mgr != null)
+ mgr.RefreshDependencies(isEnteringPlayMode);
+ }
+ }
+
+ static void ComponentWasAdded(Component c)
+ {
+ var scene = c.gameObject.scene;
+
+ if (!scene.isLoaded)
+ return;
+
+ var mgr = (ES3ReferenceMgr)ES3ReferenceMgr.GetManagerFromScene(scene, false);
+
+ if (mgr != null && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences && ES3Settings.defaultSettingsScriptableObject.updateReferencesWhenSceneChanges)
+ mgr.AddDependencies(c);
+ }
+
+#if UNITY_2020_2_OR_NEWER
+ static void Changed(ref ObjectChangeEventStream stream)
+ {
+ if (EditorApplication.isUpdating || Application.isPlaying || !ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences || !ES3Settings.defaultSettingsScriptableObject.updateReferencesWhenSceneChanges)
+ return;
+
+ for (int i = 0; i < stream.length; i++)
+ {
+ var eventType = stream.GetEventType(i);
+ int[] instanceIds;
+ Scene scene;
+
+ if (eventType == ObjectChangeKind.ChangeGameObjectOrComponentProperties)
+ {
+ ChangeGameObjectOrComponentPropertiesEventArgs evt;
+ stream.GetChangeGameObjectOrComponentPropertiesEvent(i, out evt);
+ instanceIds = new int[] { evt.instanceId };
+ scene = evt.scene;
+ }
+ else if (eventType == ObjectChangeKind.CreateGameObjectHierarchy)
+ {
+ CreateGameObjectHierarchyEventArgs evt;
+ stream.GetCreateGameObjectHierarchyEvent(i, out evt);
+ instanceIds = new int[] { evt.instanceId };
+ scene = evt.scene;
+ }
+ /*else if (eventType == ObjectChangeKind.ChangeAssetObjectProperties)
+ {
+ ChangeAssetObjectPropertiesEventArgs evt;
+ stream.GetChangeAssetObjectPropertiesEvent(i, out evt);
+ instanceIds = new int[] { evt.instanceId };
+ }*/
+ else if (eventType == ObjectChangeKind.UpdatePrefabInstances)
+ {
+ UpdatePrefabInstancesEventArgs evt;
+ stream.GetUpdatePrefabInstancesEvent(i, out evt);
+ instanceIds = evt.instanceIds.ToArray();
+ scene = evt.scene;
+ }
+ else
+ continue;
+
+ var mgr = (ES3ReferenceMgr)ES3ReferenceMgr.GetManagerFromScene(scene, false);
+
+ if (mgr == null)
+ return;
+
+ foreach (var id in instanceIds)
+ {
+ try
+ {
+ var obj = EditorUtility.InstanceIDToObject(id);
+
+ if (obj == null)
+ continue;
+
+ mgr.AddDependencies(obj);
+ }
+ catch { }
+ }
+ }
+ }
+#endif
+
+ /*public static void PlayModeStateChanged(PlayModeStateChange state)
+ {
+ // Add all GameObjects and Components to the reference manager before we enter play mode.
+ if (state == PlayModeStateChange.ExitingEditMode && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
+ RefreshReferences(true);
+ }*/
+
+ public static string[] OnWillSaveAssets(string[] paths)
+ {
+ // Don't refresh references when the application is playing.
+ if (!EditorApplication.isUpdating && !Application.isPlaying)
+ {
+ if(ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences && ES3Settings.defaultSettingsScriptableObject.updateReferencesWhenSceneIsSaved)
+ RefreshReferences();
+ UpdateAssembliesContainingES3Types();
+ }
+ return paths;
+ }
+
+ #endregion
+
+
+ private static void UpdateAssembliesContainingES3Types()
+ {
+ var assemblies = UnityEditor.Compilation.CompilationPipeline.GetAssemblies();
+
+ if (assemblies == null || assemblies.Length == 0)
+ return;
+
+ var defaults = ES3Settings.defaultSettingsScriptableObject;
+ var currentAssemblyNames = defaults.settings.assemblyNames;
+
+ var assemblyNames = new List();
+
+ foreach (var assembly in assemblies)
+ {
+ // Don't include Editor assemblies.
+ if (assembly.flags.HasFlag(UnityEditor.Compilation.AssemblyFlags.EditorAssembly))
+ continue;
+
+ // Assemblies beginning with 'com.' are assumed to be internal.
+ if (assembly.name.StartsWith("com."))
+ continue;
+
+ // If this assembly begins with 'Unity', but isn't created from an Assembly Definition File, skip it.
+ if (assembly.name.StartsWith("Unity"))
+ {
+ bool isAssemblyDefinition = true;
+
+ foreach (string sourceFile in assembly.sourceFiles)
+ {
+ if (!sourceFile.StartsWith("Assets/"))
+ {
+ isAssemblyDefinition = false;
+ break;
+ }
+ }
+
+ if (!isAssemblyDefinition)
+ continue;
+ }
+
+ assemblyNames.Add(assembly.name);
+ }
+
+ // If there are no assembly names,
+ if (assemblyNames.Count == 0)
+ return;
+
+ // Sort it alphabetically so that the order isn't constantly changing, which can affect version control.
+ assemblyNames.Sort();
+
+ // Only update if the list has changed.
+ for (int i = 0; i < assemblyNames.Count; i++)
+ {
+ if (currentAssemblyNames.Length != assemblyNames.Count || currentAssemblyNames[i] != assemblyNames[i])
+ {
+ defaults.settings.assemblyNames = assemblyNames.ToArray();
+ EditorUtility.SetDirty(defaults);
+ break;
+ }
+ }
+ }
+
+ public static GameObject AddManagerToScene()
+ {
+ GameObject mgr = null;
+
+ var mgrComponent = ES3ReferenceMgr.GetManagerFromScene(SceneManager.GetActiveScene(), false);
+ if (mgrComponent != null)
+ mgr = mgrComponent.gameObject;
+
+ if (mgr == null)
+ mgr = new GameObject("Easy Save 3 Manager");
+
+ if (mgr.GetComponent() == null)
+ {
+ var refMgr = mgr.AddComponent();
+
+ if (!Application.isPlaying && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
+ refMgr.RefreshDependencies();
+ }
+
+ if (mgr.GetComponent() == null)
+ mgr.AddComponent();
+
+ Undo.RegisterCreatedObjectUndo(mgr, "Enabled Easy Save for Scene");
+ return mgr;
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs.meta
new file mode 100644
index 0000000..f6726e4
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Postprocessor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4256380692bcb4e57bdc0a5e13956389
+timeCreated: 1474041535
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs
new file mode 100644
index 0000000..03bed84
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs
@@ -0,0 +1,50 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using System;
+using System.Collections;
+using ES3Internal;
+
+[CustomEditor(typeof(ES3Prefab))]
+[System.Serializable]
+public class ES3PrefabEditor : Editor
+{
+ bool showAdvanced = false;
+ bool openLocalRefs = false;
+
+ public override void OnInspectorGUI()
+ {
+ var es3Prefab = (ES3Prefab)serializedObject.targetObject;
+ EditorGUILayout.HelpBox("Easy Save is enabled for this prefab, and can be saved and loaded with the ES3 methods.", MessageType.None);
+
+
+ showAdvanced = EditorGUILayout.Foldout(showAdvanced, "Advanced Settings");
+ if(showAdvanced)
+ {
+ EditorGUI.indentLevel++;
+ es3Prefab.prefabId = EditorGUILayout.LongField("Prefab ID", es3Prefab.prefabId);
+ EditorGUILayout.LabelField("Reference count", es3Prefab.localRefs.Count.ToString());
+ EditorGUI.indentLevel--;
+
+ openLocalRefs = EditorGUILayout.Foldout(openLocalRefs, "localRefs");
+ if (openLocalRefs)
+ {
+ EditorGUI.indentLevel++;
+
+ EditorGUILayout.LabelField("It is not recommended to manually modify these.");
+
+ foreach (var kvp in es3Prefab.localRefs)
+ {
+ EditorGUILayout.BeginHorizontal();
+
+ EditorGUILayout.ObjectField(kvp.Key, typeof(UnityEngine.Object), false);
+ EditorGUILayout.LongField(kvp.Value);
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ EditorGUI.indentLevel--;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs.meta
new file mode 100644
index 0000000..f0d7c5e
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3PrefabEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9d25610c9233c4cdfa5a0744c9956f5c
+timeCreated: 1519132292
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs
new file mode 100644
index 0000000..714c32b
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs
@@ -0,0 +1,296 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+[CustomEditor(typeof(ES3ReferenceMgr))]
+[System.Serializable]
+public class ES3ReferenceMgrEditor : Editor
+{
+ private bool isDraggingOver = false;
+ private bool openReferences = false;
+
+ private ES3ReferenceMgr _mgr = null;
+ private ES3ReferenceMgr mgr
+ {
+ get
+ {
+ if (_mgr == null)
+ _mgr = (ES3ReferenceMgr)serializedObject.targetObject;
+ return _mgr;
+ }
+ }
+
+ public override void OnInspectorGUI()
+ {
+ EditorGUILayout.HelpBox("This allows Easy Save to maintain references to objects in your scene.\n\nIt is automatically updated when you enter Playmode or build your project.", MessageType.Info);
+
+ if (EditorGUILayout.Foldout(openReferences, "References") != openReferences)
+ {
+ openReferences = !openReferences;
+ if (openReferences == true)
+ openReferences = EditorUtility.DisplayDialog("Are you sure?", "Opening this list will display every reference in the manager, which for larger projects can cause the Editor to freeze\n\nIt is strongly recommended that you save your project before continuing.", "Open References", "Cancel");
+ }
+
+ // Make foldout drag-and-drop enabled for objects.
+ if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
+ {
+ Event evt = Event.current;
+
+ switch (evt.type)
+ {
+ case EventType.DragUpdated:
+ case EventType.DragPerform:
+ isDraggingOver = true;
+ break;
+ case EventType.DragExited:
+ isDraggingOver = false;
+ break;
+ }
+
+ if (isDraggingOver)
+ {
+ DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
+
+ if (evt.type == EventType.DragPerform)
+ {
+ DragAndDrop.AcceptDrag();
+ Undo.RecordObject(mgr, "Add References to Easy Save 3 Reference List");
+ foreach (UnityEngine.Object obj in DragAndDrop.objectReferences)
+ mgr.Add(obj);
+ // Return now because otherwise we'll change the GUI during an event which doesn't allow it.
+ return;
+ }
+ }
+ }
+
+ if (openReferences)
+ {
+ EditorGUI.indentLevel++;
+
+ foreach (var kvp in mgr.idRef)
+ {
+ EditorGUILayout.BeginHorizontal();
+
+ var value = EditorGUILayout.ObjectField(kvp.Value, typeof(UnityEngine.Object), true);
+ var key = EditorGUILayout.LongField(kvp.Key);
+
+ EditorGUILayout.EndHorizontal();
+
+ if (value != kvp.Value || key != kvp.Key)
+ {
+ Undo.RecordObject(mgr, "Change Easy Save 3 References");
+ // If we're deleting a value, delete it.
+ if (value == null)
+ mgr.Remove(key);
+ // Else, update the ID.
+ else
+ mgr.ChangeId(kvp.Key, key);
+ // Break, as removing or changing Dictionary items will make the foreach out of sync.
+ break;
+ }
+ }
+
+ EditorGUI.indentLevel--;
+ }
+
+ mgr.openPrefabs = EditorGUILayout.Foldout(mgr.openPrefabs, "ES3Prefabs");
+ if (mgr.openPrefabs)
+ {
+ EditorGUI.indentLevel++;
+
+ foreach (var prefab in mgr.prefabs)
+ {
+ EditorGUILayout.BeginHorizontal();
+
+ EditorGUILayout.ObjectField(prefab, typeof(UnityEngine.Object), true);
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ EditorGUI.indentLevel--;
+ }
+
+ var sp = serializedObject.FindProperty("excludeObjects");
+ EditorGUILayout.PropertyField(sp);
+ serializedObject.ApplyModifiedProperties();
+
+ EditorGUILayout.LabelField("Reference count", mgr.refId.Count.ToString());
+ EditorGUILayout.LabelField("Prefab count", mgr.prefabs.Count.ToString());
+
+ if (GUILayout.Button("Refresh"))
+ {
+ mgr.RefreshDependencies();
+ }
+
+ if (GUILayout.Button("Optimize"))
+ {
+ mgr.Optimize();
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Add Dependencies to Manager", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Dependencies to Manager", false, 33)]
+ public static void AddDependenciesToManager()
+ {
+ var mgr = ES3ReferenceMgr.GetManagerFromScene(SceneManager.GetActiveScene());
+ if (mgr == null)
+ {
+ EditorUtility.DisplayDialog("Could not add reference to manager", "This object could not be added to the reference manager because no reference manager exists in this scene. To create one, go to Tools > Easy Save 3 > Add Manager to Scene", "Ok");
+ return;
+ }
+
+ var selected = new HashSet(Selection.GetFiltered(SelectionMode.DeepAssets));
+ selected.UnionWith(Selection.GetFiltered(SelectionMode.TopLevel));
+
+ if (selected == null || selected.Count == 0)
+ return;
+
+ Undo.RecordObject(mgr, "Update Easy Save 3 Reference Manager");
+
+ foreach (var obj in selected)
+ {
+ if (obj == null)
+ continue;
+
+ if (obj.GetType() == typeof(GameObject))
+ {
+ var go = (GameObject)obj;
+ if (ES3EditorUtility.IsPrefabInAssets(go) && go.GetComponent() != null)
+ mgr.AddPrefab(go.GetComponent());
+ }
+
+ ((ES3ReferenceMgr)mgr).AddDependencies(obj);
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Add Reference(s) to Manager", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Reference(s) to Manager", false, 33)]
+ public static void AddReferencesToManager()
+ {
+ var mgr = ES3ReferenceMgr.Current;
+ if (mgr == null)
+ {
+ EditorUtility.DisplayDialog("Could not add reference to manager", "This object could not be added to the reference manager because no reference manager exists in this scene. To create one, go to Tools > Easy Save 3 > Add Manager to Scene", "Ok");
+ return;
+ }
+
+ var selected = Selection.GetFiltered(SelectionMode.TopLevel);
+
+ if (selected == null || selected.Length == 0)
+ return;
+
+ Undo.RecordObject(mgr, "Update Easy Save 3 Reference Manager");
+
+ foreach (var obj in selected)
+ {
+ if (obj == null)
+ continue;
+
+ if (obj.GetType() == typeof(GameObject))
+ {
+ var go = (GameObject)obj;
+ if (ES3EditorUtility.IsPrefabInAssets(go) && go.GetComponent() != null)
+ mgr.AddPrefab(go.GetComponent());
+ }
+
+ ((ES3ReferenceMgr)mgr).Add(obj);
+ }
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Add Reference(s) to Manager", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Reference(s) to Manager", true, 33)]
+ [MenuItem("GameObject/Easy Save 3/Add Dependencies to Manager", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Dependencies to Manager", true, 33)]
+ private static bool CanAddReferenceToManager()
+ {
+ var selected = Selection.GetFiltered(SelectionMode.Deep);
+ return selected != null && selected.Length > 0 && ES3ReferenceMgr.Current != null;
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Exclude Reference(s) from Manager", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Exclude Reference(s) from Manager", false, 33)]
+ public static void ExcludeReferenceFromManager()
+ {
+ var mgr = (ES3ReferenceMgr)ES3ReferenceMgr.Current;
+ if (mgr == null)
+ {
+ EditorUtility.DisplayDialog("Could not exclude reference from manager", "This object could not be excluded from the reference manager because no reference manager exists in this scene. To create one, go to Tools > Easy Save 3 > Add Manager to Scene", "Ok");
+ return;
+ }
+
+ var selected = Selection.GetFiltered(SelectionMode.TopLevel);
+
+ if (selected == null || selected.Length == 0)
+ return;
+
+ Undo.RecordObject(mgr, "Exclude from Easy Save 3 Reference Manager");
+
+ foreach (var obj in selected)
+ {
+ if (obj == null)
+ continue;
+
+ mgr.ExcludeObject(obj);
+ }
+
+ mgr.RemoveNullOrInvalidValues();
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Exclude Dependencies from Manager", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Exclude Dependencies from Manager", false, 33)]
+ public static void ExcludeDependenciesFromManager()
+ {
+ var mgr = (ES3ReferenceMgr)ES3ReferenceMgr.Current;
+ if (mgr == null)
+ {
+ EditorUtility.DisplayDialog("Could not exclude reference from manager", "This object could not be excluded from the reference manager because no reference manager exists in this scene. To create one, go to Tools > Easy Save 3 > Add Manager to Scene", "Ok");
+ return;
+ }
+
+ var selected = Selection.GetFiltered(SelectionMode.TopLevel);
+
+ if (selected == null || selected.Length == 0)
+ return;
+
+ Undo.RecordObject(mgr, "Exclude from Easy Save 3 Reference Manager");
+
+ var dependencies = EditorUtility.CollectDependencies(selected);
+
+ foreach (var dependency in dependencies)
+ mgr.ExcludeObject(dependency);
+
+ mgr.RemoveNullOrInvalidValues();
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Exclude Dependencies from Manager", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Exclude Dependencies from Manager", true, 33)]
+ [MenuItem("GameObject/Easy Save 3/Exclude Reference(s) from Manager", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Exclude Reference(s) from Manager", true, 33)]
+ private static bool CanExcludeReferencesFromManager()
+ {
+ var selected = Selection.GetFiltered(SelectionMode.Deep);
+ return selected != null && selected.Length > 0 && ES3ReferenceMgr.Current != null;
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Add Manager to Scene", false, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Manager to Scene", false, 33)]
+ [MenuItem("Tools/Easy Save 3/Add Manager to Scene", false, 150)]
+ public static void EnableForScene()
+ {
+ if(!SceneManager.GetActiveScene().isLoaded)
+ EditorUtility.DisplayDialog("Could not add manager to scene", "Could not add Easy Save 3 Manager to scene because there is not currently a scene open.", "Ok");
+ Selection.activeObject = ES3Postprocessor.AddManagerToScene();
+ }
+
+ [MenuItem("GameObject/Easy Save 3/Add Manager to Scene", true, 33)]
+ [MenuItem("Assets/Easy Save 3/Add Manager to Scene", true, 33)]
+ [MenuItem("Tools/Easy Save 3/Add Manager to Scene", true, 150)]
+ private static bool CanEnableForScene()
+ {
+ return ES3ReferenceMgr.GetManagerFromScene(SceneManager.GetActiveScene(), false) == null;
+ }
+}
+
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs.meta
new file mode 100644
index 0000000..b60a7a3
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ReferenceMgrEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3b43d266ed3464dedaa77757645ad61c
+timeCreated: 1519132283
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs
new file mode 100644
index 0000000..4a21d10
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs
@@ -0,0 +1,128 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEditor.Build;
+using System.Collections.Generic;
+using UnityEditor.Compilation;
+using System.Reflection;
+using System.Linq;
+using System;
+
+[InitializeOnLoad]
+public class ES3ScriptingDefineSymbols
+{
+ static ES3ScriptingDefineSymbols()
+ {
+ SetDefineSymbols();
+ }
+
+ static void SetDefineSymbols()
+ {
+ if (Type.GetType("Unity.VisualScripting.IncludeInSettingsAttribute, Unity.VisualScripting.Core") != null)
+ SetDefineSymbol("UNITY_VISUAL_SCRIPTING");
+
+ if (Type.GetType("Ludiq.IncludeInSettingsAttribute, Ludiq.Core.Runtime") != null)
+ SetDefineSymbol("BOLT_VISUAL_SCRIPTING");
+
+ if (Type.GetType("TMPro.TextMeshProUGUI, Unity.TextMeshPro") != null)
+ SetDefineSymbol("ES3_TMPRO");
+
+ if (Type.GetType("UnityEngine.EventSystems.EventSystem, UnityEngine.UI") != null)
+ SetDefineSymbol("ES3_UGUI");
+ }
+
+ internal static bool HasDefineSymbol(string symbol)
+ {
+#if UNITY_2021_2_OR_NEWER
+ foreach (var target in GetAllNamedBuildTargets())
+ {
+ string[] defines;
+ try
+ {
+ PlayerSettings.GetScriptingDefineSymbols(target, out defines);
+ if (defines.Contains(symbol))
+ return true;
+ }
+ catch { }
+ }
+#else
+ string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
+ var allDefines = new HashSet(definesString.Split(';'));
+ if (allDefines.Contains(symbol))
+ return true;
+#endif
+ return false;
+ }
+
+ internal static void SetDefineSymbol(string symbol)
+ {
+#if UNITY_2021_2_OR_NEWER
+ foreach (var target in GetAllNamedBuildTargets())
+ {
+ string[] defines;
+ try
+ {
+ PlayerSettings.GetScriptingDefineSymbols(target, out defines);
+ if (!defines.Contains(symbol))
+ {
+ ArrayUtility.Add(ref defines, symbol);
+ PlayerSettings.SetScriptingDefineSymbols(target, defines);
+ }
+ }
+ catch { }
+ }
+#else
+ string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
+ var allDefines = new HashSet(definesString.Split(';'));
+ if (!allDefines.Contains(symbol))
+ PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(";", allDefines.Concat(new string[] { symbol }).ToArray()));
+#endif
+ return;
+ }
+
+ internal static void RemoveDefineSymbol(string symbol)
+ {
+#if UNITY_2021_2_OR_NEWER
+ foreach (var target in GetAllNamedBuildTargets())
+ {
+ string[] defines;
+ try
+ {
+ PlayerSettings.GetScriptingDefineSymbols(target, out defines);
+ ArrayUtility.Remove(ref defines, symbol);
+ PlayerSettings.SetScriptingDefineSymbols(target, defines);
+ }
+ catch { }
+ }
+#else
+ string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
+ definesString.Replace(symbol + ";", ""); // With semicolon
+ definesString.Replace(symbol, ""); // Without semicolon
+ PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, definesString);
+#endif
+ return;
+ }
+
+#if UNITY_2021_2_OR_NEWER
+ static List GetAllNamedBuildTargets()
+ {
+ var staticFields = typeof(NamedBuildTarget).GetFields(BindingFlags.Public | BindingFlags.Static);
+ var buildTargets = new List();
+
+ foreach (var staticField in staticFields)
+ {
+ // We exclude 'Unknown' because this can throw errors when used with certain methods.
+ if (staticField.Name == "Unknown")
+ continue;
+
+ // A bug at Unity's end means that Stadia can throw an error.
+ if (staticField.Name == "Stadia")
+ continue;
+
+ if (staticField.FieldType == typeof(NamedBuildTarget))
+ buildTargets.Add((NamedBuildTarget)staticField.GetValue(null));
+ }
+
+ return buildTargets;
+ }
+#endif
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs.meta
new file mode 100644
index 0000000..ca2780c
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3ScriptingDefineSymbols.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 69b6276384d46d34fb2705f95689e8cc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs
new file mode 100644
index 0000000..9eef456
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs
@@ -0,0 +1,56 @@
+using UnityEditor;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using System;
+using System.Collections;
+using ES3Internal;
+
+namespace ES3Editor
+{
+ public static class ES3SettingsEditor
+ {
+ public static void Draw(ES3SerializableSettings settings)
+ {
+ var style = EditorStyle.Get;
+
+ settings.location = (ES3.Location)EditorGUILayout.EnumPopup("Location", settings.location);
+ // If the location is File, show the Directory.
+ if(settings.location == ES3.Location.File)
+ settings.directory = (ES3.Directory)EditorGUILayout.EnumPopup("Directory", settings.directory);
+
+ settings.path = EditorGUILayout.TextField("Default File Path", settings.path);
+
+ EditorGUILayout.Space();
+
+ settings.encryptionType = (ES3.EncryptionType)EditorGUILayout.EnumPopup("Encryption", settings.encryptionType);
+ settings.encryptionPassword = EditorGUILayout.TextField("Encryption Password", settings.encryptionPassword);
+
+ EditorGUILayout.Space();
+
+ settings.compressionType = (ES3.CompressionType)EditorGUILayout.EnumPopup("Compression", settings.compressionType);
+
+ EditorGUILayout.Space();
+
+ settings.saveChildren = EditorGUILayout.Toggle("Save GameObject Children", settings.saveChildren);
+
+ EditorGUILayout.Space();
+
+ if(settings.showAdvancedSettings = EditorGUILayout.Foldout(settings.showAdvancedSettings, "Advanced Settings"))
+ {
+ EditorGUILayout.BeginVertical(style.area);
+
+ settings.format = (ES3.Format)EditorGUILayout.EnumPopup("Format", settings.format);
+ if (settings.format == ES3.Format.JSON)
+ settings.prettyPrint = EditorGUILayout.Toggle(new GUIContent("Pretty print JSON"), settings.prettyPrint);
+ settings.bufferSize = EditorGUILayout.IntField("Buffer Size", settings.bufferSize);
+ settings.memberReferenceMode = (ES3.ReferenceMode)EditorGUILayout.EnumPopup("Serialise Unity Object fields", settings.memberReferenceMode);
+ settings.serializationDepthLimit = EditorGUILayout.IntField("Serialisation Depth", settings.serializationDepthLimit);
+ settings.postprocessRawCachedData = EditorGUILayout.Toggle(new GUIContent("Postprocess raw cached data"), settings.postprocessRawCachedData);
+
+ EditorGUILayout.Space();
+
+ EditorGUILayout.EndVertical();
+ }
+ }
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs.meta
new file mode 100644
index 0000000..be6af3c
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3SettingsEditor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 35659b9a083a341d7bee216c4b71f4bc
+timeCreated: 1519132282
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs
new file mode 100644
index 0000000..98d6aca
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs
@@ -0,0 +1,238 @@
+using UnityEngine;
+using UnityEditor;
+using System.Linq;
+
+namespace ES3Editor
+{
+ public class ES3Window : EditorWindow
+ {
+ private SubWindow[] windows = null;
+
+ public SubWindow currentWindow;
+
+ [MenuItem("Window/Easy Save 3", false, 1000)]
+ [MenuItem("Assets/Easy Save 3/Open Easy Save 3 Window", false, 1000)]
+ public static void Init()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if(window != null)
+ window.Show();
+ }
+
+ public static void InitAndShowHome()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(HomeWindow));
+ }
+ }
+
+ [MenuItem("Tools/Easy Save 3/Auto Save", false, 100)]
+ public static void InitAndShowAutoSave()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(AutoSaveWindow));
+ }
+ }
+
+ public static void InitAndShowReferences()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(ReferencesWindow));
+ }
+ }
+
+ [MenuItem("Tools/Easy Save 3/Types", false, 100)]
+ public static void InitAndShowTypes()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(TypesWindow));
+ }
+ }
+
+ public static void InitAndShowTypes(System.Type type)
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ var typesWindow = (TypesWindow)window.SetCurrentWindow(typeof(TypesWindow));
+ typesWindow.SelectType(type);
+ }
+ }
+
+ [MenuItem("Tools/Easy Save 3/Settings", false, 100)]
+ public static void InitAndShowSettings()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(SettingsWindow));
+ }
+ }
+
+ [MenuItem("Tools/Easy Save 3/Tools", false, 100)]
+ public static void InitAndShowTools()
+ {
+ // Get existing open window or if none, make a new one:
+ ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
+ if (window != null)
+ {
+ window.Show();
+ window.SetCurrentWindow(typeof(ToolsWindow));
+ }
+ }
+
+ public void InitSubWindows()
+ {
+ windows = new SubWindow[]{
+ new HomeWindow(this),
+ new SettingsWindow(this),
+ new ToolsWindow(this),
+ new TypesWindow(this),
+ new AutoSaveWindow(this)
+ //, new ReferencesWindow(this)
+ };
+ }
+
+ void OnLostFocus()
+ {
+ if(currentWindow != null)
+ currentWindow.OnLostFocus();
+ }
+
+ private void OnFocus()
+ {
+ if (currentWindow != null)
+ currentWindow.OnFocus();
+ }
+
+ void OnDestroy()
+ {
+ if(currentWindow != null)
+ currentWindow.OnDestroy();
+ }
+
+ void OnEnable()
+ {
+ if(windows == null)
+ InitSubWindows();
+ // Set the window name and icon.
+ var icon = AssetDatabase.LoadAssetAtPath(ES3Settings.PathToEasySaveFolder()+"Editor/es3Logo16x16.png");
+ titleContent = new GUIContent("Easy Save", icon);
+
+ // Get the last opened window and open it.
+ if(currentWindow == null)
+ {
+ var currentWindowName = EditorPrefs.GetString("ES3Editor.Window.currentWindow", windows[0].name);
+ for(int i=0; i w.GetType() == type);
+ EditorPrefs.SetString("ES3Editor.Window.currentWindow", currentWindow.name);
+ return currentWindow;
+ }
+
+ // Shows the Easy Save Home window if it's not been disabled.
+ // This method is called from the Postprocessor.
+ public static void OpenEditorWindowOnStart()
+ {
+ if(EditorPrefs.GetBool("Show ES3 Window on Start", true))
+ ES3Window.InitAndShowHome();
+ EditorPrefs.SetBool("Show ES3 Window on Start", false);
+ }
+ }
+
+ public abstract class SubWindow
+ {
+ public string name;
+ public EditorWindow parent;
+ public abstract void OnGUI();
+
+ public SubWindow(string name, EditorWindow parent)
+ {
+ this.name = name;
+ this.parent = parent;
+ }
+
+ public virtual void OnLostFocus()
+ {
+ }
+
+ public virtual void OnFocus()
+ {
+ }
+
+ public virtual void OnDestroy()
+ {
+ }
+
+ public virtual void OnHierarchyChange()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs.meta
new file mode 100644
index 0000000..0f5ce70
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ES3Window.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a95d98897f1cf4e7288b53b0fd8036c1
+timeCreated: 1519132293
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs
new file mode 100644
index 0000000..e6be747
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs
@@ -0,0 +1,23 @@
+using UnityEditor;
+using System.IO;
+
+public class EnableES3AssemblyDefinitions : Editor
+{
+ [MenuItem("Tools/Easy Save 3/Enable Assembly Definition Files", false, 150)]
+ public static void EnableAsmDef()
+ {
+ var pathToEasySaveFolder = ES3Settings.PathToEasySaveFolder();
+ File.Delete(pathToEasySaveFolder + "Editor/EasySave3.asmdef.disabled.meta");
+ File.Delete(pathToEasySaveFolder + "Editor/EasySave3Editor.asmdef.disabled.meta");
+ File.Move(pathToEasySaveFolder + "Editor/EasySave3Editor.asmdef.disabled", pathToEasySaveFolder + "Editor/EasySave3Editor.asmdef");
+ File.Move(pathToEasySaveFolder + "Editor/EasySave3.asmdef.disabled", pathToEasySaveFolder + "EasySave3.asmdef");
+ AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
+ EditorUtility.DisplayDialog("Assembly definition files installed", "Assembly definition files for Easy Save 3 installed.\n\nYou may need to go to 'Assets > Reimport' to apply the changes.", "Done");
+ }
+
+ [MenuItem("Tools/Easy Save 3/Enable Assembly Definition Files", true, 150)]
+ public static bool CanEnableAsmDef()
+ {
+ return !File.Exists(ES3Settings.PathToEasySaveFolder() + "EasySave3.asmdef");
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs.meta
new file mode 100644
index 0000000..0144526
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/EnableES3AssemblyDefinitions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f53975dae5ac26947856dd0b0bd3be7e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs
new file mode 100644
index 0000000..5e86054
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace ES3Editor
+{
+ public class HomeWindow : SubWindow
+ {
+ Vector2 scrollPos = Vector2.zero;
+
+ public HomeWindow(EditorWindow window) : base("Home", window){}
+
+ public override void OnGUI()
+ {
+
+ var style = EditorStyle.Get;
+
+ scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ GUILayout.Label("Welcome to Easy Save", style.heading);
+
+ EditorGUILayout.BeginVertical(style.area);
+ GUILayout.Label("New To Easy Save?", style.subheading);
+ EditorGUILayout.BeginVertical(style.area);
+ ES3EditorUtility.DisplayLink("• See our Getting Started guide", "http://docs.moodkie.com/easy-save-3/getting-started/");
+ EditorGUILayout.EndVertical();
+
+ GUILayout.Label("Support", style.subheading);
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ ES3EditorUtility.DisplayLink("• Contact us directly", "http://www.moodkie.com/contact/");
+ ES3EditorUtility.DisplayLink("• Ask a question in our Easy Save 3 forums", "http://moodkie.com/forum/viewforum.php?f=12");
+ ES3EditorUtility.DisplayLink("• Ask a question in the Unity Forum thread","https://forum.unity3d.com/threads/easy-save-the-complete-save-load-asset-for-unity.91040/");
+ EditorGUILayout.EndVertical();
+
+ GUILayout.Label("Documentation and Guides", style.subheading);
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ ES3EditorUtility.DisplayLink("• Documentation", "http://docs.moodkie.com/product/easy-save-3/");
+ ES3EditorUtility.DisplayLink("• Guides", "http://docs.moodkie.com/product/easy-save-3/es3-guides/");
+ ES3EditorUtility.DisplayLink("• API Scripting Reference", "http://docs.moodkie.com/product/easy-save-3/es3-api/");
+ ES3EditorUtility.DisplayLink("• Supported Types", "http://docs.moodkie.com/easy-save-3/es3-supported-types/");
+
+
+ EditorGUILayout.EndVertical();
+
+ GUILayout.Label("PlayMaker Documentation", style.subheading);
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ ES3EditorUtility.DisplayLink("• Actions", "http://docs.moodkie.com/product/easy-save-3/es3-playmaker/es3-playmaker-actions/");
+ ES3EditorUtility.DisplayLink("• Actions Overview", "http://docs.moodkie.com/easy-save-3/es3-playmaker/playmaker-actions-overview/");
+
+
+ EditorGUILayout.EndVertical();
+
+ EditorGUILayout.EndVertical();
+
+ EditorGUILayout.EndVertical();
+
+ EditorGUILayout.EndScrollView();
+
+ }
+ }
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs.meta
new file mode 100644
index 0000000..cf019eb
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/HomeWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 394cc2e77038849709526f44f7efdd22
+timeCreated: 1519132283
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs
new file mode 100644
index 0000000..57c4441
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs
@@ -0,0 +1,21 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using ES3Internal;
+
+namespace ES3Editor
+{
+ public class ReferencesWindow : SubWindow
+ {
+
+
+ public ReferencesWindow(EditorWindow window) : base("References", window){}
+
+ public override void OnGUI()
+ {
+
+ }
+ }
+
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs.meta
new file mode 100644
index 0000000..5e132e9
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ReferencesWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: af2d805793e784eef87fbcdebb11fa35
+timeCreated: 1519132291
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs
new file mode 100644
index 0000000..0c3e4d6
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs
@@ -0,0 +1,179 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using ES3Internal;
+
+namespace ES3Editor
+{
+ public class SettingsWindow : SubWindow
+ {
+ public ES3Defaults editorSettings = null;
+ public ES3SerializableSettings settings = null;
+ public SerializedObject so = null;
+ public SerializedProperty referenceFoldersProperty = null;
+
+ Vector2 scrollPos = Vector2.zero;
+ const string disableGlobalDefineName = "ES3GLOBAL_DISABLED";
+
+ public SettingsWindow(EditorWindow window) : base("Settings", window){}
+
+ public void OnEnable()
+ {
+
+ }
+
+ public override void OnGUI()
+ {
+ if(settings == null || editorSettings == null)
+ Init();
+
+ var style = EditorStyle.Get;
+
+ var labelWidth = EditorGUIUtility.labelWidth;
+
+
+ EditorGUI.BeginChangeCheck();
+
+ using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPos, style.area))
+ {
+ scrollPos = scrollView.scrollPosition;
+
+ EditorGUIUtility.labelWidth = 160;
+
+ GUILayout.Label("Runtime Settings", style.heading);
+
+ using (new EditorGUILayout.VerticalScope(style.area))
+ {
+ ES3SettingsEditor.Draw(settings);
+ }
+
+ GUILayout.Label("Debug Settings", style.heading);
+
+ using (new EditorGUILayout.VerticalScope(style.area))
+ {
+ EditorGUIUtility.labelWidth = 100;
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PrefixLabel("Log Info");
+ editorSettings.logDebugInfo = EditorGUILayout.Toggle(editorSettings.logDebugInfo);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PrefixLabel("Log Warnings");
+ editorSettings.logWarnings = EditorGUILayout.Toggle(editorSettings.logWarnings);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PrefixLabel("Log Errors");
+ editorSettings.logErrors = EditorGUILayout.Toggle(editorSettings.logErrors);
+ }
+
+ EditorGUILayout.Space();
+ }
+
+ GUILayout.Label("Editor Settings", style.heading);
+
+ using (new EditorGUILayout.VerticalScope(style.area))
+ {
+ EditorGUIUtility.labelWidth = 170;
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PrefixLabel("Auto Update References");
+ editorSettings.autoUpdateReferences = EditorGUILayout.Toggle(editorSettings.autoUpdateReferences);
+ }
+
+ if (editorSettings.autoUpdateReferences)
+ {
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("-- When changes are made", "Should Easy Save update the reference manager when objects in your scene changes?");
+ editorSettings.updateReferencesWhenSceneChanges = EditorGUILayout.Toggle(content, editorSettings.updateReferencesWhenSceneChanges);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("-- When scene is saved", "Should Easy Save update the reference manager when objects in your scene is saved?");
+ editorSettings.updateReferencesWhenSceneIsSaved = EditorGUILayout.Toggle(content, editorSettings.updateReferencesWhenSceneIsSaved);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("-- When scene is opened", "Should Easy Save update the reference manager you open a scene in the Editor?");
+ editorSettings.updateReferencesWhenSceneIsOpened = EditorGUILayout.Toggle(content, editorSettings.updateReferencesWhenSceneIsOpened);
+ }
+ EditorGUILayout.Space();
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ so.Update();
+ EditorGUILayout.PropertyField(referenceFoldersProperty, true);
+ so.ApplyModifiedProperties();
+ }
+ EditorGUILayout.Space();
+
+ /*using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("Reference depth", "How deep should Easy Save look when gathering references from an object? Higher means deeper.");
+ EditorGUILayout.PrefixLabel(content);
+ editorSettings.collectDependenciesDepth = EditorGUILayout.IntField(editorSettings.collectDependenciesDepth);
+ }*/
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("Reference timeout (seconds)", "How many seconds should Easy Save taking collecting references for an object before timing out?");
+ EditorGUILayout.PrefixLabel(content);
+ editorSettings.collectDependenciesTimeout = EditorGUILayout.IntField(editorSettings.collectDependenciesTimeout);
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PrefixLabel("Use Global References");
+
+ bool useGlobalReferences = !ES3ScriptingDefineSymbols.HasDefineSymbol(disableGlobalDefineName);
+ if(EditorGUILayout.Toggle(useGlobalReferences) != useGlobalReferences)
+ {
+ // If global references is currently enabled, we want to disable it.
+ if (!useGlobalReferences)
+ {
+ ES3ScriptingDefineSymbols.RemoveDefineSymbol(disableGlobalDefineName);
+ EditorUtility.DisplayDialog("Global references disabled for build platform", "This will only disable Global References for this build platform. To disable it for other build platforms, open that platform in the Build Settings and uncheck this box again.", "Ok");
+ }
+ // Else we want to enable it.
+ else
+ ES3ScriptingDefineSymbols.SetDefineSymbol(disableGlobalDefineName);
+ }
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ var content = new GUIContent("Add All Prefabs to Manager", "Should all prefabs with ES3Prefab Components be added to the manager?");
+ EditorGUILayout.PrefixLabel(content);
+ editorSettings.addAllPrefabsToManager = EditorGUILayout.Toggle(editorSettings.addAllPrefabsToManager);
+ }
+
+ EditorGUILayout.Space();
+ }
+ }
+
+ if (EditorGUI.EndChangeCheck())
+ EditorUtility.SetDirty(editorSettings);
+
+ EditorGUIUtility.labelWidth = labelWidth; // Set the label width back to default
+ }
+
+ public void Init()
+ {
+ editorSettings = ES3Settings.defaultSettingsScriptableObject;
+ settings = editorSettings.settings;
+ so = new SerializedObject(editorSettings);
+ referenceFoldersProperty = so.FindProperty("referenceFolders");
+ }
+ }
+
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs.meta
new file mode 100644
index 0000000..d58da5f
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/SettingsWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 95e7bbc9a5aee44feb088811fb5e7b80
+timeCreated: 1519132291
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs
new file mode 100644
index 0000000..4518e37
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs
@@ -0,0 +1,155 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using System.IO;
+
+namespace ES3Editor
+{
+ public class ToolsWindow : SubWindow
+ {
+ public ToolsWindow(EditorWindow window) : base("Tools", window){}
+
+ public override void OnGUI()
+ {
+ var style = EditorStyle.Get;
+
+ EditorGUILayout.BeginHorizontal(style.area);
+
+ if (GUILayout.Button("Open Persistent Data Path"))
+ OpenPersistentDataPath();
+
+ EditorGUILayout.EndHorizontal();
+
+ EditorGUILayout.BeginHorizontal(style.area);
+
+ if (GUILayout.Button("Clear Persistent Data Path"))
+ ClearPersistentDataPath();
+
+ if (GUILayout.Button("Clear PlayerPrefs"))
+ ClearPlayerPrefs();
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ [MenuItem("Tools/Easy Save 3/Open Persistent Data Path", false, 200)]
+ private static void OpenPersistentDataPath()
+ {
+ EditorUtility.RevealInFinder(Application.persistentDataPath);
+ }
+
+ [MenuItem("Tools/Easy Save 3/Clear Persistent Data Path", false, 200)]
+ private static void ClearPersistentDataPath()
+ {
+ if (EditorUtility.DisplayDialog("Clear Persistent Data Path", "Are you sure you wish to clear the persistent data path?\n This action cannot be reversed.", "Clear", "Cancel"))
+ {
+ System.IO.DirectoryInfo di = new DirectoryInfo(Application.persistentDataPath);
+
+ foreach (FileInfo file in di.GetFiles())
+ file.Delete();
+ foreach (DirectoryInfo dir in di.GetDirectories())
+ dir.Delete(true);
+ }
+ }
+
+ [MenuItem("Tools/Easy Save 3/Clear PlayerPrefs", false, 200)]
+ private static void ClearPlayerPrefs()
+ {
+ if (EditorUtility.DisplayDialog("Clear PlayerPrefs", "Are you sure you wish to clear PlayerPrefs?\nThis action cannot be reversed.", "Clear", "Cancel"))
+ PlayerPrefs.DeleteAll();
+ }
+ }
+
+ /*public static class OSFileBrowser
+ {
+ public static bool IsInMacOS
+ {
+ get
+ {
+ return UnityEngine.SystemInfo.operatingSystem.IndexOf("Mac OS") != -1;
+ }
+ }
+
+ public static bool IsInWinOS
+ {
+ get
+ {
+ return UnityEngine.SystemInfo.operatingSystem.IndexOf("Windows") != -1;
+ }
+ }
+
+ public static void OpenInMac(string path)
+ {
+ bool openInsidesOfFolder = false;
+
+ // try mac
+ string macPath = path.Replace("\\", "/"); // mac finder doesn't like backward slashes
+
+ if ( System.IO.Directory.Exists(macPath) ) // if path requested is a folder, automatically open insides of that folder
+ {
+ openInsidesOfFolder = true;
+ }
+
+ if ( !macPath.StartsWith("\"") )
+ {
+ macPath = "\"" + macPath;
+ }
+
+ if ( !macPath.EndsWith("\"") )
+ {
+ macPath = macPath + "\"";
+ }
+
+ string arguments = (openInsidesOfFolder ? "" : "-R ") + macPath;
+
+ try
+ {
+ System.Diagnostics.Process.Start("open", arguments);
+ }
+ catch ( System.ComponentModel.Win32Exception e )
+ {
+ // tried to open mac finder in windows
+ // just silently skip error
+ // we currently have no platform define for the current OS we are in, so we resort to this
+ e.HelpLink = ""; // do anything with this variable to silence warning about not using it
+ }
+ }
+
+ public static void OpenInWin(string path)
+ {
+ bool openInsidesOfFolder = false;
+
+ // try windows
+ string winPath = path.Replace("/", "\\"); // windows explorer doesn't like forward slashes
+
+ if ( System.IO.Directory.Exists(winPath) ) // if path requested is a folder, automatically open insides of that folder
+ openInsidesOfFolder = true;
+
+ try
+ {
+ System.Diagnostics.Process.Start("explorer.exe", (openInsidesOfFolder ? "/root," : "/select,") + "\"" + winPath + "\"");
+ }
+ catch ( System.ComponentModel.Win32Exception e )
+ {
+ e.HelpLink = "";
+ }
+ }
+
+ public static void Open(string path)
+ {
+ if ( IsInWinOS )
+ {
+ OpenInWin(path);
+ }
+ else if ( IsInMacOS )
+ {
+ OpenInMac(path);
+ }
+ else // couldn't determine OS
+ {
+ OpenInWin(path);
+ OpenInMac(path);
+ }
+ }
+ }*/
+}
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs.meta b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs.meta
new file mode 100644
index 0000000..c6fbe3f
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/ToolsWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0d6114c1d40624e9e8575e814c45ac1a
+timeCreated: 1519132280
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/TypesWindow.cs b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/TypesWindow.cs
new file mode 100644
index 0000000..37d83fb
--- /dev/null
+++ b/Assets/SGModule/DataStorage/SGModule/Plugins/Easy Save 3/Editor/TypesWindow.cs
@@ -0,0 +1,728 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Reflection;
+using System.Linq;
+using ES3Types;
+using System.IO;
+using ES3Internal;
+using System.Text.RegularExpressions;
+
+namespace ES3Editor
+{
+ public class TypesWindow : SubWindow
+ {
+ TypeListItem[] types = null;
+ const int recentTypeCount = 5;
+ List recentTypes = null;
+
+ Vector2 typeListScrollPos = Vector2.zero;
+ Vector2 typePaneScrollPos = Vector2.zero;
+ int leftPaneWidth = 300;
+
+ string searchFieldValue = "";
+
+ int selectedType = -1;
+ private ES3Reflection.ES3ReflectedMember[] fields = new ES3Reflection.ES3ReflectedMember[0];
+ private bool[] fieldSelected = new bool[0];
+
+ private Texture2D checkmark;
+ //private Texture2D checkmarkSmall;
+
+ private GUIStyle searchBarStyle;
+ private GUIStyle searchBarCancelButtonStyle;
+ private GUIStyle leftPaneStyle;
+ private GUIStyle typeButtonStyle;
+ private GUIStyle selectedTypeButtonStyle;
+ private GUIStyle selectAllNoneButtonStyle;
+
+ private string valueTemplateFile;
+ private string classTemplateFile;
+ private string componentTemplateFile;
+ private string scriptableObjectTemplateFile;
+
+ private bool unsavedChanges = false;
+
+ public TypesWindow(EditorWindow window) : base("Types", window){}
+
+ public override void OnGUI()
+ {
+ if(types == null)
+ Init();
+
+ EditorGUILayout.BeginHorizontal();
+
+ EditorGUILayout.BeginVertical(leftPaneStyle);
+ SearchBar();
+ TypeList();
+ EditorGUILayout.EndVertical();
+ EditorGUILayout.BeginVertical();
+ TypePane();
+ EditorGUILayout.EndVertical();
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ private void SearchBar()
+ {
+ var style = EditorStyle.Get;
+
+ GUILayout.Label("Enter a type name in the field below\n* Type names are case-sensitive *", style.subheading2);
+
+ EditorGUILayout.BeginHorizontal();
+
+ // Set control name so we can force a Focus reset for it.
+ string currentSearchFieldValue = EditorGUILayout.TextField(searchFieldValue, searchBarStyle);
+
+ if(searchFieldValue != currentSearchFieldValue)
+ {
+ searchFieldValue = currentSearchFieldValue;
+ PerformSearch(currentSearchFieldValue);
+ }
+
+ GUI.SetNextControlName("Clear");
+
+ if(GUILayout.Button("x", searchBarCancelButtonStyle))
+ {
+ searchFieldValue = "";
+ GUI.FocusControl("Clear");
+ PerformSearch("");
+ }
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ private void RecentTypeList()
+ {
+ if(!string.IsNullOrEmpty(searchFieldValue) || recentTypes.Count == 0)
+ return;
+
+ for(int i=recentTypes.Count-1; i>-1; i--)
+ TypeButton(recentTypes[i]);
+
+ EditorGUILayout.TextArea("",GUI.skin.horizontalSlider);
+
+ }
+
+ private void TypeList()
+ {
+ if(!string.IsNullOrEmpty(searchFieldValue))
+ GUILayout.Label("Search Results", EditorStyles.boldLabel);
+
+ typeListScrollPos = EditorGUILayout.BeginScrollView(typeListScrollPos);
+
+ RecentTypeList();
+
+ if(!string.IsNullOrEmpty(searchFieldValue))
+ for(int i = 0; i < types.Length; i++)
+ TypeButton(i);
+
+ EditorGUILayout.EndScrollView();
+ }
+
+ private void TypePane()
+ {
+ if(selectedType < 0)
+ return;
+
+ var style = EditorStyle.Get;
+
+ var typeListItem = types[selectedType];
+ var type = typeListItem.type;
+
+ typePaneScrollPos = EditorGUILayout.BeginScrollView(typePaneScrollPos, style.area);
+
+ GUILayout.Label(typeListItem.name, style.subheading);
+ GUILayout.Label(typeListItem.namespaceName);
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ bool hasParameterlessConstructor = ES3Reflection.HasParameterlessConstructor(type);
+ bool isComponent = ES3Reflection.IsAssignableFrom(typeof(Component), type);
+
+ string path = GetOutputPath(types[selectedType].type);
+ // An ES3Type file already exists.
+ if(File.Exists(path))
+ {
+ if(hasParameterlessConstructor || isComponent)
+ {
+ EditorGUILayout.BeginHorizontal();
+ if(GUILayout.Button("Reset to Default"))
+ {
+ SelectNone(true, true);
+ AssetDatabase.MoveAssetToTrash("Assets" + path.Remove(0, Application.dataPath.Length));
+ SelectType(selectedType);
+ }
+ if(GUILayout.Button("Edit ES3Type Script"))
+ AssetDatabase.OpenAsset(AssetDatabase.LoadMainAssetAtPath("Assets" + path.Remove(0, Application.dataPath.Length)));
+ EditorGUILayout.EndHorizontal();
+ }
+ else
+ {
+ EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to modify the ES3Type script to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
+ if(GUILayout.Button("Click here to edit the ES3Type script"))
+ AssetDatabase.OpenAsset(AssetDatabase.LoadMainAssetAtPath("Assets" + path.Remove(0, Application.dataPath.Length)));
+ if (GUILayout.Button("Reset to Default"))
+ {
+ SelectAll(true, true);
+ File.Delete(path);
+ AssetDatabase.Refresh();
+ }
+ }
+ }
+ // No ES3Type file and no fields.
+ else if(fields.Length == 0)
+ {
+ if(!hasParameterlessConstructor && !isComponent)
+ EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to create an ES3Type script and modify it to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
+
+ if(GUILayout.Button("Create ES3Type Script"))
+ Generate();
+ }
+ // No ES3Type file, but fields are selectable.
+ else
+ {
+ if(!hasParameterlessConstructor && !isComponent)
+ {
+ EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to select the fields you wish to serialize below, and then modify the generated ES3Type script to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
+ if(GUILayout.Button("Select all fields and generate ES3Type script"))
+ {
+ SelectAll(true, false);
+ Generate();
+ }
+ }
+ else
+ {
+ if(GUILayout.Button("Create ES3Type Script"))
+ Generate();
+ }
+ }
+
+ EditorGUILayout.EndVertical();
+
+ PropertyPane();
+
+ EditorGUILayout.EndScrollView();
+ }
+
+ private void PropertyPane()
+ {
+ var style = EditorStyle.Get;
+
+ EditorGUILayout.BeginVertical(style.area);
+
+ GUILayout.Label("Fields", EditorStyles.boldLabel);
+
+ DisplayFieldsOrProperties(true, false);
+ EditorGUILayout.Space();
+
+ GUILayout.Label("Properties", EditorStyles.boldLabel);
+
+ DisplayFieldsOrProperties(false, true);
+ EditorGUILayout.EndVertical();
+ }
+
+ private void DisplayFieldsOrProperties(bool showFields, bool showProperties)
+ {
+ // Get field and property counts.
+ int fieldCount = 0;
+ int propertyCount = 0;
+ for(int i=0; i 0 || propertyCount > 0)
+ {
+ EditorGUILayout.BeginHorizontal();
+
+ if(GUILayout.Button("Select All", selectAllNoneButtonStyle))
+ {
+ SelectAll(showFields, showProperties);
+ Generate();
+ }
+
+ if(GUILayout.Button("Select None", selectAllNoneButtonStyle))
+ {
+ SelectNone(showFields, showProperties);
+ Generate();
+ }
+ EditorGUILayout.EndHorizontal();
+ }
+
+ for(int i=0; i item.Name == fields[i].Name);
+ return;
+ }
+
+ // Get fields and whether they're selected.
+ var selectedFields = new List();
+ var propertyAttributes = es3Type.GetType().GetCustomAttributes(typeof(ES3PropertiesAttribute), false);
+ if(propertyAttributes.Length > 0)
+ selectedFields.AddRange(((ES3PropertiesAttribute)propertyAttributes[0]).members);
+
+ fieldSelected = new bool[fields.Length];
+
+ for(int i=0; i ();
+
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(assembly => !assembly.FullName.Contains("Editor") && assembly.FullName != "ES3" && !assembly.FullName.Contains("ES3")).OrderBy(assembly => assembly.GetName().Name).ToArray();
+
+ foreach (var assembly in assemblies)
+ {
+ var assemblyTypes = assembly.GetTypes();
+
+ for(int i = 0; i < assemblyTypes.Length; i++)
+ {
+ var type = assemblyTypes [i];
+ if(type.IsGenericType || type.IsEnum || type.IsNotPublic || type.IsAbstract || type.IsInterface)
+ continue;
+
+ var typeName = type.Name;
+ if(typeName.Length >= 3 && typeName [0] == '$' || typeName [0] == '_' || typeName [0] == '<')
+ continue;
+
+ var typeNamespace = type.Namespace;
+ var namespaceName = typeNamespace == null ? "" : typeNamespace.ToString();
+
+ tempTypes.Add(new TypeListItem (type.Name, namespaceName, type, true, HasExplicitES3Type(type)));
+ }
+
+ }
+ types = tempTypes.OrderBy(type => type.name).ToArray();
+
+ // Load types and recent types.
+ if (recentTypes == null)
+ {
+ recentTypes = new List();
+ for (int i = 0; i < recentTypeCount; i++)
+ {
+ int typeIndex = LoadTypeIndex("TypesWindowRecentType" + i);
+ if (typeIndex != -1)
+ recentTypes.Add(typeIndex);
+ }
+ SelectType(LoadTypeIndex("TypesWindowSelectedType"));
+ }
+
+
+ PerformSearch(searchFieldValue);
+
+ // Init Assets.
+ string es3FolderPath = ES3Settings.PathToEasySaveFolder();
+ checkmark = AssetDatabase.LoadAssetAtPath(es3FolderPath + "Editor/checkmark.png");
+ //checkmarkSmall = AssetDatabase.LoadAssetAtPath